41438 lines
1.6 MiB
41438 lines
1.6 MiB
--- contrib/sqlite3/Makefile.msc.orig
|
|
+++ contrib/sqlite3/Makefile.msc
|
|
@@ -73,7 +73,7 @@
|
|
!IFNDEF NO_WARN
|
|
!IF $(USE_FULLWARN)!=0
|
|
NO_WARN = -wd4054 -wd4055 -wd4100 -wd4127 -wd4130 -wd4152 -wd4189 -wd4206
|
|
-NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4305 -wd4306 -wd4702 -wd4706
|
|
+NO_WARN = $(NO_WARN) -wd4210 -wd4232 -wd4244 -wd4305 -wd4306 -wd4702 -wd4706
|
|
!ENDIF
|
|
!ENDIF
|
|
|
|
@@ -196,6 +196,7 @@
|
|
DEBUG = 0
|
|
!ENDIF
|
|
|
|
+
|
|
# Enable use of available compiler optimizations? Normally, this should be
|
|
# non-zero. Setting this to zero, thus disabling all compiler optimizations,
|
|
# can be useful for testing.
|
|
@@ -210,6 +211,12 @@
|
|
SESSION = 0
|
|
!ENDIF
|
|
|
|
+# Set this to non-0 to enable support for the rbu extension.
|
|
+#
|
|
+!IFNDEF RBU
|
|
+RBU = 0
|
|
+!ENDIF
|
|
+
|
|
# Set the source code file to be used by executables and libraries when
|
|
# they need the amalgamation.
|
|
#
|
|
@@ -282,7 +289,7 @@
|
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
|
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
|
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
|
|
-OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
|
|
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_BYTECODE_VTAB=1
|
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
|
|
!ENDIF
|
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
|
@@ -296,6 +303,13 @@
|
|
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK=1
|
|
!ENDIF
|
|
|
|
+# Should the rbu extension be enabled? If so, add compilation options
|
|
+# to enable it.
|
|
+#
|
|
+!IF $(RBU)!=0
|
|
+OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RBU=1
|
|
+!ENDIF
|
|
+
|
|
# These are the "extended" SQLite compilation options used when compiling for
|
|
# the Windows 10 platform.
|
|
#
|
|
@@ -978,7 +992,7 @@
|
|
sqlite3.def: Replace.exe $(LIBOBJ)
|
|
echo EXPORTS > sqlite3.def
|
|
dumpbin /all $(LIBOBJ) \
|
|
- | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
|
+ | .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup|rebaser|rbu)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
|
|
| sort >> sqlite3.def
|
|
|
|
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
|
|
--- contrib/sqlite3/configure.orig
|
|
+++ contrib/sqlite3/configure
|
|
@@ -1,6 +1,6 @@
|
|
#! /bin/sh
|
|
# Guess values for system-dependent variables and create Makefiles.
|
|
-# Generated by GNU Autoconf 2.69 for sqlite 3.29.0.
|
|
+# Generated by GNU Autoconf 2.69 for sqlite 3.32.2.
|
|
#
|
|
# Report bugs to <http://www.sqlite.org>.
|
|
#
|
|
@@ -590,8 +590,8 @@
|
|
# Identity of this package.
|
|
PACKAGE_NAME='sqlite'
|
|
PACKAGE_TARNAME='sqlite'
|
|
-PACKAGE_VERSION='3.29.0'
|
|
-PACKAGE_STRING='sqlite 3.29.0'
|
|
+PACKAGE_VERSION='3.32.2'
|
|
+PACKAGE_STRING='sqlite 3.32.2'
|
|
PACKAGE_BUGREPORT='http://www.sqlite.org'
|
|
PACKAGE_URL=''
|
|
|
|
@@ -1341,7 +1341,7 @@
|
|
# Omit some internal or obsolete options to make the list less imposing.
|
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
|
cat <<_ACEOF
|
|
-\`configure' configures sqlite 3.29.0 to adapt to many kinds of systems.
|
|
+\`configure' configures sqlite 3.32.2 to adapt to many kinds of systems.
|
|
|
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
|
|
|
@@ -1412,7 +1412,7 @@
|
|
|
|
if test -n "$ac_init_help"; then
|
|
case $ac_init_help in
|
|
- short | recursive ) echo "Configuration of sqlite 3.29.0:";;
|
|
+ short | recursive ) echo "Configuration of sqlite 3.32.2:";;
|
|
esac
|
|
cat <<\_ACEOF
|
|
|
|
@@ -1537,7 +1537,7 @@
|
|
test -n "$ac_init_help" && exit $ac_status
|
|
if $ac_init_version; then
|
|
cat <<\_ACEOF
|
|
-sqlite configure 3.29.0
|
|
+sqlite configure 3.32.2
|
|
generated by GNU Autoconf 2.69
|
|
|
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
|
@@ -1952,7 +1952,7 @@
|
|
This file contains any messages produced by compilers while
|
|
running configure, to aid debugging if configure makes a mistake.
|
|
|
|
-It was created by sqlite $as_me 3.29.0, which was
|
|
+It was created by sqlite $as_me 3.32.2, which was
|
|
generated by GNU Autoconf 2.69. Invocation command line was
|
|
|
|
$ $0 $@
|
|
@@ -2818,7 +2818,7 @@
|
|
|
|
# Define the identity of the package.
|
|
PACKAGE='sqlite'
|
|
- VERSION='3.29.0'
|
|
+ VERSION='3.32.2'
|
|
|
|
|
|
cat >>confdefs.h <<_ACEOF
|
|
@@ -13653,7 +13653,7 @@
|
|
fi
|
|
|
|
if test x"$enable_rtree" = "xyes"; then
|
|
- BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE"
|
|
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
|
|
fi
|
|
#-----------------------------------------------------------------------
|
|
|
|
@@ -14438,7 +14438,7 @@
|
|
# report actual input values of CONFIG_FILES etc. instead of their
|
|
# values after options handling.
|
|
ac_log="
|
|
-This file was extended by sqlite $as_me 3.29.0, which was
|
|
+This file was extended by sqlite $as_me 3.32.2, which was
|
|
generated by GNU Autoconf 2.69. Invocation command line was
|
|
|
|
CONFIG_FILES = $CONFIG_FILES
|
|
@@ -14495,7 +14495,7 @@
|
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
|
ac_cs_version="\\
|
|
-sqlite config.status 3.29.0
|
|
+sqlite config.status 3.32.2
|
|
configured by $0, generated by GNU Autoconf 2.69,
|
|
with options \\"\$ac_cs_config\\"
|
|
|
|
--- contrib/sqlite3/configure.ac.orig
|
|
+++ contrib/sqlite3/configure.ac
|
|
@@ -10,7 +10,7 @@
|
|
#
|
|
|
|
AC_PREREQ(2.61)
|
|
-AC_INIT(sqlite, 3.29.0, http://www.sqlite.org)
|
|
+AC_INIT(sqlite, 3.32.2, http://www.sqlite.org)
|
|
AC_CONFIG_SRCDIR([sqlite3.c])
|
|
AC_CONFIG_AUX_DIR([.])
|
|
|
|
@@ -161,7 +161,7 @@
|
|
[--enable-rtree], [include rtree support [default=yes]])],
|
|
[], [enable_rtree=yes])
|
|
if test x"$enable_rtree" = "xyes"; then
|
|
- BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE"
|
|
+ BUILD_CFLAGS="$BUILD_CFLAGS -DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_GEOPOLY"
|
|
fi
|
|
#-----------------------------------------------------------------------
|
|
|
|
--- contrib/sqlite3/shell.c.orig
|
|
+++ contrib/sqlite3/shell.c
|
|
@@ -35,6 +35,14 @@
|
|
#define _CRT_SECURE_NO_WARNINGS
|
|
#endif
|
|
|
|
+/*
|
|
+** Determine if we are dealing with WinRT, which provides only a subset of
|
|
+** the full Win32 API.
|
|
+*/
|
|
+#if !defined(SQLITE_OS_WINRT)
|
|
+# define SQLITE_OS_WINRT 0
|
|
+#endif
|
|
+
|
|
/*
|
|
** Warning pragmas copied from msvc.h in the core.
|
|
*/
|
|
@@ -147,22 +155,26 @@
|
|
|
|
|
|
#if defined(_WIN32) || defined(WIN32)
|
|
-# include <io.h>
|
|
-# include <fcntl.h>
|
|
-# define isatty(h) _isatty(h)
|
|
-# ifndef access
|
|
-# define access(f,m) _access((f),(m))
|
|
-# endif
|
|
-# ifndef unlink
|
|
-# define unlink _unlink
|
|
-# endif
|
|
-# ifndef strdup
|
|
-# define strdup _strdup
|
|
+# if SQLITE_OS_WINRT
|
|
+# define SQLITE_OMIT_POPEN 1
|
|
+# else
|
|
+# include <io.h>
|
|
+# include <fcntl.h>
|
|
+# define isatty(h) _isatty(h)
|
|
+# ifndef access
|
|
+# define access(f,m) _access((f),(m))
|
|
+# endif
|
|
+# ifndef unlink
|
|
+# define unlink _unlink
|
|
+# endif
|
|
+# ifndef strdup
|
|
+# define strdup _strdup
|
|
+# endif
|
|
+# undef popen
|
|
+# define popen _popen
|
|
+# undef pclose
|
|
+# define pclose _pclose
|
|
# endif
|
|
-# undef popen
|
|
-# define popen _popen
|
|
-# undef pclose
|
|
-# define pclose _pclose
|
|
#else
|
|
/* Make sure isatty() has a prototype. */
|
|
extern int isatty(int);
|
|
@@ -191,6 +203,9 @@
|
|
#define ToLower(X) (char)tolower((unsigned char)X)
|
|
|
|
#if defined(_WIN32) || defined(WIN32)
|
|
+#if SQLITE_OS_WINRT
|
|
+#include <intrin.h>
|
|
+#endif
|
|
#include <windows.h>
|
|
|
|
/* string conversion routines only needed on Win32 */
|
|
@@ -206,7 +221,7 @@
|
|
** rendering quoted strings that contain \n characters). The following
|
|
** routines take care of that.
|
|
*/
|
|
-#if defined(_WIN32) || defined(WIN32)
|
|
+#if (defined(_WIN32) || defined(WIN32)) && !SQLITE_OS_WINRT
|
|
static void setBinaryMode(FILE *file, int isOutput){
|
|
if( isOutput ) fflush(file);
|
|
_setmode(_fileno(file), _O_BINARY);
|
|
@@ -310,6 +325,7 @@
|
|
if( getProcessTimesAddr ){
|
|
return 1;
|
|
} else {
|
|
+#if !SQLITE_OS_WINRT
|
|
/* GetProcessTimes() isn't supported in WIN95 and some other Windows
|
|
** versions. See if the version we are running on has it, and if it
|
|
** does, save off a pointer to it and the current process handle.
|
|
@@ -326,6 +342,7 @@
|
|
FreeLibrary(hinstLib);
|
|
}
|
|
}
|
|
+#endif
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -415,6 +432,15 @@
|
|
*/
|
|
static volatile int seenInterrupt = 0;
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+/*
|
|
+** Out-of-memory simulator variables
|
|
+*/
|
|
+static unsigned int oomCounter = 0; /* Simulate OOM when equals 1 */
|
|
+static unsigned int oomRepeat = 0; /* Number of OOMs in a row */
|
|
+static void*(*defaultMalloc)(int) = 0; /* The low-level malloc routine */
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
/*
|
|
** This is the name of our program. It is set in main(), used
|
|
** in a number of other places, mostly for error messages.
|
|
@@ -466,6 +492,49 @@
|
|
exit(1);
|
|
}
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+/* This routine is called when a simulated OOM occurs. It is broken
|
|
+** out as a separate routine to make it easy to set a breakpoint on
|
|
+** the OOM
|
|
+*/
|
|
+void shellOomFault(void){
|
|
+ if( oomRepeat>0 ){
|
|
+ oomRepeat--;
|
|
+ }else{
|
|
+ oomCounter--;
|
|
+ }
|
|
+}
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
+#ifdef SQLITE_DEBUG
|
|
+/* This routine is a replacement malloc() that is used to simulate
|
|
+** Out-Of-Memory (OOM) errors for testing purposes.
|
|
+*/
|
|
+static void *oomMalloc(int nByte){
|
|
+ if( oomCounter ){
|
|
+ if( oomCounter==1 ){
|
|
+ shellOomFault();
|
|
+ return 0;
|
|
+ }else{
|
|
+ oomCounter--;
|
|
+ }
|
|
+ }
|
|
+ return defaultMalloc(nByte);
|
|
+}
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
+#ifdef SQLITE_DEBUG
|
|
+/* Register the OOM simulator. This must occur before any memory
|
|
+** allocations */
|
|
+static void registerOomSimulator(void){
|
|
+ sqlite3_mem_methods mem;
|
|
+ sqlite3_config(SQLITE_CONFIG_GETMALLOC, &mem);
|
|
+ defaultMalloc = mem.xMalloc;
|
|
+ mem.xMalloc = oomMalloc;
|
|
+ sqlite3_config(SQLITE_CONFIG_MALLOC, &mem);
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
** Write I/O traces to the following stream.
|
|
*/
|
|
@@ -2007,19 +2076,23 @@
|
|
int rc = SQLITE_OK;
|
|
SQLITE_EXTENSION_INIT2(pApi);
|
|
(void)pzErrMsg; /* Unused parameter */
|
|
- rc = sqlite3_create_function(db, "sha3", 1, SQLITE_UTF8, 0,
|
|
- sha3Func, 0, 0);
|
|
+ rc = sqlite3_create_function(db, "sha3", 1,
|
|
+ SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
|
|
+ 0, sha3Func, 0, 0);
|
|
if( rc==SQLITE_OK ){
|
|
- rc = sqlite3_create_function(db, "sha3", 2, SQLITE_UTF8, 0,
|
|
- sha3Func, 0, 0);
|
|
+ rc = sqlite3_create_function(db, "sha3", 2,
|
|
+ SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC,
|
|
+ 0, sha3Func, 0, 0);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
- rc = sqlite3_create_function(db, "sha3_query", 1, SQLITE_UTF8, 0,
|
|
- sha3QueryFunc, 0, 0);
|
|
+ rc = sqlite3_create_function(db, "sha3_query", 1,
|
|
+ SQLITE_UTF8 | SQLITE_DIRECTONLY,
|
|
+ 0, sha3QueryFunc, 0, 0);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
- rc = sqlite3_create_function(db, "sha3_query", 2, SQLITE_UTF8, 0,
|
|
- sha3QueryFunc, 0, 0);
|
|
+ rc = sqlite3_create_function(db, "sha3_query", 2,
|
|
+ SQLITE_UTF8 | SQLITE_DIRECTONLY,
|
|
+ 0, sha3QueryFunc, 0, 0);
|
|
}
|
|
return rc;
|
|
}
|
|
@@ -2422,6 +2495,7 @@
|
|
|
|
if( mtime>=0 ){
|
|
#if defined(_WIN32)
|
|
+#if !SQLITE_OS_WINRT
|
|
/* Windows */
|
|
FILETIME lastAccess;
|
|
FILETIME lastWrite;
|
|
@@ -2452,6 +2526,7 @@
|
|
}else{
|
|
return 1;
|
|
}
|
|
+#endif
|
|
#elif defined(AT_FDCWD) && 0 /* utimensat() is not universally available */
|
|
/* Recent unix */
|
|
struct timespec times[2];
|
|
@@ -2613,6 +2688,7 @@
|
|
pNew = (fsdir_tab*)sqlite3_malloc( sizeof(*pNew) );
|
|
if( pNew==0 ) return SQLITE_NOMEM;
|
|
memset(pNew, 0, sizeof(*pNew));
|
|
+ sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
|
|
}
|
|
*ppVtab = (sqlite3_vtab*)pNew;
|
|
return rc;
|
|
@@ -3006,10 +3082,12 @@
|
|
int rc = SQLITE_OK;
|
|
SQLITE_EXTENSION_INIT2(pApi);
|
|
(void)pzErrMsg; /* Unused parameter */
|
|
- rc = sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
|
|
+ rc = sqlite3_create_function(db, "readfile", 1,
|
|
+ SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
|
|
readfileFunc, 0, 0);
|
|
if( rc==SQLITE_OK ){
|
|
- rc = sqlite3_create_function(db, "writefile", -1, SQLITE_UTF8, 0,
|
|
+ rc = sqlite3_create_function(db, "writefile", -1,
|
|
+ SQLITE_UTF8|SQLITE_DIRECTONLY, 0,
|
|
writefileFunc, 0, 0);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
@@ -3144,6 +3222,7 @@
|
|
#define COMPLETION_COLUMN_WHOLELINE 2 /* Entire line seen so far */
|
|
#define COMPLETION_COLUMN_PHASE 3 /* ePhase - used for debugging only */
|
|
|
|
+ sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
|
rc = sqlite3_declare_vtab(db,
|
|
"CREATE TABLE x("
|
|
" candidate TEXT,"
|
|
@@ -4205,6 +4284,101 @@
|
|
}
|
|
|
|
/************************* End ../ext/misc/memtrace.c ********************/
|
|
+/************************* Begin ../ext/misc/uint.c ******************/
|
|
+/*
|
|
+** 2020-04-14
|
|
+**
|
|
+** The author disclaims copyright to this source code. In place of
|
|
+** a legal notice, here is a blessing:
|
|
+**
|
|
+** May you do good and not evil.
|
|
+** May you find forgiveness for yourself and forgive others.
|
|
+** May you share freely, never taking more than you give.
|
|
+**
|
|
+******************************************************************************
|
|
+**
|
|
+** This SQLite extension implements the UINT collating sequence.
|
|
+**
|
|
+** UINT works like BINARY for text, except that embedded strings
|
|
+** of digits compare in numeric order.
|
|
+**
|
|
+** * Leading zeros are handled properly, in the sense that
|
|
+** they do not mess of the maginitude comparison of embedded
|
|
+** strings of digits. "x00123y" is equal to "x123y".
|
|
+**
|
|
+** * Only unsigned integers are recognized. Plus and minus
|
|
+** signs are ignored. Decimal points and exponential notation
|
|
+** are ignored.
|
|
+**
|
|
+** * Embedded integers can be of arbitrary length. Comparison
|
|
+** is *not* limited integers that can be expressed as a
|
|
+** 64-bit machine integer.
|
|
+*/
|
|
+/* #include "sqlite3ext.h" */
|
|
+SQLITE_EXTENSION_INIT1
|
|
+#include <assert.h>
|
|
+#include <string.h>
|
|
+#include <ctype.h>
|
|
+
|
|
+/*
|
|
+** Compare text in lexicographic order, except strings of digits
|
|
+** compare in numeric order.
|
|
+*/
|
|
+static int uintCollFunc(
|
|
+ void *notUsed,
|
|
+ int nKey1, const void *pKey1,
|
|
+ int nKey2, const void *pKey2
|
|
+){
|
|
+ const unsigned char *zA = (const unsigned char*)pKey1;
|
|
+ const unsigned char *zB = (const unsigned char*)pKey2;
|
|
+ int i=0, j=0, x;
|
|
+ (void)notUsed;
|
|
+ while( i<nKey1 && j<nKey2 ){
|
|
+ x = zA[i] - zB[j];
|
|
+ if( isdigit(zA[i]) ){
|
|
+ int k;
|
|
+ if( !isdigit(zB[j]) ) return x;
|
|
+ while( i<nKey1 && zA[i]=='0' ){ i++; }
|
|
+ while( j<nKey2 && zB[j]=='0' ){ j++; }
|
|
+ k = 0;
|
|
+ while( i+k<nKey1 && isdigit(zA[i+k])
|
|
+ && j+k<nKey2 && isdigit(zB[j+k]) ){
|
|
+ k++;
|
|
+ }
|
|
+ if( i+k<nKey1 && isdigit(zA[i+k]) ){
|
|
+ return +1;
|
|
+ }else if( j+k<nKey2 && isdigit(zB[j+k]) ){
|
|
+ return -1;
|
|
+ }else{
|
|
+ x = memcmp(zA+i, zB+j, k);
|
|
+ if( x ) return x;
|
|
+ i += k;
|
|
+ j += k;
|
|
+ }
|
|
+ }else if( x ){
|
|
+ return x;
|
|
+ }else{
|
|
+ i++;
|
|
+ j++;
|
|
+ }
|
|
+ }
|
|
+ return (nKey1 - i) - (nKey2 - j);
|
|
+}
|
|
+
|
|
+#ifdef _WIN32
|
|
+
|
|
+#endif
|
|
+int sqlite3_uint_init(
|
|
+ sqlite3 *db,
|
|
+ char **pzErrMsg,
|
|
+ const sqlite3_api_routines *pApi
|
|
+){
|
|
+ SQLITE_EXTENSION_INIT2(pApi);
|
|
+ (void)pzErrMsg; /* Unused parameter */
|
|
+ return sqlite3_create_collation(db, "uint", SQLITE_UTF8, 0, uintCollFunc);
|
|
+}
|
|
+
|
|
+/************************* End ../ext/misc/uint.c ********************/
|
|
#ifdef SQLITE_HAVE_ZLIB
|
|
/************************* Begin ../ext/misc/zipfile.c ******************/
|
|
/*
|
|
@@ -4578,6 +4752,7 @@
|
|
zipfileDequote(pNew->zFile);
|
|
}
|
|
}
|
|
+ sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
|
|
*ppVtab = (sqlite3_vtab*)pNew;
|
|
return rc;
|
|
}
|
|
@@ -5190,25 +5365,25 @@
|
|
u8 **ppOut, int *pnOut, /* Output */
|
|
char **pzErr /* OUT: Error message */
|
|
){
|
|
- sqlite3_int64 nAlloc = compressBound(nIn);
|
|
- u8 *aOut;
|
|
int rc = SQLITE_OK;
|
|
+ sqlite3_int64 nAlloc;
|
|
+ z_stream str;
|
|
+ u8 *aOut;
|
|
+
|
|
+ memset(&str, 0, sizeof(str));
|
|
+ str.next_in = (Bytef*)aIn;
|
|
+ str.avail_in = nIn;
|
|
+ deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
|
|
|
|
+ nAlloc = deflateBound(&str, nIn);
|
|
aOut = (u8*)sqlite3_malloc64(nAlloc);
|
|
if( aOut==0 ){
|
|
rc = SQLITE_NOMEM;
|
|
}else{
|
|
int res;
|
|
- z_stream str;
|
|
- memset(&str, 0, sizeof(str));
|
|
- str.next_in = (Bytef*)aIn;
|
|
- str.avail_in = nIn;
|
|
str.next_out = aOut;
|
|
str.avail_out = nAlloc;
|
|
-
|
|
- deflateInit2(&str, 9, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
|
|
res = deflate(&str, Z_FINISH);
|
|
-
|
|
if( res==Z_STREAM_END ){
|
|
*ppOut = aOut;
|
|
*pnOut = (int)str.total_out;
|
|
@@ -5517,10 +5692,10 @@
|
|
idx = i;
|
|
}
|
|
}
|
|
+ pIdxInfo->estimatedCost = 1000.0;
|
|
if( idx>=0 ){
|
|
pIdxInfo->aConstraintUsage[idx].argvIndex = 1;
|
|
pIdxInfo->aConstraintUsage[idx].omit = 1;
|
|
- pIdxInfo->estimatedCost = 1000.0;
|
|
pIdxInfo->idxNum = 1;
|
|
}else if( unusable ){
|
|
return SQLITE_CONSTRAINT;
|
|
@@ -5642,8 +5817,8 @@
|
|
** identical, ignoring any trailing '/' character in either path. */
|
|
static int zipfileComparePath(const char *zA, const char *zB, int nB){
|
|
int nA = (int)strlen(zA);
|
|
- if( zA[nA-1]=='/' ) nA--;
|
|
- if( zB[nB-1]=='/' ) nB--;
|
|
+ if( nA>0 && zA[nA-1]=='/' ) nA--;
|
|
+ if( nB>0 && zB[nB-1]=='/' ) nB--;
|
|
if( nA==nB && memcmp(zA, zB, nA)==0 ) return 0;
|
|
return 1;
|
|
}
|
|
@@ -5653,6 +5828,10 @@
|
|
int rc = SQLITE_OK;
|
|
|
|
assert( pTab->pWriteFd==0 );
|
|
+ if( pTab->zFile==0 || pTab->zFile[0]==0 ){
|
|
+ pTab->base.zErrMsg = sqlite3_mprintf("zipfile: missing filename");
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
|
|
/* Open a write fd on the file. Also load the entire central directory
|
|
** structure into memory. During the transaction any new file data is
|
|
@@ -5827,6 +6006,7 @@
|
|
|
|
if( rc==SQLITE_OK ){
|
|
zPath = (const char*)sqlite3_value_text(apVal[2]);
|
|
+ if( zPath==0 ) zPath = "";
|
|
nPath = (int)strlen(zPath);
|
|
mTime = zipfileGetTime(apVal[4]);
|
|
}
|
|
@@ -5836,11 +6016,15 @@
|
|
** '/'. This appears to be required for compatibility with info-zip
|
|
** (the unzip command on unix). It does not create directories
|
|
** otherwise. */
|
|
- if( zPath[nPath-1]!='/' ){
|
|
+ if( nPath<=0 || zPath[nPath-1]!='/' ){
|
|
zFree = sqlite3_mprintf("%s/", zPath);
|
|
- if( zFree==0 ){ rc = SQLITE_NOMEM; }
|
|
zPath = (const char*)zFree;
|
|
- nPath++;
|
|
+ if( zFree==0 ){
|
|
+ rc = SQLITE_NOMEM;
|
|
+ nPath = 0;
|
|
+ }else{
|
|
+ nPath = (int)strlen(zPath);
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -6233,19 +6417,19 @@
|
|
** at the end of the path. Or, if this is not a directory and the path
|
|
** ends in '/' it is an error. */
|
|
if( bIsDir==0 ){
|
|
- if( zName[nName-1]=='/' ){
|
|
+ if( nName>0 && zName[nName-1]=='/' ){
|
|
zErr = sqlite3_mprintf("non-directory name must not end with /");
|
|
rc = SQLITE_ERROR;
|
|
goto zipfile_step_out;
|
|
}
|
|
}else{
|
|
- if( zName[nName-1]!='/' ){
|
|
+ if( nName==0 || zName[nName-1]!='/' ){
|
|
zName = zFree = sqlite3_mprintf("%s/", zName);
|
|
- nName++;
|
|
if( zName==0 ){
|
|
rc = SQLITE_NOMEM;
|
|
goto zipfile_step_out;
|
|
}
|
|
+ nName = (int)strlen(zName);
|
|
}else{
|
|
while( nName>1 && zName[nName-2]=='/' ) nName--;
|
|
}
|
|
@@ -6407,6 +6591,7 @@
|
|
/* #include "sqlite3ext.h" */
|
|
SQLITE_EXTENSION_INIT1
|
|
#include <zlib.h>
|
|
+#include <assert.h>
|
|
|
|
/*
|
|
** Implementation of the "sqlar_compress(X)" SQL function.
|
|
@@ -6501,10 +6686,12 @@
|
|
int rc = SQLITE_OK;
|
|
SQLITE_EXTENSION_INIT2(pApi);
|
|
(void)pzErrMsg; /* Unused parameter */
|
|
- rc = sqlite3_create_function(db, "sqlar_compress", 1, SQLITE_UTF8, 0,
|
|
+ rc = sqlite3_create_function(db, "sqlar_compress", 1,
|
|
+ SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
|
sqlarCompressFunc, 0, 0);
|
|
if( rc==SQLITE_OK ){
|
|
- rc = sqlite3_create_function(db, "sqlar_uncompress", 2, SQLITE_UTF8, 0,
|
|
+ rc = sqlite3_create_function(db, "sqlar_uncompress", 2,
|
|
+ SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
|
|
sqlarUncompressFunc, 0, 0);
|
|
}
|
|
return rc;
|
|
@@ -6525,8 +6712,8 @@
|
|
**
|
|
*************************************************************************
|
|
*/
|
|
-
|
|
-
|
|
+#if !defined(SQLITEEXPERT_H)
|
|
+#define SQLITEEXPERT_H 1
|
|
/* #include "sqlite3.h" */
|
|
|
|
typedef struct sqlite3expert sqlite3expert;
|
|
@@ -6680,7 +6867,7 @@
|
|
*/
|
|
void sqlite3_expert_destroy(sqlite3expert*);
|
|
|
|
-
|
|
+#endif /* !defined(SQLITEEXPERT_H) */
|
|
|
|
/************************* End ../ext/expert/sqlite3expert.h ********************/
|
|
/************************* Begin ../ext/expert/sqlite3expert.c ******************/
|
|
@@ -7814,14 +8001,19 @@
|
|
/* int iParent = sqlite3_column_int(pExplain, 1); */
|
|
/* int iNotUsed = sqlite3_column_int(pExplain, 2); */
|
|
const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
|
|
- int nDetail = STRLEN(zDetail);
|
|
+ int nDetail;
|
|
int i;
|
|
|
|
+ if( !zDetail ) continue;
|
|
+ nDetail = STRLEN(zDetail);
|
|
+
|
|
for(i=0; i<nDetail; i++){
|
|
const char *zIdx = 0;
|
|
- if( memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
|
|
+ if( i+13<nDetail && memcmp(&zDetail[i], " USING INDEX ", 13)==0 ){
|
|
zIdx = &zDetail[i+13];
|
|
- }else if( memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0 ){
|
|
+ }else if( i+22<nDetail
|
|
+ && memcmp(&zDetail[i], " USING COVERING INDEX ", 22)==0
|
|
+ ){
|
|
zIdx = &zDetail[i+22];
|
|
}
|
|
if( zIdx ){
|
|
@@ -8636,7 +8828,7 @@
|
|
}
|
|
}
|
|
|
|
-#endif /* ifndef SQLITE_OMIT_VIRTUAL_TABLE */
|
|
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
|
|
|
/************************* End ../ext/expert/sqlite3expert.c ********************/
|
|
|
|
@@ -9566,6 +9758,7 @@
|
|
int outCount; /* Revert to stdout when reaching zero */
|
|
int cnt; /* Number of records displayed so far */
|
|
int lineno; /* Line number of last line read from in */
|
|
+ int openFlags; /* Additional flags to open. (SQLITE_OPEN_NOFOLLOW) */
|
|
FILE *in; /* Read commands from this stream */
|
|
FILE *out; /* Write results here */
|
|
FILE *traceOut; /* Output for sqlite3_trace() */
|
|
@@ -9581,6 +9774,7 @@
|
|
unsigned mxProgress; /* Maximum progress callbacks before failing */
|
|
unsigned flgProgress; /* Flags for the progress callback */
|
|
unsigned shellFlgs; /* Various flags */
|
|
+ unsigned priorShFlgs; /* Saved copy of flags */
|
|
sqlite3_int64 szMax; /* --maxsize argument to .open */
|
|
char *zDestTable; /* Name of destination table when MODE_Insert */
|
|
char *zTempFile; /* Temporary file that might need deleting */
|
|
@@ -9801,12 +9995,12 @@
|
|
}
|
|
sz = sqlite3_value_bytes(argv[0]);
|
|
if( bBin ){
|
|
- x = fwrite(sqlite3_value_blob(argv[0]), 1, sz, f);
|
|
+ x = fwrite(sqlite3_value_blob(argv[0]), 1, (size_t)sz, f);
|
|
}else{
|
|
const char *z = (const char*)sqlite3_value_text(argv[0]);
|
|
/* Remember whether or not the value originally contained \r\n */
|
|
if( z && strstr(z,"\r\n")!=0 ) hasCRNL = 1;
|
|
- x = fwrite(sqlite3_value_text(argv[0]), 1, sz, f);
|
|
+ x = fwrite(sqlite3_value_text(argv[0]), 1, (size_t)sz, f);
|
|
}
|
|
fclose(f);
|
|
f = 0;
|
|
@@ -9834,12 +10028,12 @@
|
|
fseek(f, 0, SEEK_END);
|
|
sz = ftell(f);
|
|
rewind(f);
|
|
- p = sqlite3_malloc64( sz+(bBin==0) );
|
|
+ p = sqlite3_malloc64( sz+1 );
|
|
if( p==0 ){
|
|
sqlite3_result_error_nomem(context);
|
|
goto edit_func_end;
|
|
}
|
|
- x = fread(p, 1, sz, f);
|
|
+ x = fread(p, 1, (size_t)sz, f);
|
|
fclose(f);
|
|
f = 0;
|
|
if( x!=sz ){
|
|
@@ -9881,11 +10075,13 @@
|
|
*/
|
|
static void outputModePush(ShellState *p){
|
|
p->modePrior = p->mode;
|
|
+ p->priorShFlgs = p->shellFlgs;
|
|
memcpy(p->colSepPrior, p->colSeparator, sizeof(p->colSeparator));
|
|
memcpy(p->rowSepPrior, p->rowSeparator, sizeof(p->rowSeparator));
|
|
}
|
|
static void outputModePop(ShellState *p){
|
|
p->mode = p->modePrior;
|
|
+ p->shellFlgs = p->priorShFlgs;
|
|
memcpy(p->colSeparator, p->colSepPrior, sizeof(p->colSeparator));
|
|
memcpy(p->rowSeparator, p->rowSepPrior, sizeof(p->rowSeparator));
|
|
}
|
|
@@ -10311,7 +10507,8 @@
|
|
for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
|
|
pNext = eqp_next_row(p, iEqpId, pRow);
|
|
z = pRow->zText;
|
|
- utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);
|
|
+ utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
|
|
+ pNext ? "|--" : "`--", z);
|
|
if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
|
|
memcpy(&p->sGraph.zPrefix[n], pNext ? "| " : " ", 4);
|
|
eqp_render_level(p, pRow->iEqpId);
|
|
@@ -10399,19 +10596,22 @@
|
|
const int *colWidth;
|
|
int showHdr;
|
|
char *rowSep;
|
|
+ int nWidth;
|
|
if( p->cMode==MODE_Column ){
|
|
colWidth = p->colWidth;
|
|
+ nWidth = ArraySize(p->colWidth);
|
|
showHdr = p->showHeader;
|
|
rowSep = p->rowSeparator;
|
|
}else{
|
|
colWidth = aExplainWidths;
|
|
+ nWidth = ArraySize(aExplainWidths);
|
|
showHdr = 1;
|
|
rowSep = SEP_Row;
|
|
}
|
|
if( p->cnt++==0 ){
|
|
for(i=0; i<nArg; i++){
|
|
int w, n;
|
|
- if( i<ArraySize(p->colWidth) ){
|
|
+ if( i<nWidth ){
|
|
w = colWidth[i];
|
|
}else{
|
|
w = 0;
|
|
@@ -10502,7 +10702,7 @@
|
|
while( j>0 && IsSpace(z[j-1]) ){ j--; }
|
|
z[j] = 0;
|
|
if( strlen30(z)>=79 ){
|
|
- for(i=j=0; (c = z[i])!=0; i++){ /* Copy changes from z[i] back to z[j] */
|
|
+ for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
|
|
if( c==cEnd ){
|
|
cEnd = 0;
|
|
}else if( c=='"' || c=='\'' || c=='`' ){
|
|
@@ -10846,8 +11046,7 @@
|
|
*/
|
|
static int run_table_dump_query(
|
|
ShellState *p, /* Query context */
|
|
- const char *zSelect, /* SELECT statement to extract content */
|
|
- const char *zFirstRow /* Print before first row, if not NULL */
|
|
+ const char *zSelect /* SELECT statement to extract content */
|
|
){
|
|
sqlite3_stmt *pSelect;
|
|
int rc;
|
|
@@ -10864,10 +11063,6 @@
|
|
rc = sqlite3_step(pSelect);
|
|
nResult = sqlite3_column_count(pSelect);
|
|
while( rc==SQLITE_ROW ){
|
|
- if( zFirstRow ){
|
|
- utf8_printf(p->out, "%s", zFirstRow);
|
|
- zFirstRow = 0;
|
|
- }
|
|
z = (const char*)sqlite3_column_text(pSelect, 0);
|
|
utf8_printf(p->out, "%s", z);
|
|
for(i=1; i<nResult; i++){
|
|
@@ -11081,7 +11276,7 @@
|
|
raw_printf(pArg->out, "Autoindex Inserts: %d\n", iCur);
|
|
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
|
|
raw_printf(pArg->out, "Virtual Machine Steps: %d\n", iCur);
|
|
- iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
|
|
+ iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
|
|
raw_printf(pArg->out, "Reprepare operations: %d\n", iCur);
|
|
iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
|
|
raw_printf(pArg->out, "Number of times run: %d\n", iCur);
|
|
@@ -11301,6 +11496,9 @@
|
|
/* Create the TEMP table used to store parameter bindings */
|
|
static void bind_table_init(ShellState *p){
|
|
int wrSchema = 0;
|
|
+ int defensiveMode = 0;
|
|
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, -1, &defensiveMode);
|
|
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, 0, 0);
|
|
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
|
|
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
|
|
sqlite3_exec(p->db,
|
|
@@ -11310,6 +11508,7 @@
|
|
") WITHOUT ROWID;",
|
|
0, 0, 0);
|
|
sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
|
|
+ sqlite3_db_config(p->db, SQLITE_DBCONFIG_DEFENSIVE, defensiveMode, 0);
|
|
}
|
|
|
|
/*
|
|
@@ -11320,9 +11519,9 @@
|
|
** CREATE TEMP TABLE sqlite_parameters(key TEXT PRIMARY KEY, value)
|
|
** WITHOUT ROWID;
|
|
**
|
|
-** No bindings occur if this table does not exist. The special character '$'
|
|
-** is included in the table name to help prevent collisions with actual tables.
|
|
-** The table must be in the TEMP schema.
|
|
+** No bindings occur if this table does not exist. The name of the table
|
|
+** begins with "sqlite_" so that it will not collide with ordinary application
|
|
+** tables. The table must be in the TEMP schema.
|
|
*/
|
|
static void bind_prepared_stmt(ShellState *pArg, sqlite3_stmt *pStmt){
|
|
int nVar;
|
|
@@ -11626,6 +11825,7 @@
|
|
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
|
|
int iEqpId = sqlite3_column_int(pExplain, 0);
|
|
int iParentId = sqlite3_column_int(pExplain, 1);
|
|
+ if( zEQPLine==0 ) zEQPLine = "";
|
|
if( zEQPLine[0]=='-' ) eqp_render(pArg);
|
|
eqp_append(pArg, iEqpId, iParentId, zEQPLine);
|
|
}
|
|
@@ -12004,20 +12204,20 @@
|
|
".archive ... Manage SQL archives",
|
|
" Each command must have exactly one of the following options:",
|
|
" -c, --create Create a new archive",
|
|
- " -u, --update Add files or update files with changed mtime",
|
|
- " -i, --insert Like -u but always add even if mtime unchanged",
|
|
+ " -u, --update Add or update files with changed mtime",
|
|
+ " -i, --insert Like -u but always add even if unchanged",
|
|
" -t, --list List contents of archive",
|
|
" -x, --extract Extract files from archive",
|
|
" Optional arguments:",
|
|
" -v, --verbose Print each filename as it is processed",
|
|
- " -f FILE, --file FILE Operate on archive FILE (default is current db)",
|
|
- " -a FILE, --append FILE Operate on FILE opened using the apndvfs VFS",
|
|
- " -C DIR, --directory DIR Change to directory DIR to read/extract files",
|
|
+ " -f FILE, --file FILE Use archive FILE (default is current db)",
|
|
+ " -a FILE, --append FILE Open FILE using the apndvfs VFS",
|
|
+ " -C DIR, --directory DIR Read/extract files from directory DIR",
|
|
" -n, --dryrun Show the SQL that would have occurred",
|
|
" Examples:",
|
|
- " .ar -cf archive.sar foo bar # Create archive.sar from files foo and bar",
|
|
- " .ar -tf archive.sar # List members of archive.sar",
|
|
- " .ar -xvf archive.sar # Verbosely extract files from archive.sar",
|
|
+ " .ar -cf ARCHIVE foo bar # Create ARCHIVE from files foo and bar",
|
|
+ " .ar -tf ARCHIVE # List members of ARCHIVE",
|
|
+ " .ar -xvf ARCHIVE # Verbosely extract files from ARCHIVE",
|
|
" See also:",
|
|
" http://sqlite.org/cli.html#sqlar_archive_support",
|
|
#endif
|
|
@@ -12026,7 +12226,7 @@
|
|
#endif
|
|
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
|
|
" --append Use the appendvfs",
|
|
- " --async Write to FILE without a journal and without fsync()",
|
|
+ " --async Write to FILE without journal and fsync()",
|
|
".bail on|off Stop after hitting an error. Default OFF",
|
|
".binary on|off Turn binary output on or off. Default OFF",
|
|
".cd DIRECTORY Change the working directory to DIRECTORY",
|
|
@@ -12036,31 +12236,44 @@
|
|
".databases List names and files of attached databases",
|
|
".dbconfig ?op? ?val? List or change sqlite3_db_config() options",
|
|
".dbinfo ?DB? Show status information about the database",
|
|
- ".dump ?TABLE? ... Render all database content as SQL",
|
|
+ ".dump ?TABLE? Render database content as SQL",
|
|
" Options:",
|
|
" --preserve-rowids Include ROWID values in the output",
|
|
" --newlines Allow unescaped newline characters in output",
|
|
" TABLE is a LIKE pattern for the tables to dump",
|
|
+ " Additional LIKE patterns can be given in subsequent arguments",
|
|
".echo on|off Turn command echo on or off",
|
|
".eqp on|off|full|... Enable or disable automatic EXPLAIN QUERY PLAN",
|
|
" Other Modes:",
|
|
#ifdef SQLITE_DEBUG
|
|
" test Show raw EXPLAIN QUERY PLAN output",
|
|
- " trace Like \"full\" but also enable \"PRAGMA vdbe_trace\"",
|
|
+ " trace Like \"full\" but enable \"PRAGMA vdbe_trace\"",
|
|
#endif
|
|
" trigger Like \"full\" but also show trigger bytecode",
|
|
- ".excel Display the output of next command in a spreadsheet",
|
|
+ ".excel Display the output of next command in spreadsheet",
|
|
+ " --bom Put a UTF8 byte-order mark on intermediate file",
|
|
".exit ?CODE? Exit this program with return-code CODE",
|
|
- ".expert EXPERIMENTAL. Suggest indexes for specified queries",
|
|
-/* Because explain mode comes on automatically now, the ".explain" mode
|
|
-** is removed from the help screen. It is still supported for legacy, however */
|
|
-/*".explain ?on|off|auto? Turn EXPLAIN output mode on or off or to automatic",*/
|
|
+ ".expert EXPERIMENTAL. Suggest indexes for queries",
|
|
+ ".explain ?on|off|auto? Change the EXPLAIN formatting mode. Default: auto",
|
|
".filectrl CMD ... Run various sqlite3_file_control() operations",
|
|
- " Run \".filectrl\" with no arguments for details",
|
|
+ " --schema SCHEMA Use SCHEMA instead of \"main\"",
|
|
+ " --help Show CMD details",
|
|
".fullschema ?--indent? Show schema and the content of sqlite_stat tables",
|
|
".headers on|off Turn display of headers on or off",
|
|
".help ?-all? ?PATTERN? Show help text for PATTERN",
|
|
".import FILE TABLE Import data from FILE into TABLE",
|
|
+ " Options:",
|
|
+ " --ascii Use \\037 and \\036 as column and row separators",
|
|
+ " --csv Use , and \\n as column and row separators",
|
|
+ " --skip N Skip the first N rows of input",
|
|
+ " -v \"Verbose\" - increase auxiliary output",
|
|
+ " Notes:",
|
|
+ " * If TABLE does not exist, it is created. The first row of input",
|
|
+ " determines the column names.",
|
|
+ " * If neither --csv or --ascii are used, the input mode is derived",
|
|
+ " from the \".mode\" output mode",
|
|
+ " * If FILE begins with \"|\" then it is a command that generates the",
|
|
+ " input text.",
|
|
#ifndef SQLITE_OMIT_TEST_CONTROL
|
|
".imposter INDEX TABLE Create imposter table TABLE on index INDEX",
|
|
#endif
|
|
@@ -12091,30 +12304,38 @@
|
|
" tabs Tab-separated values",
|
|
" tcl TCL list elements",
|
|
".nullvalue STRING Use STRING in place of NULL values",
|
|
- ".once (-e|-x|FILE) Output for the next SQL command only to FILE",
|
|
+ ".once ?OPTIONS? ?FILE? Output for the next SQL command only to FILE",
|
|
" If FILE begins with '|' then open as a pipe",
|
|
- " Other options:",
|
|
- " -e Invoke system text editor",
|
|
- " -x Open in a spreadsheet",
|
|
+ " --bom Put a UTF8 byte-order mark at the beginning",
|
|
+ " -e Send output to the system text editor",
|
|
+ " -x Send output as CSV to a spreadsheet (same as \".excel\")",
|
|
+#ifdef SQLITE_DEBUG
|
|
+ ".oom [--repeat M] [N] Simulate an OOM error on the N-th allocation",
|
|
+#endif
|
|
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE",
|
|
" Options:",
|
|
" --append Use appendvfs to append database to the end of FILE",
|
|
#ifdef SQLITE_ENABLE_DESERIALIZE
|
|
" --deserialize Load into memory useing sqlite3_deserialize()",
|
|
- " --hexdb Load the output of \"dbtotxt\" as an in-memory database",
|
|
+ " --hexdb Load the output of \"dbtotxt\" as an in-memory db",
|
|
" --maxsize N Maximum size for --hexdb or --deserialized database",
|
|
#endif
|
|
" --new Initialize FILE to an empty database",
|
|
+ " --nofollow Do not follow symbolic links",
|
|
" --readonly Open FILE readonly",
|
|
" --zip FILE is a ZIP archive",
|
|
".output ?FILE? Send output to FILE or stdout if FILE is omitted",
|
|
- " If FILE begins with '|' then open it as a pipe.",
|
|
+ " If FILE begins with '|' then open it as a pipe.",
|
|
+ " Options:",
|
|
+ " --bom Prefix output with a UTF8 byte-order mark",
|
|
+ " -e Send output to the system text editor",
|
|
+ " -x Send output as CSV to a spreadsheet",
|
|
".parameter CMD ... Manage SQL parameter bindings",
|
|
" clear Erase all bindings",
|
|
" init Initialize the TEMP table that holds bindings",
|
|
" list List the current parameter bindings",
|
|
" set PARAMETER VALUE Given SQL parameter PARAMETER a value of VALUE",
|
|
- " PARAMETER should start with '$', ':', '@', or '?'",
|
|
+ " PARAMETER should start with one of: $ : @ ?",
|
|
" unset PARAMETER Remove PARAMETER from the binding table",
|
|
".print STRING... Print literal STRING",
|
|
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
|
@@ -12129,6 +12350,11 @@
|
|
".read FILE Read input from FILE",
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
|
".recover Recover as much data as possible from corrupt db.",
|
|
+ " --freelist-corrupt Assume the freelist is corrupt",
|
|
+ " --recovery-db NAME Store recovery metadata in database file NAME",
|
|
+ " --lost-and-found TABLE Alternative name for the lost-and-found table",
|
|
+ " --no-rowids Do not attempt to recover rowid values",
|
|
+ " that are not also INTEGER PRIMARY KEYs",
|
|
#endif
|
|
".restore ?DB? FILE Restore content of DB (default \"main\") from FILE",
|
|
".save FILE Write in-memory database into FILE",
|
|
@@ -12160,7 +12386,7 @@
|
|
" Options:",
|
|
" --schema Also hash the sqlite_master table",
|
|
" --sha3-224 Use the sha3-224 algorithm",
|
|
- " --sha3-256 Use the sha3-256 algorithm. This is the default.",
|
|
+ " --sha3-256 Use the sha3-256 algorithm (default)",
|
|
" --sha3-384 Use the sha3-384 algorithm",
|
|
" --sha3-512 Use the sha3-512 algorithm",
|
|
" Any other argument is a LIKE pattern for tables to hash",
|
|
@@ -12194,6 +12420,10 @@
|
|
" --row Trace each row (SQLITE_TRACE_ROW)",
|
|
" --close Trace connection close (SQLITE_TRACE_CLOSE)",
|
|
#endif /* SQLITE_OMIT_TRACE */
|
|
+#ifdef SQLITE_DEBUG
|
|
+ ".unmodule NAME ... Unregister virtual table modules",
|
|
+ " --allexcept Unregister everything except those named",
|
|
+#endif
|
|
".vfsinfo ?AUX? Information about the top-level VFS",
|
|
".vfslist List all available VFSes",
|
|
".vfsname ?AUX? Print the name of the VFS stack",
|
|
@@ -12219,6 +12449,7 @@
|
|
|| zPattern[0]=='0'
|
|
|| strcmp(zPattern,"-a")==0
|
|
|| strcmp(zPattern,"-all")==0
|
|
+ || strcmp(zPattern,"--all")==0
|
|
){
|
|
/* Show all commands, but only one line per command */
|
|
if( zPattern==0 ) zPattern = "";
|
|
@@ -12436,6 +12667,8 @@
|
|
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
|
|
if( rc!=2 ) goto readHexDb_error;
|
|
if( n<0 ) goto readHexDb_error;
|
|
+ if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ) goto readHexDb_error;
|
|
+ n = (n+pgsz-1)&~(pgsz-1); /* Round n up to the next multiple of pgsz */
|
|
a = sqlite3_malloc( n ? n : 1 );
|
|
if( a==0 ){
|
|
utf8_printf(stderr, "Out of memory!\n");
|
|
@@ -12520,6 +12753,23 @@
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+** Scalar function "shell_idquote(X)" returns string X quoted as an identifier,
|
|
+** using "..." with internal double-quote characters doubled.
|
|
+*/
|
|
+static void shellIdQuote(
|
|
+ sqlite3_context *context,
|
|
+ int argc,
|
|
+ sqlite3_value **argv
|
|
+){
|
|
+ const char *zName = (const char*)sqlite3_value_text(argv[0]);
|
|
+ UNUSED_PARAMETER(argc);
|
|
+ if( zName ){
|
|
+ char *z = sqlite3_mprintf("\"%w\"", zName);
|
|
+ sqlite3_result_text(context, z, -1, sqlite3_free);
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Scalar function "shell_escape_crnl" used by the .recover command.
|
|
** The argument passed to this function is the output of built-in
|
|
@@ -12641,7 +12891,7 @@
|
|
switch( p->openMode ){
|
|
case SHELL_OPEN_APPENDVFS: {
|
|
sqlite3_open_v2(p->zDbFilename, &p->db,
|
|
- SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
|
|
+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, "apndvfs");
|
|
break;
|
|
}
|
|
case SHELL_OPEN_HEXDB:
|
|
@@ -12654,12 +12904,14 @@
|
|
break;
|
|
}
|
|
case SHELL_OPEN_READONLY: {
|
|
- sqlite3_open_v2(p->zDbFilename, &p->db, SQLITE_OPEN_READONLY, 0);
|
|
+ sqlite3_open_v2(p->zDbFilename, &p->db,
|
|
+ SQLITE_OPEN_READONLY|p->openFlags, 0);
|
|
break;
|
|
}
|
|
case SHELL_OPEN_UNSPEC:
|
|
case SHELL_OPEN_NORMAL: {
|
|
- sqlite3_open(p->zDbFilename, &p->db);
|
|
+ sqlite3_open_v2(p->zDbFilename, &p->db,
|
|
+ SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|p->openFlags, 0);
|
|
break;
|
|
}
|
|
}
|
|
@@ -12679,6 +12931,7 @@
|
|
sqlite3_fileio_init(p->db, 0, 0);
|
|
sqlite3_shathree_init(p->db, 0, 0);
|
|
sqlite3_completion_init(p->db, 0, 0);
|
|
+ sqlite3_uint_init(p->db, 0, 0);
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
|
sqlite3_dbdata_init(p->db, 0, 0);
|
|
#endif
|
|
@@ -12696,6 +12949,8 @@
|
|
shellEscapeCrnl, 0, 0);
|
|
sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0,
|
|
shellInt32, 0, 0);
|
|
+ sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0,
|
|
+ shellIdQuote, 0, 0);
|
|
#ifndef SQLITE_NOHAVE_SYSTEM
|
|
sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0,
|
|
editFunc, 0, 0);
|
|
@@ -13013,6 +13268,8 @@
|
|
int n; /* Number of bytes in z */
|
|
int nAlloc; /* Space allocated for z[] */
|
|
int nLine; /* Current line number */
|
|
+ int nRow; /* Number of rows imported */
|
|
+ int nErr; /* Number of errors encountered */
|
|
int bNotFirst; /* True if one or more bytes already read */
|
|
int cTerm; /* Character that terminated the most recent field */
|
|
int cColSep; /* The column separator character. (Usually ",") */
|
|
@@ -13394,11 +13651,15 @@
|
|
zCmd = sqlite3_mprintf("%s %s", zXdgOpenCmd, p->zTempFile);
|
|
if( system(zCmd) ){
|
|
utf8_printf(stderr, "Failed: [%s]\n", zCmd);
|
|
+ }else{
|
|
+ /* Give the start/open/xdg-open command some time to get
|
|
+ ** going before we continue, and potential delete the
|
|
+ ** p->zTempFile data file out from under it */
|
|
+ sqlite3_sleep(2000);
|
|
}
|
|
sqlite3_free(zCmd);
|
|
outputModePop(p);
|
|
p->doXdgOpen = 0;
|
|
- sqlite3_sleep(100);
|
|
}
|
|
#endif /* !defined(SQLITE_NOHAVE_SYSTEM) */
|
|
}
|
|
@@ -13431,7 +13692,7 @@
|
|
}
|
|
|
|
/*
|
|
-** Implementation of the ".info" command.
|
|
+** Implementation of the ".dbinfo" command.
|
|
**
|
|
** Return 1 on error, 2 to exit, and 0 otherwise.
|
|
*/
|
|
@@ -13474,12 +13735,7 @@
|
|
"SELECT data FROM sqlite_dbpage(?1) WHERE pgno=1",
|
|
-1, &pStmt, 0);
|
|
if( rc ){
|
|
- if( !sqlite3_compileoption_used("ENABLE_DBPAGE_VTAB") ){
|
|
- utf8_printf(stderr, "the \".dbinfo\" command requires the "
|
|
- "-DSQLITE_ENABLE_DBPAGE_VTAB compile-time options\n");
|
|
- }else{
|
|
- utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
|
|
- }
|
|
+ utf8_printf(stderr, "error: %s\n", sqlite3_errmsg(p->db));
|
|
sqlite3_finalize(pStmt);
|
|
return 1;
|
|
}
|
|
@@ -13688,9 +13944,21 @@
|
|
sqlite3_file_control(p->db, 0, SQLITE_FCNTL_TEMPFILENAME, &p->zTempFile);
|
|
}
|
|
if( p->zTempFile==0 ){
|
|
+ /* If p->db is an in-memory database then the TEMPFILENAME file-control
|
|
+ ** will not work and we will need to fallback to guessing */
|
|
+ char *zTemp;
|
|
sqlite3_uint64 r;
|
|
sqlite3_randomness(sizeof(r), &r);
|
|
- p->zTempFile = sqlite3_mprintf("temp%llx.%s", r, zSuffix);
|
|
+ zTemp = getenv("TEMP");
|
|
+ if( zTemp==0 ) zTemp = getenv("TMP");
|
|
+ if( zTemp==0 ){
|
|
+#ifdef _WIN32
|
|
+ zTemp = "\\tmp";
|
|
+#else
|
|
+ zTemp = "/tmp";
|
|
+#endif
|
|
+ }
|
|
+ p->zTempFile = sqlite3_mprintf("%s/temp%llx.%s", zTemp, r, zSuffix);
|
|
}else{
|
|
p->zTempFile = sqlite3_mprintf("%z.%s", p->zTempFile, zSuffix);
|
|
}
|
|
@@ -14043,7 +14311,7 @@
|
|
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */
|
|
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
|
-/*********************************************************************************
|
|
+/******************************************************************************
|
|
** The ".archive" or ".ar" command.
|
|
*/
|
|
/*
|
|
@@ -14241,7 +14509,8 @@
|
|
i = n;
|
|
}else{
|
|
if( iArg>=(nArg-1) ){
|
|
- return arErrorMsg(pAr, "option requires an argument: %c",z[i]);
|
|
+ return arErrorMsg(pAr, "option requires an argument: %c",
|
|
+ z[i]);
|
|
}
|
|
zArg = azArg[++iArg];
|
|
}
|
|
@@ -14629,10 +14898,10 @@
|
|
** Implementation of ".ar" dot command.
|
|
*/
|
|
static int arDotCommand(
|
|
- ShellState *pState, /* Current shell tool state */
|
|
- int fromCmdLine, /* True if -A command-line option, not .ar cmd */
|
|
- char **azArg, /* Array of arguments passed to dot command */
|
|
- int nArg /* Number of entries in azArg[] */
|
|
+ ShellState *pState, /* Current shell tool state */
|
|
+ int fromCmdLine, /* True if -A command-line option, not .ar cmd */
|
|
+ char **azArg, /* Array of arguments passed to dot command */
|
|
+ int nArg /* Number of entries in azArg[] */
|
|
){
|
|
ArCommand cmd;
|
|
int rc;
|
|
@@ -14732,7 +15001,7 @@
|
|
return rc;
|
|
}
|
|
/* End of the ".archive" or ".ar" command logic
|
|
-**********************************************************************************/
|
|
+*******************************************************************************/
|
|
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */
|
|
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
|
|
@@ -14873,6 +15142,10 @@
|
|
sqlite3_stmt *pStmt = 0;
|
|
|
|
rc = sqlite3_open("", &dbtmp);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ sqlite3_create_function(dbtmp, "shell_idquote", 1, SQLITE_UTF8, 0,
|
|
+ shellIdQuote, 0, 0);
|
|
+ }
|
|
if( rc==SQLITE_OK ){
|
|
rc = sqlite3_exec(dbtmp, "PRAGMA writable_schema = on", 0, 0, 0);
|
|
}
|
|
@@ -14929,18 +15202,18 @@
|
|
}
|
|
}
|
|
|
|
- pTab->zQuoted = shellMPrintf(&rc, "%Q", zName);
|
|
+ pTab->zQuoted = shellMPrintf(&rc, "\"%w\"", zName);
|
|
pTab->azlCol = (char**)shellMalloc(&rc, sizeof(char*) * (nSqlCol+1));
|
|
pTab->nCol = nSqlCol;
|
|
|
|
if( bIntkey ){
|
|
- pTab->azlCol[0] = shellMPrintf(&rc, "%Q", zPk);
|
|
+ pTab->azlCol[0] = shellMPrintf(&rc, "\"%w\"", zPk);
|
|
}else{
|
|
pTab->azlCol[0] = shellMPrintf(&rc, "");
|
|
}
|
|
i = 1;
|
|
shellPreparePrintf(dbtmp, &rc, &pStmt,
|
|
- "SELECT %Q || group_concat(name, ', ') "
|
|
+ "SELECT %Q || group_concat(shell_idquote(name), ', ') "
|
|
" FILTER (WHERE cid!=%d) OVER (ORDER BY %s cid) "
|
|
"FROM pragma_table_info(%Q)",
|
|
bIntkey ? ", " : "", pTab->iPk,
|
|
@@ -15054,7 +15327,7 @@
|
|
|
|
pTab = (RecoverTable*)shellMalloc(pRc, sizeof(RecoverTable));
|
|
if( pTab ){
|
|
- pTab->zQuoted = shellMPrintf(pRc, "%Q", zTab);
|
|
+ pTab->zQuoted = shellMPrintf(pRc, "\"%w\"", zTab);
|
|
pTab->nCol = nCol;
|
|
pTab->iPk = -2;
|
|
if( nCol>0 ){
|
|
@@ -15103,6 +15376,7 @@
|
|
RecoverTable *pOrphan = 0;
|
|
|
|
int bFreelist = 1; /* 0 if --freelist-corrupt is specified */
|
|
+ int bRowids = 1; /* 0 if --no-rowids */
|
|
for(i=1; i<nArg; i++){
|
|
char *z = azArg[i];
|
|
int n;
|
|
@@ -15118,13 +15392,13 @@
|
|
if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
|
|
i++;
|
|
zLostAndFound = azArg[i];
|
|
+ }else
|
|
+ if( n<=10 && memcmp("-no-rowids", z, n)==0 ){
|
|
+ bRowids = 0;
|
|
}
|
|
else{
|
|
- raw_printf(stderr, "unexpected option: %s\n", azArg[i]);
|
|
- raw_printf(stderr, "options are:\n");
|
|
- raw_printf(stderr, " --freelist-corrupt\n");
|
|
- raw_printf(stderr, " --recovery-db DATABASE\n");
|
|
- raw_printf(stderr, " --lost-and-found TABLE-NAME\n");
|
|
+ utf8_printf(stderr, "unexpected option: %s\n", azArg[i]);
|
|
+ showHelp(pState->out, azArg[0]);
|
|
return 1;
|
|
}
|
|
}
|
|
@@ -15132,6 +15406,7 @@
|
|
shellExecPrintf(pState->db, &rc,
|
|
/* Attach an in-memory database named 'recovery'. Create an indexed
|
|
** cache of the sqlite_dbptr virtual table. */
|
|
+ "PRAGMA writable_schema = on;"
|
|
"ATTACH %Q AS recovery;"
|
|
"DROP TABLE IF EXISTS recovery.dbptr;"
|
|
"DROP TABLE IF EXISTS recovery.freelist;"
|
|
@@ -15162,6 +15437,21 @@
|
|
);
|
|
}
|
|
|
|
+ /* If this is an auto-vacuum database, add all pointer-map pages to
|
|
+ ** the freelist table. Do this regardless of whether or not
|
|
+ ** --freelist-corrupt was specified. */
|
|
+ shellExec(pState->db, &rc,
|
|
+ "WITH ptrmap(pgno) AS ("
|
|
+ " SELECT 2 WHERE shell_int32("
|
|
+ " (SELECT data FROM sqlite_dbpage WHERE pgno=1), 13"
|
|
+ " )"
|
|
+ " UNION ALL "
|
|
+ " SELECT pgno+1+(SELECT page_size FROM pragma_page_size)/5 AS pp "
|
|
+ " FROM ptrmap WHERE pp<=(SELECT page_count FROM pragma_page_count)"
|
|
+ ")"
|
|
+ "REPLACE INTO recovery.freelist SELECT pgno FROM ptrmap"
|
|
+ );
|
|
+
|
|
shellExec(pState->db, &rc,
|
|
"CREATE TABLE recovery.dbptr("
|
|
" pgno, child, PRIMARY KEY(child, pgno)"
|
|
@@ -15210,7 +15500,7 @@
|
|
" )"
|
|
" SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
|
|
") "
|
|
- "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"
|
|
+ "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
|
|
"UPDATE recovery.map AS o SET intkey = ("
|
|
" SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
|
|
");"
|
|
@@ -15235,6 +15525,11 @@
|
|
** CREATE TABLE statements that extracted from the existing schema. */
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3_stmt *pStmt = 0;
|
|
+ /* ".recover" might output content in an order which causes immediate
|
|
+ ** foreign key constraints to be violated. So disable foreign-key
|
|
+ ** constraint enforcement to prevent problems when running the output
|
|
+ ** script. */
|
|
+ raw_printf(pState->out, "PRAGMA foreign_keys=OFF;\n");
|
|
raw_printf(pState->out, "BEGIN;\n");
|
|
raw_printf(pState->out, "PRAGMA writable_schema = on;\n");
|
|
shellPrepare(pState->db, &rc,
|
|
@@ -15265,8 +15560,12 @@
|
|
shellPrepare(pState->db, &rc,
|
|
"SELECT pgno FROM recovery.map WHERE root=?", &pPages
|
|
);
|
|
+
|
|
shellPrepare(pState->db, &rc,
|
|
- "SELECT max(field), group_concat(shell_escape_crnl(quote(value)), ', ')"
|
|
+ "SELECT max(field), group_concat(shell_escape_crnl(quote"
|
|
+ "(case when (? AND field<0) then NULL else value end)"
|
|
+ "), ', ')"
|
|
+ ", min(field) "
|
|
"FROM sqlite_dbdata WHERE pgno = ? AND field != ?"
|
|
"GROUP BY cell", &pCells
|
|
);
|
|
@@ -15285,6 +15584,7 @@
|
|
int bNoop = 0;
|
|
RecoverTable *pTab;
|
|
|
|
+ assert( bIntkey==0 || bIntkey==1 );
|
|
pTab = recoverFindTable(pState, &rc, iRoot, bIntkey, nCol, &bNoop);
|
|
if( bNoop || rc ) continue;
|
|
if( pTab==0 ){
|
|
@@ -15295,29 +15595,44 @@
|
|
if( pTab==0 ) break;
|
|
}
|
|
|
|
- if( 0==sqlite3_stricmp(pTab->zQuoted, "'sqlite_sequence'") ){
|
|
+ if( 0==sqlite3_stricmp(pTab->zQuoted, "\"sqlite_sequence\"") ){
|
|
raw_printf(pState->out, "DELETE FROM sqlite_sequence;\n");
|
|
}
|
|
sqlite3_bind_int(pPages, 1, iRoot);
|
|
- sqlite3_bind_int(pCells, 2, pTab->iPk);
|
|
+ if( bRowids==0 && pTab->iPk<0 ){
|
|
+ sqlite3_bind_int(pCells, 1, 1);
|
|
+ }else{
|
|
+ sqlite3_bind_int(pCells, 1, 0);
|
|
+ }
|
|
+ sqlite3_bind_int(pCells, 3, pTab->iPk);
|
|
|
|
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pPages) ){
|
|
int iPgno = sqlite3_column_int(pPages, 0);
|
|
- sqlite3_bind_int(pCells, 1, iPgno);
|
|
+ sqlite3_bind_int(pCells, 2, iPgno);
|
|
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pCells) ){
|
|
int nField = sqlite3_column_int(pCells, 0);
|
|
+ int iMin = sqlite3_column_int(pCells, 2);
|
|
const char *zVal = (const char*)sqlite3_column_text(pCells, 1);
|
|
|
|
+ RecoverTable *pTab2 = pTab;
|
|
+ if( pTab!=pOrphan && (iMin<0)!=bIntkey ){
|
|
+ if( pOrphan==0 ){
|
|
+ pOrphan = recoverOrphanTable(pState, &rc, zLostAndFound, nOrphan);
|
|
+ }
|
|
+ pTab2 = pOrphan;
|
|
+ if( pTab2==0 ) break;
|
|
+ }
|
|
+
|
|
nField = nField+1;
|
|
- if( pTab==pOrphan ){
|
|
+ if( pTab2==pOrphan ){
|
|
raw_printf(pState->out,
|
|
"INSERT INTO %s VALUES(%d, %d, %d, %s%s%s);\n",
|
|
- pTab->zQuoted, iRoot, iPgno, nField,
|
|
- bIntkey ? "" : "NULL, ", zVal, pTab->azlCol[nField]
|
|
+ pTab2->zQuoted, iRoot, iPgno, nField,
|
|
+ iMin<0 ? "" : "NULL, ", zVal, pTab2->azlCol[nField]
|
|
);
|
|
}else{
|
|
raw_printf(pState->out, "INSERT INTO %s(%s) VALUES( %s );\n",
|
|
- pTab->zQuoted, pTab->azlCol[nField], zVal
|
|
+ pTab2->zQuoted, pTab2->azlCol[nField], zVal
|
|
);
|
|
}
|
|
}
|
|
@@ -15376,7 +15691,7 @@
|
|
int nArg = 0;
|
|
int n, c;
|
|
int rc = 0;
|
|
- char *azArg[50];
|
|
+ char *azArg[52];
|
|
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
if( p->expert.pExpert ){
|
|
@@ -15386,7 +15701,7 @@
|
|
|
|
/* Parse the input line into tokens.
|
|
*/
|
|
- while( zLine[h] && nArg<ArraySize(azArg) ){
|
|
+ while( zLine[h] && nArg<ArraySize(azArg)-1 ){
|
|
while( IsSpace(zLine[h]) ){ h++; }
|
|
if( zLine[h]==0 ) break;
|
|
if( zLine[h]=='\'' || zLine[h]=='"' ){
|
|
@@ -15407,6 +15722,7 @@
|
|
resolve_backslashes(azArg[nArg-1]);
|
|
}
|
|
}
|
|
+ azArg[nArg] = 0;
|
|
|
|
/* Process the input line.
|
|
*/
|
|
@@ -15620,19 +15936,22 @@
|
|
const char *zName;
|
|
int op;
|
|
} aDbConfig[] = {
|
|
+ { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
|
|
+ { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
|
|
+ { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
|
|
{ "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
|
|
+ { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
|
|
{ "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
|
|
+ { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
|
|
{ "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
|
|
+ { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
|
|
+ { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
|
|
{ "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
|
|
{ "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
|
|
- { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
|
|
- { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
|
|
{ "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
|
|
- { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
|
|
+ { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
|
|
+ { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
|
|
{ "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
|
|
- { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
|
|
- { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
|
|
- { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
|
|
};
|
|
int ii, v;
|
|
open_db(p, 0);
|
|
@@ -15642,7 +15961,7 @@
|
|
sqlite3_db_config(p->db, aDbConfig[ii].op, booleanValue(azArg[2]), 0);
|
|
}
|
|
sqlite3_db_config(p->db, aDbConfig[ii].op, -1, &v);
|
|
- utf8_printf(p->out, "%18s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
|
|
+ utf8_printf(p->out, "%19s %s\n", aDbConfig[ii].zName, v ? "on" : "off");
|
|
if( nArg>1 ) break;
|
|
}
|
|
if( nArg>1 && ii==ArraySize(aDbConfig) ){
|
|
@@ -15663,7 +15982,8 @@
|
|
#endif /* !(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) */
|
|
|
|
if( c=='d' && strncmp(azArg[0], "dump", n)==0 ){
|
|
- const char *zLike = 0;
|
|
+ char *zLike = 0;
|
|
+ char *zSql;
|
|
int i;
|
|
int savedShowHeader = p->showHeader;
|
|
int savedShellFlags = p->shellFlgs;
|
|
@@ -15691,12 +16011,10 @@
|
|
goto meta_command_exit;
|
|
}
|
|
}else if( zLike ){
|
|
- raw_printf(stderr, "Usage: .dump ?--preserve-rowids? "
|
|
- "?--newlines? ?LIKE-PATTERN?\n");
|
|
- rc = 1;
|
|
- goto meta_command_exit;
|
|
+ zLike = sqlite3_mprintf("%z OR name LIKE %Q ESCAPE '\\'",
|
|
+ zLike, azArg[i]);
|
|
}else{
|
|
- zLike = azArg[i];
|
|
+ zLike = sqlite3_mprintf("name LIKE %Q ESCAPE '\\'", azArg[i]);
|
|
}
|
|
}
|
|
|
|
@@ -15714,35 +16032,25 @@
|
|
** corrupt. */
|
|
sqlite3_exec(p->db, "SAVEPOINT dump; PRAGMA writable_schema=ON", 0, 0, 0);
|
|
p->nErr = 0;
|
|
- if( zLike==0 ){
|
|
- run_schema_dump_query(p,
|
|
- "SELECT name, type, sql FROM sqlite_master "
|
|
- "WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'"
|
|
- );
|
|
- run_schema_dump_query(p,
|
|
- "SELECT name, type, sql FROM sqlite_master "
|
|
- "WHERE name=='sqlite_sequence'"
|
|
- );
|
|
- run_table_dump_query(p,
|
|
- "SELECT sql FROM sqlite_master "
|
|
- "WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
|
|
- );
|
|
- }else{
|
|
- char *zSql;
|
|
- zSql = sqlite3_mprintf(
|
|
- "SELECT name, type, sql FROM sqlite_master "
|
|
- "WHERE tbl_name LIKE %Q AND type=='table'"
|
|
- " AND sql NOT NULL", zLike);
|
|
- run_schema_dump_query(p,zSql);
|
|
- sqlite3_free(zSql);
|
|
- zSql = sqlite3_mprintf(
|
|
- "SELECT sql FROM sqlite_master "
|
|
- "WHERE sql NOT NULL"
|
|
- " AND type IN ('index','trigger','view')"
|
|
- " AND tbl_name LIKE %Q", zLike);
|
|
- run_table_dump_query(p, zSql, 0);
|
|
- sqlite3_free(zSql);
|
|
- }
|
|
+ if( zLike==0 ) zLike = sqlite3_mprintf("true");
|
|
+ zSql = sqlite3_mprintf(
|
|
+ "SELECT name, type, sql FROM sqlite_master "
|
|
+ "WHERE (%s) AND type=='table'"
|
|
+ " AND sql NOT NULL"
|
|
+ " ORDER BY tbl_name='sqlite_sequence', rowid",
|
|
+ zLike
|
|
+ );
|
|
+ run_schema_dump_query(p,zSql);
|
|
+ sqlite3_free(zSql);
|
|
+ zSql = sqlite3_mprintf(
|
|
+ "SELECT sql FROM sqlite_master "
|
|
+ "WHERE (%s) AND sql NOT NULL"
|
|
+ " AND type IN ('index','trigger','view')",
|
|
+ zLike
|
|
+ );
|
|
+ run_table_dump_query(p, zSql);
|
|
+ sqlite3_free(zSql);
|
|
+ sqlite3_free(zLike);
|
|
if( p->writableSchema ){
|
|
raw_printf(p->out, "PRAGMA writable_schema=OFF;\n");
|
|
p->writableSchema = 0;
|
|
@@ -15845,6 +16153,7 @@
|
|
{ "tempfilename", SQLITE_FCNTL_TEMPFILENAME, "" },
|
|
{ "has_moved", SQLITE_FCNTL_HAS_MOVED, "" },
|
|
{ "lock_timeout", SQLITE_FCNTL_LOCK_TIMEOUT, "MILLISEC" },
|
|
+ { "reserve_bytes", SQLITE_FCNTL_RESERVE_BYTES, "[N]" },
|
|
};
|
|
int filectrl = -1;
|
|
int iCtrl = -1;
|
|
@@ -15852,10 +16161,21 @@
|
|
int isOk = 0; /* 0: usage 1: %lld 2: no-result */
|
|
int n2, i;
|
|
const char *zCmd = 0;
|
|
+ const char *zSchema = 0;
|
|
|
|
open_db(p, 0);
|
|
zCmd = nArg>=2 ? azArg[1] : "help";
|
|
|
|
+ if( zCmd[0]=='-'
|
|
+ && (strcmp(zCmd,"--schema")==0 || strcmp(zCmd,"-schema")==0)
|
|
+ && nArg>=4
|
|
+ ){
|
|
+ zSchema = azArg[2];
|
|
+ for(i=3; i<nArg; i++) azArg[i-2] = azArg[i];
|
|
+ nArg -= 2;
|
|
+ zCmd = azArg[1];
|
|
+ }
|
|
+
|
|
/* The argument can optionally begin with "-" or "--" */
|
|
if( zCmd[0]=='-' && zCmd[1] ){
|
|
zCmd++;
|
|
@@ -15897,7 +16217,7 @@
|
|
case SQLITE_FCNTL_SIZE_LIMIT: {
|
|
if( nArg!=2 && nArg!=3 ) break;
|
|
iRes = nArg==3 ? integerValue(azArg[2]) : -1;
|
|
- sqlite3_file_control(p->db, 0, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
|
|
+ sqlite3_file_control(p->db, zSchema, SQLITE_FCNTL_SIZE_LIMIT, &iRes);
|
|
isOk = 1;
|
|
break;
|
|
}
|
|
@@ -15906,7 +16226,7 @@
|
|
int x;
|
|
if( nArg!=3 ) break;
|
|
x = (int)integerValue(azArg[2]);
|
|
- sqlite3_file_control(p->db, 0, filectrl, &x);
|
|
+ sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
|
isOk = 2;
|
|
break;
|
|
}
|
|
@@ -15915,7 +16235,7 @@
|
|
int x;
|
|
if( nArg!=2 && nArg!=3 ) break;
|
|
x = nArg==3 ? booleanValue(azArg[2]) : -1;
|
|
- sqlite3_file_control(p->db, 0, filectrl, &x);
|
|
+ sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
|
iRes = x;
|
|
isOk = 1;
|
|
break;
|
|
@@ -15923,7 +16243,7 @@
|
|
case SQLITE_FCNTL_HAS_MOVED: {
|
|
int x;
|
|
if( nArg!=2 ) break;
|
|
- sqlite3_file_control(p->db, 0, filectrl, &x);
|
|
+ sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
|
iRes = x;
|
|
isOk = 1;
|
|
break;
|
|
@@ -15931,7 +16251,7 @@
|
|
case SQLITE_FCNTL_TEMPFILENAME: {
|
|
char *z = 0;
|
|
if( nArg!=2 ) break;
|
|
- sqlite3_file_control(p->db, 0, filectrl, &z);
|
|
+ sqlite3_file_control(p->db, zSchema, filectrl, &z);
|
|
if( z ){
|
|
utf8_printf(p->out, "%s\n", z);
|
|
sqlite3_free(z);
|
|
@@ -15939,6 +16259,18 @@
|
|
isOk = 2;
|
|
break;
|
|
}
|
|
+ case SQLITE_FCNTL_RESERVE_BYTES: {
|
|
+ int x;
|
|
+ if( nArg>=3 ){
|
|
+ x = atoi(azArg[2]);
|
|
+ sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
|
+ }
|
|
+ x = -1;
|
|
+ sqlite3_file_control(p->db, zSchema, filectrl, &x);
|
|
+ utf8_printf(p->out,"%d\n", x);
|
|
+ isOk = 2;
|
|
+ break;
|
|
+ }
|
|
}
|
|
}
|
|
if( isOk==0 && iCtrl>=0 ){
|
|
@@ -15995,8 +16327,6 @@
|
|
data.cMode = data.mode = MODE_Insert;
|
|
data.zDestTable = "sqlite_stat1";
|
|
shell_exec(&data, "SELECT * FROM sqlite_stat1", &zErrMsg);
|
|
- data.zDestTable = "sqlite_stat3";
|
|
- shell_exec(&data, "SELECT * FROM sqlite_stat3", &zErrMsg);
|
|
data.zDestTable = "sqlite_stat4";
|
|
shell_exec(&data, "SELECT * FROM sqlite_stat4", &zErrMsg);
|
|
raw_printf(p->out, "ANALYZE sqlite_master;\n");
|
|
@@ -16024,8 +16354,8 @@
|
|
}else
|
|
|
|
if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
|
|
- char *zTable; /* Insert data into this table */
|
|
- char *zFile; /* Name of file to extra content from */
|
|
+ char *zTable = 0; /* Insert data into this table */
|
|
+ char *zFile = 0; /* Name of file to extra content from */
|
|
sqlite3_stmt *pStmt = NULL; /* A statement */
|
|
int nCol; /* Number of columns in the table */
|
|
int nByte; /* Number of bytes in an SQL string */
|
|
@@ -16036,51 +16366,108 @@
|
|
ImportCtx sCtx; /* Reader context */
|
|
char *(SQLITE_CDECL *xRead)(ImportCtx*); /* Func to read one value */
|
|
int (SQLITE_CDECL *xCloser)(FILE*); /* Func to close file */
|
|
+ int eVerbose = 0; /* Larger for more console output */
|
|
+ int nSkip = 0; /* Initial lines to skip */
|
|
+ int useOutputMode = 1; /* Use output mode to determine separators */
|
|
|
|
- if( nArg!=3 ){
|
|
- raw_printf(stderr, "Usage: .import FILE TABLE\n");
|
|
- goto meta_command_exit;
|
|
- }
|
|
- zFile = azArg[1];
|
|
- zTable = azArg[2];
|
|
- seenInterrupt = 0;
|
|
memset(&sCtx, 0, sizeof(sCtx));
|
|
- open_db(p, 0);
|
|
- nSep = strlen30(p->colSeparator);
|
|
- if( nSep==0 ){
|
|
- raw_printf(stderr,
|
|
- "Error: non-null column separator required for import\n");
|
|
- return 1;
|
|
+ if( p->mode==MODE_Ascii ){
|
|
+ xRead = ascii_read_one_field;
|
|
+ }else{
|
|
+ xRead = csv_read_one_field;
|
|
}
|
|
- if( nSep>1 ){
|
|
- raw_printf(stderr, "Error: multi-character column separators not allowed"
|
|
- " for import\n");
|
|
- return 1;
|
|
+ for(i=1; i<nArg; i++){
|
|
+ char *z = azArg[i];
|
|
+ if( z[0]=='-' && z[1]=='-' ) z++;
|
|
+ if( z[0]!='-' ){
|
|
+ if( zFile==0 ){
|
|
+ zFile = z;
|
|
+ }else if( zTable==0 ){
|
|
+ zTable = z;
|
|
+ }else{
|
|
+ utf8_printf(p->out, "ERROR: extra argument: \"%s\". Usage:\n", z);
|
|
+ showHelp(p->out, "import");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ }else if( strcmp(z,"-v")==0 ){
|
|
+ eVerbose++;
|
|
+ }else if( strcmp(z,"-skip")==0 && i<nArg-1 ){
|
|
+ nSkip = integerValue(azArg[++i]);
|
|
+ }else if( strcmp(z,"-ascii")==0 ){
|
|
+ sCtx.cColSep = SEP_Unit[0];
|
|
+ sCtx.cRowSep = SEP_Record[0];
|
|
+ xRead = ascii_read_one_field;
|
|
+ useOutputMode = 0;
|
|
+ }else if( strcmp(z,"-csv")==0 ){
|
|
+ sCtx.cColSep = ',';
|
|
+ sCtx.cRowSep = '\n';
|
|
+ xRead = csv_read_one_field;
|
|
+ useOutputMode = 0;
|
|
+ }else{
|
|
+ utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n", z);
|
|
+ showHelp(p->out, "import");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
}
|
|
- nSep = strlen30(p->rowSeparator);
|
|
- if( nSep==0 ){
|
|
- raw_printf(stderr, "Error: non-null row separator required for import\n");
|
|
- return 1;
|
|
+ if( zTable==0 ){
|
|
+ utf8_printf(p->out, "ERROR: missing %s argument. Usage:\n",
|
|
+ zFile==0 ? "FILE" : "TABLE");
|
|
+ showHelp(p->out, "import");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
}
|
|
- if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator, SEP_CrLf)==0 ){
|
|
- /* When importing CSV (only), if the row separator is set to the
|
|
- ** default output row separator, change it to the default input
|
|
- ** row separator. This avoids having to maintain different input
|
|
- ** and output row separators. */
|
|
- sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
|
+ seenInterrupt = 0;
|
|
+ open_db(p, 0);
|
|
+ if( useOutputMode ){
|
|
+ /* If neither the --csv or --ascii options are specified, then set
|
|
+ ** the column and row separator characters from the output mode. */
|
|
+ nSep = strlen30(p->colSeparator);
|
|
+ if( nSep==0 ){
|
|
+ raw_printf(stderr,
|
|
+ "Error: non-null column separator required for import\n");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ if( nSep>1 ){
|
|
+ raw_printf(stderr,
|
|
+ "Error: multi-character column separators not allowed"
|
|
+ " for import\n");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
nSep = strlen30(p->rowSeparator);
|
|
- }
|
|
- if( nSep>1 ){
|
|
- raw_printf(stderr, "Error: multi-character row separators not allowed"
|
|
- " for import\n");
|
|
- return 1;
|
|
+ if( nSep==0 ){
|
|
+ raw_printf(stderr,
|
|
+ "Error: non-null row separator required for import\n");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ if( nSep==2 && p->mode==MODE_Csv && strcmp(p->rowSeparator,SEP_CrLf)==0 ){
|
|
+ /* When importing CSV (only), if the row separator is set to the
|
|
+ ** default output row separator, change it to the default input
|
|
+ ** row separator. This avoids having to maintain different input
|
|
+ ** and output row separators. */
|
|
+ sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_Row);
|
|
+ nSep = strlen30(p->rowSeparator);
|
|
+ }
|
|
+ if( nSep>1 ){
|
|
+ raw_printf(stderr, "Error: multi-character row separators not allowed"
|
|
+ " for import\n");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ sCtx.cColSep = p->colSeparator[0];
|
|
+ sCtx.cRowSep = p->rowSeparator[0];
|
|
}
|
|
sCtx.zFile = zFile;
|
|
sCtx.nLine = 1;
|
|
if( sCtx.zFile[0]=='|' ){
|
|
#ifdef SQLITE_OMIT_POPEN
|
|
raw_printf(stderr, "Error: pipes are not supported in this OS\n");
|
|
- return 1;
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
#else
|
|
sCtx.in = popen(sCtx.zFile+1, "r");
|
|
sCtx.zFile = "<pipe>";
|
|
@@ -16090,17 +16477,26 @@
|
|
sCtx.in = fopen(sCtx.zFile, "rb");
|
|
xCloser = fclose;
|
|
}
|
|
- if( p->mode==MODE_Ascii ){
|
|
- xRead = ascii_read_one_field;
|
|
- }else{
|
|
- xRead = csv_read_one_field;
|
|
- }
|
|
if( sCtx.in==0 ){
|
|
utf8_printf(stderr, "Error: cannot open \"%s\"\n", zFile);
|
|
- return 1;
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ if( eVerbose>=2 || (eVerbose>=1 && useOutputMode) ){
|
|
+ char zSep[2];
|
|
+ zSep[1] = 0;
|
|
+ zSep[0] = sCtx.cColSep;
|
|
+ utf8_printf(p->out, "Column separator ");
|
|
+ output_c_string(p->out, zSep);
|
|
+ utf8_printf(p->out, ", row separator ");
|
|
+ zSep[0] = sCtx.cRowSep;
|
|
+ output_c_string(p->out, zSep);
|
|
+ utf8_printf(p->out, "\n");
|
|
+ }
|
|
+ while( (nSkip--)>0 ){
|
|
+ while( xRead(&sCtx) && sCtx.cTerm==sCtx.cColSep ){}
|
|
+ sCtx.nLine++;
|
|
}
|
|
- sCtx.cColSep = p->colSeparator[0];
|
|
- sCtx.cRowSep = p->rowSeparator[0];
|
|
zSql = sqlite3_mprintf("SELECT * FROM %s", zTable);
|
|
if( zSql==0 ){
|
|
xCloser(sCtx.in);
|
|
@@ -16122,9 +16518,13 @@
|
|
sqlite3_free(sCtx.z);
|
|
xCloser(sCtx.in);
|
|
utf8_printf(stderr,"%s: empty file\n", sCtx.zFile);
|
|
- return 1;
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
}
|
|
zCreate = sqlite3_mprintf("%z\n)", zCreate);
|
|
+ if( eVerbose>=1 ){
|
|
+ utf8_printf(p->out, "%s\n", zCreate);
|
|
+ }
|
|
rc = sqlite3_exec(p->db, zCreate, 0, 0, 0);
|
|
sqlite3_free(zCreate);
|
|
if( rc ){
|
|
@@ -16132,7 +16532,8 @@
|
|
sqlite3_errmsg(p->db));
|
|
sqlite3_free(sCtx.z);
|
|
xCloser(sCtx.in);
|
|
- return 1;
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
}
|
|
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
|
}
|
|
@@ -16141,7 +16542,8 @@
|
|
if (pStmt) sqlite3_finalize(pStmt);
|
|
utf8_printf(stderr,"Error: %s\n", sqlite3_errmsg(p->db));
|
|
xCloser(sCtx.in);
|
|
- return 1;
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
}
|
|
nCol = sqlite3_column_count(pStmt);
|
|
sqlite3_finalize(pStmt);
|
|
@@ -16160,13 +16562,17 @@
|
|
}
|
|
zSql[j++] = ')';
|
|
zSql[j] = 0;
|
|
+ if( eVerbose>=2 ){
|
|
+ utf8_printf(p->out, "Insert using: %s\n", zSql);
|
|
+ }
|
|
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
|
sqlite3_free(zSql);
|
|
if( rc ){
|
|
utf8_printf(stderr, "Error: %s\n", sqlite3_errmsg(p->db));
|
|
if (pStmt) sqlite3_finalize(pStmt);
|
|
xCloser(sCtx.in);
|
|
- return 1;
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
}
|
|
needCommit = sqlite3_get_autocommit(p->db);
|
|
if( needCommit ) sqlite3_exec(p->db, "BEGIN", 0, 0, 0);
|
|
@@ -16209,6 +16615,9 @@
|
|
if( rc!=SQLITE_OK ){
|
|
utf8_printf(stderr, "%s:%d: INSERT failed: %s\n", sCtx.zFile,
|
|
startLine, sqlite3_errmsg(p->db));
|
|
+ sCtx.nErr++;
|
|
+ }else{
|
|
+ sCtx.nRow++;
|
|
}
|
|
}
|
|
}while( sCtx.cTerm!=EOF );
|
|
@@ -16217,6 +16626,11 @@
|
|
sqlite3_free(sCtx.z);
|
|
sqlite3_finalize(pStmt);
|
|
if( needCommit ) sqlite3_exec(p->db, "COMMIT", 0, 0, 0);
|
|
+ if( eVerbose>0 ){
|
|
+ utf8_printf(p->out,
|
|
+ "Added %d rows with %d errors using %d lines of input\n",
|
|
+ sCtx.nRow, sCtx.nErr, sCtx.nLine-1);
|
|
+ }
|
|
}else
|
|
|
|
#ifndef SQLITE_UNTESTABLE
|
|
@@ -16225,10 +16639,19 @@
|
|
char *zCollist = 0;
|
|
sqlite3_stmt *pStmt;
|
|
int tnum = 0;
|
|
+ int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */
|
|
+ int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */
|
|
int i;
|
|
if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){
|
|
utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n"
|
|
" .imposter off\n");
|
|
+ /* Also allowed, but not documented:
|
|
+ **
|
|
+ ** .imposter TABLE IMPOSTER
|
|
+ **
|
|
+ ** where TABLE is a WITHOUT ROWID table. In that case, the
|
|
+ ** imposter is another WITHOUT ROWID table with the columns in
|
|
+ ** storage order. */
|
|
rc = 1;
|
|
goto meta_command_exit;
|
|
}
|
|
@@ -16237,19 +16660,22 @@
|
|
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 0, 1);
|
|
goto meta_command_exit;
|
|
}
|
|
- zSql = sqlite3_mprintf("SELECT rootpage FROM sqlite_master"
|
|
- " WHERE name='%q' AND type='index'", azArg[1]);
|
|
+ zSql = sqlite3_mprintf(
|
|
+ "SELECT rootpage, 0 FROM sqlite_master"
|
|
+ " WHERE name='%q' AND type='index'"
|
|
+ "UNION ALL "
|
|
+ "SELECT rootpage, 1 FROM sqlite_master"
|
|
+ " WHERE name='%q' AND type='table'"
|
|
+ " AND sql LIKE '%%without%%rowid%%'",
|
|
+ azArg[1], azArg[1]
|
|
+ );
|
|
sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
|
sqlite3_free(zSql);
|
|
if( sqlite3_step(pStmt)==SQLITE_ROW ){
|
|
tnum = sqlite3_column_int(pStmt, 0);
|
|
+ isWO = sqlite3_column_int(pStmt, 1);
|
|
}
|
|
sqlite3_finalize(pStmt);
|
|
- if( tnum==0 ){
|
|
- utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
|
|
- rc = 1;
|
|
- goto meta_command_exit;
|
|
- }
|
|
zSql = sqlite3_mprintf("PRAGMA index_xinfo='%q'", azArg[1]);
|
|
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
|
sqlite3_free(zSql);
|
|
@@ -16266,6 +16692,9 @@
|
|
zCol = zLabel;
|
|
}
|
|
}
|
|
+ if( isWO && lenPK==0 && sqlite3_column_int(pStmt,5)==0 && zCollist ){
|
|
+ lenPK = (int)strlen(zCollist);
|
|
+ }
|
|
if( zCollist==0 ){
|
|
zCollist = sqlite3_mprintf("\"%w\"", zCol);
|
|
}else{
|
|
@@ -16273,9 +16702,16 @@
|
|
}
|
|
}
|
|
sqlite3_finalize(pStmt);
|
|
+ if( i==0 || tnum==0 ){
|
|
+ utf8_printf(stderr, "no such index: \"%s\"\n", azArg[1]);
|
|
+ rc = 1;
|
|
+ sqlite3_free(zCollist);
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ if( lenPK==0 ) lenPK = 100000;
|
|
zSql = sqlite3_mprintf(
|
|
- "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%s))WITHOUT ROWID",
|
|
- azArg[2], zCollist, zCollist);
|
|
+ "CREATE TABLE \"%w\"(%s,PRIMARY KEY(%.*s))WITHOUT ROWID",
|
|
+ azArg[2], zCollist, lenPK, zCollist);
|
|
sqlite3_free(zCollist);
|
|
rc = sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->db, "main", 1, tnum);
|
|
if( rc==SQLITE_OK ){
|
|
@@ -16286,7 +16722,8 @@
|
|
}else{
|
|
utf8_printf(stdout, "%s;\n", zSql);
|
|
raw_printf(stdout,
|
|
- "WARNING: writing to an imposter table will corrupt the index!\n"
|
|
+ "WARNING: writing to an imposter table will corrupt the \"%s\" %s!\n",
|
|
+ azArg[1], isWO ? "table" : "index"
|
|
);
|
|
}
|
|
}else{
|
|
@@ -16472,6 +16909,34 @@
|
|
}
|
|
}else
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+ if( c=='o' && strcmp(azArg[0],"oom")==0 ){
|
|
+ int i;
|
|
+ for(i=1; i<nArg; i++){
|
|
+ const char *z = azArg[i];
|
|
+ if( z[0]=='-' && z[1]=='-' ) z++;
|
|
+ if( strcmp(z,"-repeat")==0 ){
|
|
+ if( i==nArg-1 ){
|
|
+ raw_printf(p->out, "missing argument on \"%s\"\n", azArg[i]);
|
|
+ rc = 1;
|
|
+ }else{
|
|
+ oomRepeat = (int)integerValue(azArg[++i]);
|
|
+ }
|
|
+ }else if( IsDigit(z[0]) ){
|
|
+ oomCounter = (int)integerValue(azArg[i]);
|
|
+ }else{
|
|
+ raw_printf(p->out, "unknown argument: \"%s\"\n", azArg[i]);
|
|
+ raw_printf(p->out, "Usage: .oom [--repeat N] [M]\n");
|
|
+ rc = 1;
|
|
+ }
|
|
+ }
|
|
+ if( rc==0 ){
|
|
+ raw_printf(p->out, "oomCounter = %d\n", oomCounter);
|
|
+ raw_printf(p->out, "oomRepeat = %d\n", oomRepeat);
|
|
+ }
|
|
+ }else
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
|
|
char *zNewFilename; /* Name of the database file to open */
|
|
int iName = 1; /* Index in azArg[] of the filename */
|
|
@@ -16484,6 +16949,7 @@
|
|
sqlite3_free(p->zFreeOnClose);
|
|
p->zFreeOnClose = 0;
|
|
p->openMode = SHELL_OPEN_UNSPEC;
|
|
+ p->openFlags = 0;
|
|
p->szMax = 0;
|
|
/* Check for command-line arguments */
|
|
for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
|
|
@@ -16498,6 +16964,8 @@
|
|
p->openMode = SHELL_OPEN_APPENDVFS;
|
|
}else if( optionMatch(z, "readonly") ){
|
|
p->openMode = SHELL_OPEN_READONLY;
|
|
+ }else if( optionMatch(z, "nofollow") ){
|
|
+ p->openFlags |= SQLITE_OPEN_NOFOLLOW;
|
|
#ifdef SQLITE_ENABLE_DESERIALIZE
|
|
}else if( optionMatch(z, "deserialize") ){
|
|
p->openMode = SHELL_OPEN_DESERIALIZE;
|
|
@@ -16536,42 +17004,66 @@
|
|
&& (strncmp(azArg[0], "output", n)==0||strncmp(azArg[0], "once", n)==0))
|
|
|| (c=='e' && n==5 && strcmp(azArg[0],"excel")==0)
|
|
){
|
|
- const char *zFile = nArg>=2 ? azArg[1] : "stdout";
|
|
+ const char *zFile = 0;
|
|
int bTxtMode = 0;
|
|
- if( azArg[0][0]=='e' ){
|
|
- /* Transform the ".excel" command into ".once -x" */
|
|
- nArg = 2;
|
|
- azArg[0] = "once";
|
|
- zFile = azArg[1] = "-x";
|
|
- n = 4;
|
|
- }
|
|
- if( nArg>2 ){
|
|
- utf8_printf(stderr, "Usage: .%s [-e|-x|FILE]\n", azArg[0]);
|
|
- rc = 1;
|
|
- goto meta_command_exit;
|
|
+ int i;
|
|
+ int eMode = 0;
|
|
+ int bBOM = 0;
|
|
+ int bOnce = 0; /* 0: .output, 1: .once, 2: .excel */
|
|
+
|
|
+ if( c=='e' ){
|
|
+ eMode = 'x';
|
|
+ bOnce = 2;
|
|
+ }else if( strncmp(azArg[0],"once",n)==0 ){
|
|
+ bOnce = 1;
|
|
}
|
|
- if( n>1 && strncmp(azArg[0], "once", n)==0 ){
|
|
- if( nArg<2 ){
|
|
- raw_printf(stderr, "Usage: .once (-e|-x|FILE)\n");
|
|
+ for(i=1; i<nArg; i++){
|
|
+ char *z = azArg[i];
|
|
+ if( z[0]=='-' ){
|
|
+ if( z[1]=='-' ) z++;
|
|
+ if( strcmp(z,"-bom")==0 ){
|
|
+ bBOM = 1;
|
|
+ }else if( c!='e' && strcmp(z,"-x")==0 ){
|
|
+ eMode = 'x'; /* spreadsheet */
|
|
+ }else if( c!='e' && strcmp(z,"-e")==0 ){
|
|
+ eMode = 'e'; /* text editor */
|
|
+ }else{
|
|
+ utf8_printf(p->out, "ERROR: unknown option: \"%s\". Usage:\n",
|
|
+ azArg[i]);
|
|
+ showHelp(p->out, azArg[0]);
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ }else if( zFile==0 ){
|
|
+ zFile = z;
|
|
+ }else{
|
|
+ utf8_printf(p->out,"ERROR: extra parameter: \"%s\". Usage:\n",
|
|
+ azArg[i]);
|
|
+ showHelp(p->out, azArg[0]);
|
|
rc = 1;
|
|
goto meta_command_exit;
|
|
}
|
|
+ }
|
|
+ if( zFile==0 ) zFile = "stdout";
|
|
+ if( bOnce ){
|
|
p->outCount = 2;
|
|
}else{
|
|
p->outCount = 0;
|
|
}
|
|
output_reset(p);
|
|
- if( zFile[0]=='-' && zFile[1]=='-' ) zFile++;
|
|
#ifndef SQLITE_NOHAVE_SYSTEM
|
|
- if( strcmp(zFile, "-e")==0 || strcmp(zFile, "-x")==0 ){
|
|
+ if( eMode=='e' || eMode=='x' ){
|
|
p->doXdgOpen = 1;
|
|
outputModePush(p);
|
|
- if( zFile[1]=='x' ){
|
|
+ if( eMode=='x' ){
|
|
+ /* spreadsheet mode. Output as CSV. */
|
|
newTempFile(p, "csv");
|
|
+ ShellClearFlag(p, SHFLG_Echo);
|
|
p->mode = MODE_Csv;
|
|
sqlite3_snprintf(sizeof(p->colSeparator), p->colSeparator, SEP_Comma);
|
|
sqlite3_snprintf(sizeof(p->rowSeparator), p->rowSeparator, SEP_CrLf);
|
|
}else{
|
|
+ /* text editor mode */
|
|
newTempFile(p, "txt");
|
|
bTxtMode = 1;
|
|
}
|
|
@@ -16590,6 +17082,7 @@
|
|
p->out = stdout;
|
|
rc = 1;
|
|
}else{
|
|
+ if( bBOM ) fprintf(p->out,"\357\273\277");
|
|
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
|
}
|
|
#endif
|
|
@@ -16602,6 +17095,7 @@
|
|
p->out = stdout;
|
|
rc = 1;
|
|
} else {
|
|
+ if( bBOM ) fprintf(p->out,"\357\273\277");
|
|
sqlite3_snprintf(sizeof(p->outfile), p->outfile, "%s", zFile);
|
|
}
|
|
}
|
|
@@ -16615,12 +17109,8 @@
|
|
** Clear all bind parameters by dropping the TEMP table that holds them.
|
|
*/
|
|
if( nArg==2 && strcmp(azArg[1],"clear")==0 ){
|
|
- int wrSchema = 0;
|
|
- sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, -1, &wrSchema);
|
|
- sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, 1, 0);
|
|
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp.sqlite_parameters;",
|
|
0, 0, 0);
|
|
- sqlite3_db_config(p->db, SQLITE_DBCONFIG_WRITABLE_SCHEMA, wrSchema, 0);
|
|
}else
|
|
|
|
/* .parameter list
|
|
@@ -16933,7 +17423,7 @@
|
|
zDiv = " UNION ALL ";
|
|
appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
|
|
if( sqlite3_stricmp(zDb, "main")!=0 ){
|
|
- appendText(&sSelect, zDb, '"');
|
|
+ appendText(&sSelect, zDb, '\'');
|
|
}else{
|
|
appendText(&sSelect, "NULL", 0);
|
|
}
|
|
@@ -16942,15 +17432,16 @@
|
|
appendText(&sSelect, " AS snum, ", 0);
|
|
appendText(&sSelect, zDb, '\'');
|
|
appendText(&sSelect, " AS sname FROM ", 0);
|
|
- appendText(&sSelect, zDb, '"');
|
|
+ appendText(&sSelect, zDb, quoteChar(zDb));
|
|
appendText(&sSelect, ".sqlite_master", 0);
|
|
}
|
|
sqlite3_finalize(pStmt);
|
|
-#ifdef SQLITE_INTROSPECTION_PRAGMAS
|
|
+#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
|
if( zName ){
|
|
appendText(&sSelect,
|
|
" UNION ALL SELECT shell_module_schema(name),"
|
|
- " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);
|
|
+ " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
|
|
+ 0);
|
|
}
|
|
#endif
|
|
appendText(&sSelect, ") WHERE ", 0);
|
|
@@ -17049,7 +17540,8 @@
|
|
if( pSession->p==0 ) goto session_not_open;
|
|
out = fopen(azCmd[1], "wb");
|
|
if( out==0 ){
|
|
- utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);
|
|
+ utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
|
|
+ azCmd[1]);
|
|
}else{
|
|
int szChng;
|
|
void *pChng;
|
|
@@ -17370,8 +17862,7 @@
|
|
{
|
|
utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
|
|
azArg[i], azArg[0]);
|
|
- raw_printf(stderr, "Should be one of: --schema"
|
|
- " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n");
|
|
+ showHelp(p->out, azArg[0]);
|
|
rc = 1;
|
|
goto meta_command_exit;
|
|
}
|
|
@@ -17417,8 +17908,7 @@
|
|
}else if( strcmp(zTab, "sqlite_stat1")==0 ){
|
|
appendText(&sQuery,"SELECT tbl,idx,stat FROM sqlite_stat1"
|
|
" ORDER BY tbl,idx;", 0);
|
|
- }else if( strcmp(zTab, "sqlite_stat3")==0
|
|
- || strcmp(zTab, "sqlite_stat4")==0 ){
|
|
+ }else if( strcmp(zTab, "sqlite_stat4")==0 ){
|
|
appendText(&sQuery, "SELECT * FROM ", 0);
|
|
appendText(&sQuery, zTab, 0);
|
|
appendText(&sQuery, " ORDER BY tbl, idx, rowid;\n", 0);
|
|
@@ -17650,25 +18140,25 @@
|
|
int ctrlCode; /* Integer code for that option */
|
|
const char *zUsage; /* Usage notes */
|
|
} aCtrl[] = {
|
|
- { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
|
|
- { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
|
|
- /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
|
|
- /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
|
|
- { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
|
|
- /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" }, */
|
|
- { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
|
|
- { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN" },
|
|
- { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
|
|
- { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
|
|
- { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
|
|
+ { "always", SQLITE_TESTCTRL_ALWAYS, "BOOLEAN" },
|
|
+ { "assert", SQLITE_TESTCTRL_ASSERT, "BOOLEAN" },
|
|
+ /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, "" },*/
|
|
+ /*{ "bitvec_test", SQLITE_TESTCTRL_BITVEC_TEST, "" },*/
|
|
+ { "byteorder", SQLITE_TESTCTRL_BYTEORDER, "" },
|
|
+ { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN" },
|
|
+ /*{ "fault_install", SQLITE_TESTCTRL_FAULT_INSTALL, "" },*/
|
|
+ { "imposter", SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
|
|
+ { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "" },
|
|
+ { "localtime_fault", SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN" },
|
|
+ { "never_corrupt", SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN" },
|
|
+ { "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK" },
|
|
#ifdef YYCOVERAGE
|
|
- { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
|
|
+ { "parser_coverage", SQLITE_TESTCTRL_PARSER_COVERAGE, "" },
|
|
#endif
|
|
- { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
|
|
- { "prng_reset", SQLITE_TESTCTRL_PRNG_RESET, "" },
|
|
- { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
|
|
- { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
|
|
- { "reserve", SQLITE_TESTCTRL_RESERVE, "BYTES-OF-RESERVE" },
|
|
+ { "pending_byte", SQLITE_TESTCTRL_PENDING_BYTE, "OFFSET " },
|
|
+ { "prng_restore", SQLITE_TESTCTRL_PRNG_RESTORE, "" },
|
|
+ { "prng_save", SQLITE_TESTCTRL_PRNG_SAVE, "" },
|
|
+ { "prng_seed", SQLITE_TESTCTRL_PRNG_SEED, "SEED ?db?" },
|
|
};
|
|
int testctrl = -1;
|
|
int iCtrl = -1;
|
|
@@ -17721,7 +18211,6 @@
|
|
|
|
/* sqlite3_test_control(int, db, int) */
|
|
case SQLITE_TESTCTRL_OPTIMIZATIONS:
|
|
- case SQLITE_TESTCTRL_RESERVE:
|
|
if( nArg==3 ){
|
|
int opt = (int)strtol(azArg[2], 0, 0);
|
|
rc2 = sqlite3_test_control(testctrl, p->db, opt);
|
|
@@ -17749,10 +18238,30 @@
|
|
}
|
|
break;
|
|
|
|
+ /* sqlite3_test_control(int, int, sqlite3*) */
|
|
+ case SQLITE_TESTCTRL_PRNG_SEED:
|
|
+ if( nArg==3 || nArg==4 ){
|
|
+ int ii = (int)integerValue(azArg[2]);
|
|
+ sqlite3 *db;
|
|
+ if( ii==0 && strcmp(azArg[2],"random")==0 ){
|
|
+ sqlite3_randomness(sizeof(ii),&ii);
|
|
+ printf("-- random seed: %d\n", ii);
|
|
+ }
|
|
+ if( nArg==3 ){
|
|
+ db = 0;
|
|
+ }else{
|
|
+ db = p->db;
|
|
+ /* Make sure the schema has been loaded */
|
|
+ sqlite3_table_column_metadata(db, 0, "x", 0, 0, 0, 0, 0, 0);
|
|
+ }
|
|
+ rc2 = sqlite3_test_control(testctrl, ii, db);
|
|
+ isOk = 3;
|
|
+ }
|
|
+ break;
|
|
+
|
|
/* sqlite3_test_control(int, int) */
|
|
case SQLITE_TESTCTRL_ASSERT:
|
|
case SQLITE_TESTCTRL_ALWAYS:
|
|
- case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
|
|
if( nArg==3 ){
|
|
int opt = booleanValue(azArg[2]);
|
|
rc2 = sqlite3_test_control(testctrl, opt);
|
|
@@ -17770,6 +18279,12 @@
|
|
}
|
|
break;
|
|
|
|
+ /* sqlite3_test_control(sqlite3*) */
|
|
+ case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS:
|
|
+ rc2 = sqlite3_test_control(testctrl, p->db);
|
|
+ isOk = 3;
|
|
+ break;
|
|
+
|
|
case SQLITE_TESTCTRL_IMPOSTER:
|
|
if( nArg==5 ){
|
|
rc2 = sqlite3_test_control(testctrl, p->db,
|
|
@@ -17790,7 +18305,7 @@
|
|
}
|
|
}
|
|
if( isOk==0 && iCtrl>=0 ){
|
|
- utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
|
|
+ utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
|
|
rc = 1;
|
|
}else if( isOk==1 ){
|
|
raw_printf(p->out, "%d\n", rc2);
|
|
@@ -17868,6 +18383,31 @@
|
|
}else
|
|
#endif /* !defined(SQLITE_OMIT_TRACE) */
|
|
|
|
+#if defined(SQLITE_DEBUG) && !defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
+ if( c=='u' && strncmp(azArg[0], "unmodule", n)==0 ){
|
|
+ int ii;
|
|
+ int lenOpt;
|
|
+ char *zOpt;
|
|
+ if( nArg<2 ){
|
|
+ raw_printf(stderr, "Usage: .unmodule [--allexcept] NAME ...\n");
|
|
+ rc = 1;
|
|
+ goto meta_command_exit;
|
|
+ }
|
|
+ open_db(p, 0);
|
|
+ zOpt = azArg[1];
|
|
+ if( zOpt[0]=='-' && zOpt[1]=='-' && zOpt[2]!=0 ) zOpt++;
|
|
+ lenOpt = (int)strlen(zOpt);
|
|
+ if( lenOpt>=3 && strncmp(zOpt, "-allexcept",lenOpt)==0 ){
|
|
+ assert( azArg[nArg]==0 );
|
|
+ sqlite3_drop_modules(p->db, nArg>2 ? (const char**)(azArg+2) : 0);
|
|
+ }else{
|
|
+ for(ii=1; ii<nArg; ii++){
|
|
+ sqlite3_create_module(p->db, azArg[ii], 0, 0);
|
|
+ }
|
|
+ }
|
|
+ }else
|
|
+#endif
|
|
+
|
|
#if SQLITE_USER_AUTHENTICATION
|
|
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
|
|
if( nArg<2 ){
|
|
@@ -17882,7 +18422,8 @@
|
|
rc = 1;
|
|
goto meta_command_exit;
|
|
}
|
|
- rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));
|
|
+ rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
|
|
+ strlen30(azArg[3]));
|
|
if( rc ){
|
|
utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
|
|
rc = 1;
|
|
@@ -18374,6 +18915,7 @@
|
|
" -multiplex enable the multiplexor VFS\n"
|
|
#endif
|
|
" -newline SEP set output row separator. Default: '\\n'\n"
|
|
+ " -nofollow refuse to open symbolic links to database files\n"
|
|
" -nullvalue TEXT set text string for NULL values. Default ''\n"
|
|
" -pagecache SIZE N use N slots of SZ bytes each for page cache memory\n"
|
|
" -quote set output mode to 'quote'\n"
|
|
@@ -18440,14 +18982,18 @@
|
|
*/
|
|
#ifdef _WIN32
|
|
static void printBold(const char *zText){
|
|
+#if !SQLITE_OS_WINRT
|
|
HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
|
|
CONSOLE_SCREEN_BUFFER_INFO defaultScreenInfo;
|
|
GetConsoleScreenBufferInfo(out, &defaultScreenInfo);
|
|
SetConsoleTextAttribute(out,
|
|
FOREGROUND_RED|FOREGROUND_INTENSITY
|
|
);
|
|
+#endif
|
|
printf("%s", zText);
|
|
+#if !SQLITE_OS_WINRT
|
|
SetConsoleTextAttribute(out, defaultScreenInfo.wAttributes);
|
|
+#endif
|
|
}
|
|
#else
|
|
static void printBold(const char *zText){
|
|
@@ -18502,6 +19048,10 @@
|
|
stdin_is_interactive = isatty(0);
|
|
stdout_is_console = isatty(1);
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+ registerOomSimulator();
|
|
+#endif
|
|
+
|
|
#if !defined(_WIN32_WCE)
|
|
if( getenv("SQLITE_DEBUG_BREAK") ){
|
|
if( isatty(0) && isatty(2) ){
|
|
@@ -18511,7 +19061,11 @@
|
|
fgetc(stdin);
|
|
}else{
|
|
#if defined(_WIN32) || defined(WIN32)
|
|
+#if SQLITE_OS_WINRT
|
|
+ __debugbreak();
|
|
+#else
|
|
DebugBreak();
|
|
+#endif
|
|
#elif defined(SIGTRAP)
|
|
raise(SIGTRAP);
|
|
#endif
|
|
@@ -18684,6 +19238,8 @@
|
|
#endif
|
|
}else if( strcmp(z,"-readonly")==0 ){
|
|
data.openMode = SHELL_OPEN_READONLY;
|
|
+ }else if( strcmp(z,"-nofollow")==0 ){
|
|
+ data.openFlags = SQLITE_OPEN_NOFOLLOW;
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
|
|
}else if( strncmp(z, "-A",2)==0 ){
|
|
/* All remaining command-line arguments are passed to the ".archive"
|
|
@@ -18787,6 +19343,8 @@
|
|
#endif
|
|
}else if( strcmp(z,"-readonly")==0 ){
|
|
data.openMode = SHELL_OPEN_READONLY;
|
|
+ }else if( strcmp(z,"-nofollow")==0 ){
|
|
+ data.openFlags |= SQLITE_OPEN_NOFOLLOW;
|
|
}else if( strcmp(z,"-ascii")==0 ){
|
|
data.mode = MODE_Ascii;
|
|
sqlite3_snprintf(sizeof(data.colSeparator), data.colSeparator,
|
|
--- contrib/sqlite3/sqlite3.c.orig
|
|
+++ contrib/sqlite3/sqlite3.c
|
|
@@ -1,6 +1,6 @@
|
|
/******************************************************************************
|
|
** This file is an amalgamation of many separate C source files from SQLite
|
|
-** version 3.29.0. By combining all the individual C code files into this
|
|
+** version 3.32.2. By combining all the individual C code files into this
|
|
** single large file, the entire code can be compiled as a single translation
|
|
** unit. This allows many compilers to do optimizations that would not be
|
|
** possible if the files were compiled separately. Performance improvements
|
|
@@ -218,6 +218,9 @@
|
|
#if SQLITE_ENABLE_BATCH_ATOMIC_WRITE
|
|
"ENABLE_BATCH_ATOMIC_WRITE",
|
|
#endif
|
|
+#if SQLITE_ENABLE_BYTECODE_VTAB
|
|
+ "ENABLE_BYTECODE_VTAB",
|
|
+#endif
|
|
#if SQLITE_ENABLE_CEROD
|
|
"ENABLE_CEROD=" CTIMEOPT_VAL(SQLITE_ENABLE_CEROD),
|
|
#endif
|
|
@@ -331,8 +334,6 @@
|
|
#endif
|
|
#if defined(SQLITE_ENABLE_STAT4)
|
|
"ENABLE_STAT4",
|
|
-#elif defined(SQLITE_ENABLE_STAT3)
|
|
- "ENABLE_STAT3",
|
|
#endif
|
|
#if SQLITE_ENABLE_STMTVTAB
|
|
"ENABLE_STMTVTAB",
|
|
@@ -382,9 +383,6 @@
|
|
#if SQLITE_FTS5_NO_WITHOUT_ROWID
|
|
"FTS5_NO_WITHOUT_ROWID",
|
|
#endif
|
|
-#if SQLITE_HAS_CODEC
|
|
- "HAS_CODEC",
|
|
-#endif
|
|
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
|
|
"HAVE_ISNAN",
|
|
#endif
|
|
@@ -541,9 +539,6 @@
|
|
#if SQLITE_OMIT_BLOB_LITERAL
|
|
"OMIT_BLOB_LITERAL",
|
|
#endif
|
|
-#if SQLITE_OMIT_BTREECOUNT
|
|
- "OMIT_BTREECOUNT",
|
|
-#endif
|
|
#if SQLITE_OMIT_CAST
|
|
"OMIT_CAST",
|
|
#endif
|
|
@@ -1167,9 +1162,9 @@
|
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
*/
|
|
-#define SQLITE_VERSION "3.29.0"
|
|
-#define SQLITE_VERSION_NUMBER 3029000
|
|
-#define SQLITE_SOURCE_ID "2019-07-10 17:32:03 fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6"
|
|
+#define SQLITE_VERSION "3.32.2"
|
|
+#define SQLITE_VERSION_NUMBER 3032002
|
|
+#define SQLITE_SOURCE_ID "2020-06-04 12:58:43 ec02243ea6ce33b090870ae55ab8aa2534b54d216d45c4aa2fdbb00e86861e8c"
|
|
|
|
/*
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -1343,26 +1338,22 @@
|
|
** the [sqlite3] object is successfully destroyed and all associated
|
|
** resources are deallocated.
|
|
**
|
|
-** ^If the database connection is associated with unfinalized prepared
|
|
-** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
|
-** will leave the database connection open and return [SQLITE_BUSY].
|
|
-** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
|
-** and/or unfinished sqlite3_backups, then the database connection becomes
|
|
-** an unusable "zombie" which will automatically be deallocated when the
|
|
-** last prepared statement is finalized or the last sqlite3_backup is
|
|
-** finished. The sqlite3_close_v2() interface is intended for use with
|
|
-** host languages that are garbage collected, and where the order in which
|
|
-** destructors are called is arbitrary.
|
|
-**
|
|
-** Applications should [sqlite3_finalize | finalize] all [prepared statements],
|
|
-** [sqlite3_blob_close | close] all [BLOB handles], and
|
|
+** Ideally, applications should [sqlite3_finalize | finalize] all
|
|
+** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
|
|
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
|
|
-** with the [sqlite3] object prior to attempting to close the object. ^If
|
|
-** sqlite3_close_v2() is called on a [database connection] that still has
|
|
-** outstanding [prepared statements], [BLOB handles], and/or
|
|
-** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
|
|
-** of resources is deferred until all [prepared statements], [BLOB handles],
|
|
-** and [sqlite3_backup] objects are also destroyed.
|
|
+** with the [sqlite3] object prior to attempting to close the object.
|
|
+** ^If the database connection is associated with unfinalized prepared
|
|
+** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
|
|
+** sqlite3_close() will leave the database connection open and return
|
|
+** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
|
|
+** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
|
|
+** it returns [SQLITE_OK] regardless, but instead of deallocating the database
|
|
+** connection immediately, it marks the database connection as an unusable
|
|
+** "zombie" and makes arrangements to automatically deallocate the database
|
|
+** connection after all prepared statements are finalized, all BLOB handles
|
|
+** are closed, and all backups have finished. The sqlite3_close_v2() interface
|
|
+** is intended for use with host languages that are garbage collected, and
|
|
+** where the order in which destructors are called is arbitrary.
|
|
**
|
|
** ^If an [sqlite3] object is destroyed while a transaction is open,
|
|
** the transaction is automatically rolled back.
|
|
@@ -1551,17 +1542,21 @@
|
|
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
|
|
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
|
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
|
+#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
|
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
|
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
|
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
|
+#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
|
|
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
|
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
|
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
|
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
|
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
|
|
+#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
|
|
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
|
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
|
+#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
|
|
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
|
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
|
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
|
@@ -1579,11 +1574,13 @@
|
|
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
|
|
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
|
|
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
|
|
+#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
|
|
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
|
|
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
|
|
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
|
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
|
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
|
|
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
|
|
|
|
/*
|
|
** CAPI3REF: Flags For File Open Operations
|
|
@@ -1612,6 +1609,7 @@
|
|
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
|
+#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
|
|
|
|
/* Reserved: 0x00F00000 */
|
|
|
|
@@ -2023,16 +2021,16 @@
|
|
** ^The [SQLITE_FCNTL_BUSYHANDLER]
|
|
** file-control may be invoked by SQLite on the database file handle
|
|
** shortly after it is opened in order to provide a custom VFS with access
|
|
-** to the connections busy-handler callback. The argument is of type (void **)
|
|
+** to the connection's busy-handler callback. The argument is of type (void**)
|
|
** - an array of two (void *) values. The first (void *) actually points
|
|
-** to a function of type (int (*)(void *)). In order to invoke the connections
|
|
+** to a function of type (int (*)(void *)). In order to invoke the connection's
|
|
** busy-handler, this function should be invoked with the second (void *) in
|
|
** the array as the only argument. If it returns non-zero, then the operation
|
|
** should be retried. If it returns zero, the custom VFS should abandon the
|
|
** current operation.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
|
|
-** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
|
|
+** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
|
|
** to have SQLite generate a
|
|
** temporary filename using the same algorithm that is followed to generate
|
|
** temporary filenames for TEMP tables and other internal uses. The
|
|
@@ -2127,10 +2125,12 @@
|
|
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
|
|
-** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
|
|
-** a file lock using the xLock or xShmLock methods of the VFS to wait
|
|
-** for up to M milliseconds before failing, where M is the single
|
|
-** unsigned integer parameter.
|
|
+** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS
|
|
+** to block for up to M milliseconds before failing when attempting to
|
|
+** obtain a file lock using the xLock or xShmLock methods of the VFS.
|
|
+** The parameter is a pointer to a 32-bit signed integer that contains
|
|
+** the value that M is to be set to. Before returning, the 32-bit signed
|
|
+** integer is overwritten with the previous value of M.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
|
|
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
|
|
@@ -2145,12 +2145,23 @@
|
|
** not provide a mechanism to detect changes to MAIN only. Also, the
|
|
** [sqlite3_total_changes()] interface responds to internal changes only and
|
|
** omits changes made by other database connections. The
|
|
-** [PRAGMA data_version] command provide a mechanism to detect changes to
|
|
+** [PRAGMA data_version] command provides a mechanism to detect changes to
|
|
** a single attached database that occur due to other database connections,
|
|
** but omits changes implemented by the database connection on which it is
|
|
** called. This file control is the only mechanism to detect changes that
|
|
** happen either internally or externally and that are associated with
|
|
** a particular attached database.
|
|
+**
|
|
+** <li>[[SQLITE_FCNTL_CKPT_START]]
|
|
+** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
|
|
+** in wal mode before the client starts to copy pages from the wal
|
|
+** file to the database file.
|
|
+**
|
|
+** <li>[[SQLITE_FCNTL_CKPT_DONE]]
|
|
+** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
|
|
+** in wal mode after the client has finished copying pages from the wal
|
|
+** file to the database file, but before the *-shm file is updated to
|
|
+** record the fact that the pages have been checkpointed.
|
|
** </ul>
|
|
*/
|
|
#define SQLITE_FCNTL_LOCKSTATE 1
|
|
@@ -2188,6 +2199,9 @@
|
|
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
|
|
#define SQLITE_FCNTL_DATA_VERSION 35
|
|
#define SQLITE_FCNTL_SIZE_LIMIT 36
|
|
+#define SQLITE_FCNTL_CKPT_DONE 37
|
|
+#define SQLITE_FCNTL_RESERVE_BYTES 38
|
|
+#define SQLITE_FCNTL_CKPT_START 39
|
|
|
|
/* deprecated names */
|
|
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
|
@@ -2233,10 +2247,10 @@
|
|
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
|
|
** may be appended to the sqlite3_vfs object and the iVersion value
|
|
** may increase again in future versions of SQLite.
|
|
-** Note that the structure
|
|
-** of the sqlite3_vfs object changes in the transition from
|
|
+** Note that due to an oversight, the structure
|
|
+** of the sqlite3_vfs object changed in the transition from
|
|
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
|
|
-** and yet the iVersion field was not modified.
|
|
+** and yet the iVersion field was not increased.
|
|
**
|
|
** The szOsFile field is the size of the subclassed [sqlite3_file]
|
|
** structure used by this VFS. mxPathname is the maximum length of
|
|
@@ -2327,7 +2341,7 @@
|
|
** for exclusive access.
|
|
**
|
|
** ^At least szOsFile bytes of memory are allocated by SQLite
|
|
-** to hold the [sqlite3_file] structure passed as the third
|
|
+** to hold the [sqlite3_file] structure passed as the third
|
|
** argument to xOpen. The xOpen method does not have to
|
|
** allocate the structure; it should just fill it in. Note that
|
|
** the xOpen method must set the sqlite3_file.pMethods to either
|
|
@@ -2664,7 +2678,7 @@
|
|
** that causes the corresponding memory allocation to fail.
|
|
**
|
|
** The xInit method initializes the memory allocator. For example,
|
|
-** it might allocate any require mutexes or initialize internal data
|
|
+** it might allocate any required mutexes or initialize internal data
|
|
** structures. The xShutdown method is invoked (indirectly) by
|
|
** [sqlite3_shutdown()] and should deallocate any resources acquired
|
|
** by xInit. The pAppData pointer is used as the only parameter to
|
|
@@ -2786,6 +2800,7 @@
|
|
** memory allocation statistics. ^(When memory allocation statistics are
|
|
** disabled, the following SQLite interfaces become non-operational:
|
|
** <ul>
|
|
+** <li> [sqlite3_hard_heap_limit64()]
|
|
** <li> [sqlite3_memory_used()]
|
|
** <li> [sqlite3_memory_highwater()]
|
|
** <li> [sqlite3_soft_heap_limit64()]
|
|
@@ -2804,7 +2819,7 @@
|
|
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
|
|
** that SQLite can use for the database page cache with the default page
|
|
** cache implementation.
|
|
-** This configuration option is a no-op if an application-define page
|
|
+** This configuration option is a no-op if an application-defined page
|
|
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
|
|
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
|
|
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
|
|
@@ -3137,6 +3152,17 @@
|
|
** following this call. The second parameter may be a NULL pointer, in
|
|
** which case the trigger setting is not reported back. </dd>
|
|
**
|
|
+** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
|
|
+** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
|
|
+** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
|
|
+** There should be two additional arguments.
|
|
+** The first argument is an integer which is 0 to disable views,
|
|
+** positive to enable views or negative to leave the setting unchanged.
|
|
+** The second parameter is a pointer to an integer into which
|
|
+** is written 0 or 1 to indicate whether views are disabled or enabled
|
|
+** following this call. The second parameter may be a NULL pointer, in
|
|
+** which case the view setting is not reported back. </dd>
|
|
+**
|
|
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
|
** <dd> ^This option is used to enable or disable the
|
|
@@ -3278,7 +3304,7 @@
|
|
** [[SQLITE_DBCONFIG_DQS_DML]]
|
|
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
|
|
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
|
|
-** the legacy [double-quoted string literal] misfeature for DML statement
|
|
+** the legacy [double-quoted string literal] misfeature for DML statements
|
|
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
|
|
** default value of this setting is determined by the [-DSQLITE_DQS]
|
|
** compile-time option.
|
|
@@ -3292,6 +3318,49 @@
|
|
** default value of this setting is determined by the [-DSQLITE_DQS]
|
|
** compile-time option.
|
|
** </dd>
|
|
+**
|
|
+** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
|
|
+** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
|
|
+** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
|
|
+** assume that database schemas (the contents of the [sqlite_master] tables)
|
|
+** are untainted by malicious content.
|
|
+** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
|
|
+** takes additional defensive steps to protect the application from harm
|
|
+** including:
|
|
+** <ul>
|
|
+** <li> Prohibit the use of SQL functions inside triggers, views,
|
|
+** CHECK constraints, DEFAULT clauses, expression indexes,
|
|
+** partial indexes, or generated columns
|
|
+** unless those functions are tagged with [SQLITE_INNOCUOUS].
|
|
+** <li> Prohibit the use of virtual tables inside of triggers or views
|
|
+** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
|
|
+** </ul>
|
|
+** This setting defaults to "on" for legacy compatibility, however
|
|
+** all applications are advised to turn it off if possible. This setting
|
|
+** can also be controlled using the [PRAGMA trusted_schema] statement.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
|
|
+** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
|
|
+** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
|
|
+** the legacy file format flag. When activated, this flag causes all newly
|
|
+** created database file to have a schema format version number (the 4-byte
|
|
+** integer found at offset 44 into the database header) of 1. This in turn
|
|
+** means that the resulting database file will be readable and writable by
|
|
+** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
|
|
+** newly created databases are generally not understandable by SQLite versions
|
|
+** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
|
|
+** is now scarcely any need to generated database files that are compatible
|
|
+** all the way back to version 3.0.0, and so this setting is of little
|
|
+** practical use, but is provided so that SQLite can continue to claim the
|
|
+** ability to generate new database files that are compatible with version
|
|
+** 3.0.0.
|
|
+** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
|
|
+** the [VACUUM] command will fail with an obscure error when attempting to
|
|
+** process a table with generated columns and a descending index. This is
|
|
+** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
|
+** either generated columns or decending indexes.
|
|
+** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
|
@@ -3309,7 +3378,10 @@
|
|
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */
|
|
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
|
|
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
|
|
-#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */
|
|
+#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
|
|
+#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
|
|
+#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
|
|
+#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */
|
|
|
|
/*
|
|
** CAPI3REF: Enable Or Disable Extended Result Codes
|
|
@@ -3515,7 +3587,7 @@
|
|
** ^The sqlite3_interrupt(D) call is in effect until all currently running
|
|
** SQL statements on [database connection] D complete. ^Any new SQL statements
|
|
** that are started after the sqlite3_interrupt() call and before the
|
|
-** running statements reaches zero are interrupted as if they had been
|
|
+** running statement count reaches zero are interrupted as if they had been
|
|
** running prior to the sqlite3_interrupt() call. ^New SQL statements
|
|
** that are started after the running statement count reaches zero are
|
|
** not effected by the sqlite3_interrupt().
|
|
@@ -3683,9 +3755,9 @@
|
|
** Cindy | 21
|
|
** </pre></blockquote>
|
|
**
|
|
-** There are two column (M==2) and three rows (N==3). Thus the
|
|
+** There are two columns (M==2) and three rows (N==3). Thus the
|
|
** result table has 8 entries. Suppose the result table is stored
|
|
-** in an array names azResult. Then azResult holds this content:
|
|
+** in an array named azResult. Then azResult holds this content:
|
|
**
|
|
** <blockquote><pre>
|
|
** azResult[0] = "Name";
|
|
@@ -3778,7 +3850,7 @@
|
|
**
|
|
** The SQLite core uses these three routines for all of its own
|
|
** internal memory allocation needs. "Core" in the previous sentence
|
|
-** does not include operating-system specific VFS implementation. The
|
|
+** does not include operating-system specific [VFS] implementation. The
|
|
** Windows VFS uses native malloc() and free() for some operations.
|
|
**
|
|
** ^The sqlite3_malloc() routine returns a pointer to a block
|
|
@@ -3839,19 +3911,6 @@
|
|
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
|
|
** option is used.
|
|
**
|
|
-** In SQLite version 3.5.0 and 3.5.1, it was possible to define
|
|
-** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
|
|
-** implementation of these routines to be omitted. That capability
|
|
-** is no longer provided. Only built-in memory allocators can be used.
|
|
-**
|
|
-** Prior to SQLite version 3.7.10, the Windows OS interface layer called
|
|
-** the system malloc() and free() directly when converting
|
|
-** filenames between the UTF-8 encoding used by SQLite
|
|
-** and whatever filename encoding is used by the particular Windows
|
|
-** installation. Memory allocation errors were detected, but
|
|
-** they were reported back as [SQLITE_CANTOPEN] or
|
|
-** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
|
|
-**
|
|
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
|
|
** must be either NULL or else pointers obtained from a prior
|
|
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
|
|
@@ -3900,7 +3959,7 @@
|
|
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
|
|
** select random [ROWID | ROWIDs] when inserting new records into a table that
|
|
** already uses the largest possible [ROWID]. The PRNG is also used for
|
|
-** the build-in random() and randomblob() SQL functions. This interface allows
|
|
+** the built-in random() and randomblob() SQL functions. This interface allows
|
|
** applications to access the same PRNG for other purposes.
|
|
**
|
|
** ^A call to this routine stores N bytes of randomness into buffer P.
|
|
@@ -4274,10 +4333,8 @@
|
|
** The sqlite3_open_v2() interface works like sqlite3_open()
|
|
** except that it accepts two additional parameters for additional control
|
|
** over the new database connection. ^(The flags parameter to
|
|
-** sqlite3_open_v2() can take one of
|
|
-** the following three values, optionally combined with the
|
|
-** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
|
|
-** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
|
|
+** sqlite3_open_v2() must include, at a minimum, one of the following
|
|
+** three flag combinations:)^
|
|
**
|
|
** <dl>
|
|
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
|
|
@@ -4295,23 +4352,51 @@
|
|
** sqlite3_open() and sqlite3_open16().</dd>)^
|
|
** </dl>
|
|
**
|
|
+** In addition to the required flags, the following optional flags are
|
|
+** also supported:
|
|
+**
|
|
+** <dl>
|
|
+** ^(<dt>[SQLITE_OPEN_URI]</dt>
|
|
+** <dd>The filename can be interpreted as a URI if this flag is set.</dd>)^
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_MEMORY]</dt>
|
|
+** <dd>The database will be opened as an in-memory database. The database
|
|
+** is named by the "filename" argument for the purposes of cache-sharing,
|
|
+** if shared cache mode is enabled, but the "filename" is otherwise ignored.
|
|
+** </dd>)^
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_NOMUTEX]</dt>
|
|
+** <dd>The new database connection will use the "multi-thread"
|
|
+** [threading mode].)^ This means that separate threads are allowed
|
|
+** to use SQLite at the same time, as long as each thread is using
|
|
+** a different [database connection].
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_FULLMUTEX]</dt>
|
|
+** <dd>The new database connection will use the "serialized"
|
|
+** [threading mode].)^ This means the multiple threads can safely
|
|
+** attempt to use the same database connection at the same time.
|
|
+** (Mutexes will block any actual concurrency, but in this mode
|
|
+** there is no harm in trying.)
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
|
|
+** <dd>The database is opened [shared cache] enabled, overriding
|
|
+** the default shared cache setting provided by
|
|
+** [sqlite3_enable_shared_cache()].)^
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
|
|
+** <dd>The database is opened [shared cache] disabled, overriding
|
|
+** the default shared cache setting provided by
|
|
+** [sqlite3_enable_shared_cache()].)^
|
|
+**
|
|
+** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
|
|
+** <dd>The database filename is not allowed to be a symbolic link</dd>
|
|
+** </dl>)^
|
|
+**
|
|
** If the 3rd parameter to sqlite3_open_v2() is not one of the
|
|
-** combinations shown above optionally combined with other
|
|
+** required combinations shown above optionally combined with other
|
|
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
|
|
** then the behavior is undefined.
|
|
**
|
|
-** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
|
|
-** opens in the multi-thread [threading mode] as long as the single-thread
|
|
-** mode has not been set at compile-time or start-time. ^If the
|
|
-** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
|
|
-** in the serialized [threading mode] unless single-thread was
|
|
-** previously selected at compile-time or start-time.
|
|
-** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
|
|
-** eligible to use [shared cache mode], regardless of whether or not shared
|
|
-** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
|
|
-** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
|
|
-** participate in [shared cache mode] even if it is enabled.
|
|
-**
|
|
** ^The fourth parameter to sqlite3_open_v2() is the name of the
|
|
** [sqlite3_vfs] object that defines the operating system interface that
|
|
** the new database connection should use. ^If the fourth parameter is
|
|
@@ -4491,17 +4576,27 @@
|
|
/*
|
|
** CAPI3REF: Obtain Values For URI Parameters
|
|
**
|
|
-** These are utility routines, useful to VFS implementations, that check
|
|
-** to see if a database file was a URI that contained a specific query
|
|
+** These are utility routines, useful to [VFS|custom VFS implementations],
|
|
+** that check if a database file was a URI that contained a specific query
|
|
** parameter, and if so obtains the value of that query parameter.
|
|
**
|
|
-** If F is the database filename pointer passed into the xOpen() method of
|
|
-** a VFS implementation when the flags parameter to xOpen() has one or
|
|
-** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
|
|
-** P is the name of the query parameter, then
|
|
+** The first parameter to these interfaces (hereafter referred to
|
|
+** as F) must be one of:
|
|
+** <ul>
|
|
+** <li> A database filename pointer created by the SQLite core and
|
|
+** passed into the xOpen() method of a VFS implemention, or
|
|
+** <li> A filename obtained from [sqlite3_db_filename()], or
|
|
+** <li> A new filename constructed using [sqlite3_create_filename()].
|
|
+** </ul>
|
|
+** If the F parameter is not one of the above, then the behavior is
|
|
+** undefined and probably undesirable. Older versions of SQLite were
|
|
+** more tolerant of invalid F parameters than newer versions.
|
|
+**
|
|
+** If F is a suitable filename (as described in the previous paragraph)
|
|
+** and if P is the name of the query parameter, then
|
|
** sqlite3_uri_parameter(F,P) returns the value of the P
|
|
** parameter if it exists or a NULL pointer if P does not appear as a
|
|
-** query parameter on F. If P is a query parameter of F
|
|
+** query parameter on F. If P is a query parameter of F and it
|
|
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
|
|
** a pointer to an empty string.
|
|
**
|
|
@@ -4513,26 +4608,145 @@
|
|
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
|
|
** query parameter P is one of "no", "false", or "off" in any case or
|
|
** if the value begins with a numeric zero. If P is not a query
|
|
-** parameter on F or if the value of P is does not match any of the
|
|
+** parameter on F or if the value of P does not match any of the
|
|
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
|
|
**
|
|
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
|
|
** 64-bit signed integer and returns that integer, or D if P does not
|
|
** exist. If the value of P is something other than an integer, then
|
|
** zero is returned.
|
|
+**
|
|
+** The sqlite3_uri_key(F,N) returns a pointer to the name (not
|
|
+** the value) of the N-th query parameter for filename F, or a NULL
|
|
+** pointer if N is less than zero or greater than the number of query
|
|
+** parameters minus 1. The N value is zero-based so N should be 0 to obtain
|
|
+** the name of the first query parameter, 1 for the second parameter, and
|
|
+** so forth.
|
|
**
|
|
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
|
|
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
|
|
-** is not a database file pathname pointer that SQLite passed into the xOpen
|
|
-** VFS method, then the behavior of this routine is undefined and probably
|
|
-** undesirable.
|
|
+** is not a database file pathname pointer that the SQLite core passed
|
|
+** into the xOpen VFS method, then the behavior of this routine is undefined
|
|
+** and probably undesirable.
|
|
+**
|
|
+** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
|
|
+** parameter can also be the name of a rollback journal file or WAL file
|
|
+** in addition to the main database file. Prior to version 3.31.0, these
|
|
+** routines would only work if F was the name of the main database file.
|
|
+** When the F parameter is the name of the rollback journal or WAL file,
|
|
+** it has access to all the same query parameters as were found on the
|
|
+** main database file.
|
|
**
|
|
** See the [URI filename] documentation for additional information.
|
|
*/
|
|
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
|
|
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
|
|
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
|
|
+SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
|
|
|
|
+/*
|
|
+** CAPI3REF: Translate filenames
|
|
+**
|
|
+** These routines are available to [VFS|custom VFS implementations] for
|
|
+** translating filenames between the main database file, the journal file,
|
|
+** and the WAL file.
|
|
+**
|
|
+** If F is the name of an sqlite database file, journal file, or WAL file
|
|
+** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
|
|
+** returns the name of the corresponding database file.
|
|
+**
|
|
+** If F is the name of an sqlite database file, journal file, or WAL file
|
|
+** passed by the SQLite core into the VFS, or if F is a database filename
|
|
+** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
|
|
+** returns the name of the corresponding rollback journal file.
|
|
+**
|
|
+** If F is the name of an sqlite database file, journal file, or WAL file
|
|
+** that was passed by the SQLite core into the VFS, or if F is a database
|
|
+** filename obtained from [sqlite3_db_filename()], then
|
|
+** sqlite3_filename_wal(F) returns the name of the corresponding
|
|
+** WAL file.
|
|
+**
|
|
+** In all of the above, if F is not the name of a database, journal or WAL
|
|
+** filename passed into the VFS from the SQLite core and F is not the
|
|
+** return value from [sqlite3_db_filename()], then the result is
|
|
+** undefined and is likely a memory access violation.
|
|
+*/
|
|
+SQLITE_API const char *sqlite3_filename_database(const char*);
|
|
+SQLITE_API const char *sqlite3_filename_journal(const char*);
|
|
+SQLITE_API const char *sqlite3_filename_wal(const char*);
|
|
+
|
|
+/*
|
|
+** CAPI3REF: Database File Corresponding To A Journal
|
|
+**
|
|
+** ^If X is the name of a rollback or WAL-mode journal file that is
|
|
+** passed into the xOpen method of [sqlite3_vfs], then
|
|
+** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
|
|
+** object that represents the main database file.
|
|
+**
|
|
+** This routine is intended for use in custom [VFS] implementations
|
|
+** only. It is not a general-purpose interface.
|
|
+** The argument sqlite3_file_object(X) must be a filename pointer that
|
|
+** has been passed into [sqlite3_vfs].xOpen method where the
|
|
+** flags parameter to xOpen contains one of the bits
|
|
+** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
|
|
+** of this routine results in undefined and probably undesirable
|
|
+** behavior.
|
|
+*/
|
|
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
|
+
|
|
+/*
|
|
+** CAPI3REF: Create and Destroy VFS Filenames
|
|
+**
|
|
+** These interfces are provided for use by [VFS shim] implementations and
|
|
+** are not useful outside of that context.
|
|
+**
|
|
+** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
|
|
+** database filename D with corresponding journal file J and WAL file W and
|
|
+** with N URI parameters key/values pairs in the array P. The result from
|
|
+** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
|
|
+** is safe to pass to routines like:
|
|
+** <ul>
|
|
+** <li> [sqlite3_uri_parameter()],
|
|
+** <li> [sqlite3_uri_boolean()],
|
|
+** <li> [sqlite3_uri_int64()],
|
|
+** <li> [sqlite3_uri_key()],
|
|
+** <li> [sqlite3_filename_database()],
|
|
+** <li> [sqlite3_filename_journal()], or
|
|
+** <li> [sqlite3_filename_wal()].
|
|
+** </ul>
|
|
+** If a memory allocation error occurs, sqlite3_create_filename() might
|
|
+** return a NULL pointer. The memory obtained from sqlite3_create_filename(X)
|
|
+** must be released by a corresponding call to sqlite3_free_filename(Y).
|
|
+**
|
|
+** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array
|
|
+** of 2*N pointers to strings. Each pair of pointers in this array corresponds
|
|
+** to a key and value for a query parameter. The P parameter may be a NULL
|
|
+** pointer if N is zero. None of the 2*N pointers in the P array may be
|
|
+** NULL pointers and key pointers should not be empty strings.
|
|
+** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
|
|
+** be NULL pointers, though they can be empty strings.
|
|
+**
|
|
+** The sqlite3_free_filename(Y) routine releases a memory allocation
|
|
+** previously obtained from sqlite3_create_filename(). Invoking
|
|
+** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
|
|
+**
|
|
+** If the Y parameter to sqlite3_free_filename(Y) is anything other
|
|
+** than a NULL pointer or a pointer previously acquired from
|
|
+** sqlite3_create_filename(), then bad things such as heap
|
|
+** corruption or segfaults may occur. The value Y should be
|
|
+** used again after sqlite3_free_filename(Y) has been called. This means
|
|
+** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
|
|
+** then the corresponding [sqlite3_module.xClose() method should also be
|
|
+** invoked prior to calling sqlite3_free_filename(Y).
|
|
+*/
|
|
+SQLITE_API char *sqlite3_create_filename(
|
|
+ const char *zDatabase,
|
|
+ const char *zJournal,
|
|
+ const char *zWal,
|
|
+ int nParam,
|
|
+ const char **azParam
|
|
+);
|
|
+SQLITE_API void sqlite3_free_filename(char*);
|
|
|
|
/*
|
|
** CAPI3REF: Error Codes And Messages
|
|
@@ -4850,15 +5064,15 @@
|
|
** </li>
|
|
**
|
|
** <li>
|
|
-** ^If the specific value bound to [parameter | host parameter] in the
|
|
+** ^If the specific value bound to a [parameter | host parameter] in the
|
|
** WHERE clause might influence the choice of query plan for a statement,
|
|
** then the statement will be automatically recompiled, as if there had been
|
|
-** a schema change, on the first [sqlite3_step()] call following any change
|
|
+** a schema change, on the first [sqlite3_step()] call following any change
|
|
** to the [sqlite3_bind_text | bindings] of that [parameter].
|
|
-** ^The specific value of WHERE-clause [parameter] might influence the
|
|
+** ^The specific value of a WHERE-clause [parameter] might influence the
|
|
** choice of query plan if the parameter is the left-hand side of a [LIKE]
|
|
** or [GLOB] operator or if the parameter is compared to an indexed column
|
|
-** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
|
|
+** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
|
|
** </li>
|
|
** </ol>
|
|
**
|
|
@@ -5115,12 +5329,30 @@
|
|
** [sqlite3_bind_parameter_index()] API if desired. ^The index
|
|
** for "?NNN" parameters is the value of NNN.
|
|
** ^The NNN value must be between 1 and the [sqlite3_limit()]
|
|
-** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
|
|
+** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
|
|
**
|
|
** ^The third argument is the value to bind to the parameter.
|
|
** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
|
|
** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
|
|
** is ignored and the end result is the same as sqlite3_bind_null().
|
|
+** ^If the third parameter to sqlite3_bind_text() is not NULL, then
|
|
+** it should be a pointer to well-formed UTF8 text.
|
|
+** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
|
|
+** it should be a pointer to well-formed UTF16 text.
|
|
+** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
|
|
+** it should be a pointer to a well-formed unicode string that is
|
|
+** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
|
|
+** otherwise.
|
|
+**
|
|
+** [[byte-order determination rules]] ^The byte-order of
|
|
+** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
|
|
+** found in first character, which is removed, or in the absence of a BOM
|
|
+** the byte order is the native byte order of the host
|
|
+** machine for sqlite3_bind_text16() or the byte order specified in
|
|
+** the 6th parameter for sqlite3_bind_text64().)^
|
|
+** ^If UTF16 input text contains invalid unicode
|
|
+** characters, then SQLite might change those invalid characters
|
|
+** into the unicode replacement character: U+FFFD.
|
|
**
|
|
** ^(In those routines that have a fourth argument, its value is the
|
|
** number of bytes in the parameter. To be clear: the value is the
|
|
@@ -5134,7 +5366,7 @@
|
|
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
|
|
** that parameter must be the byte offset
|
|
** where the NUL terminator would occur assuming the string were NUL
|
|
-** terminated. If any NUL characters occur at byte offsets less than
|
|
+** terminated. If any NUL characters occurs at byte offsets less than
|
|
** the value of the fourth parameter then the resulting string value will
|
|
** contain embedded NULs. The result of expressions involving strings
|
|
** with embedded NULs is undefined.
|
|
@@ -5364,7 +5596,7 @@
|
|
**
|
|
** ^If the Nth column returned by the statement is an expression or
|
|
** subquery and is not a column value, then all of these functions return
|
|
-** NULL. ^These routine might also return NULL if a memory allocation error
|
|
+** NULL. ^These routines might also return NULL if a memory allocation error
|
|
** occurs. ^Otherwise, they return the name of the attached database, table,
|
|
** or column that query result column was extracted from.
|
|
**
|
|
@@ -5374,10 +5606,6 @@
|
|
** ^These APIs are only available if the library was compiled with the
|
|
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
|
|
**
|
|
-** If two or more threads call one or more of these routines against the same
|
|
-** prepared statement and column at the same time then the results are
|
|
-** undefined.
|
|
-**
|
|
** If two or more threads call one or more
|
|
** [sqlite3_column_database_name | column metadata interfaces]
|
|
** for the same [prepared statement] and result column
|
|
@@ -5514,7 +5742,7 @@
|
|
** ^The sqlite3_data_count(P) interface returns the number of columns in the
|
|
** current row of the result set of [prepared statement] P.
|
|
** ^If prepared statement P does not have results ready to return
|
|
-** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
|
|
+** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
|
|
** interfaces) then sqlite3_data_count(P) returns 0.
|
|
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
|
|
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
|
|
@@ -5838,8 +6066,6 @@
|
|
/*
|
|
** CAPI3REF: Create Or Redefine SQL Functions
|
|
** KEYWORDS: {function creation routines}
|
|
-** KEYWORDS: {application-defined SQL function}
|
|
-** KEYWORDS: {application-defined SQL functions}
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These functions (collectively known as "function creation routines")
|
|
@@ -5893,6 +6119,23 @@
|
|
** perform additional optimizations on deterministic functions, so use
|
|
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
|
|
**
|
|
+** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
|
|
+** flag, which if present prevents the function from being invoked from
|
|
+** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
|
|
+** index expressions, or the WHERE clause of partial indexes.
|
|
+**
|
|
+** <span style="background-color:#ffff90;">
|
|
+** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
|
|
+** all application-defined SQL functions that do not need to be
|
|
+** used inside of triggers, view, CHECK constraints, or other elements of
|
|
+** the database schema. This flags is especially recommended for SQL
|
|
+** functions that have side effects or reveal internal application state.
|
|
+** Without this flag, an attacker might be able to modify the schema of
|
|
+** a database file to include invocations of the function with parameters
|
|
+** chosen by the attacker, which the application will then execute when
|
|
+** the database file is opened and read.
|
|
+** </span>
|
|
+**
|
|
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
|
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
|
**
|
|
@@ -6009,8 +6252,68 @@
|
|
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
|
|
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
|
|
** [sqlite3_create_function_v2()].
|
|
+**
|
|
+** <dl>
|
|
+** [[SQLITE_DETERMINISTIC]] <dt>SQLITE_DETERMINISTIC</dt><dd>
|
|
+** The SQLITE_DETERMINISTIC flag means that the new function always gives
|
|
+** the same output when the input parameters are the same.
|
|
+** The [abs|abs() function] is deterministic, for example, but
|
|
+** [randomblob|randomblob()] is not. Functions must
|
|
+** be deterministic in order to be used in certain contexts such as
|
|
+** with the WHERE clause of [partial indexes] or in [generated columns].
|
|
+** SQLite might also optimize deterministic functions by factoring them
|
|
+** out of inner loops.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_DIRECTONLY]] <dt>SQLITE_DIRECTONLY</dt><dd>
|
|
+** The SQLITE_DIRECTONLY flag means that the function may only be invoked
|
|
+** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
|
|
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
|
+** [expression indexes], [partial indexes], or [generated columns].
|
|
+** The SQLITE_DIRECTONLY flags is a security feature which is recommended
|
|
+** for all [application-defined SQL functions], and especially for functions
|
|
+** that have side-effects or that could potentially leak sensitive
|
|
+** information.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
|
|
+** The SQLITE_INNOCUOUS flag means that the function is unlikely
|
|
+** to cause problems even if misused. An innocuous function should have
|
|
+** no side effects and should not depend on any values other than its
|
|
+** input parameters. The [abs|abs() function] is an example of an
|
|
+** innocuous function.
|
|
+** The [load_extension() SQL function] is not innocuous because of its
|
|
+** side effects.
|
|
+** <p> SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
|
|
+** exactly the same. The [random|random() function] is an example of a
|
|
+** function that is innocuous but not deterministic.
|
|
+** <p>Some heightened security settings
|
|
+** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
|
|
+** disable the use of SQL functions inside views and triggers and in
|
|
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
|
+** [expression indexes], [partial indexes], and [generated columns] unless
|
|
+** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
|
|
+** are innocuous. Developers are advised to avoid using the
|
|
+** SQLITE_INNOCUOUS flag for application-defined functions unless the
|
|
+** function has been carefully audited and found to be free of potentially
|
|
+** security-adverse side-effects and information-leaks.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
|
|
+** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
|
|
+** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
|
|
+** Specifying this flag makes no difference for scalar or aggregate user
|
|
+** functions. However, if it is not specified for a user-defined window
|
|
+** function, then any sub-types belonging to arguments passed to the window
|
|
+** function may be discarded before the window function is called (i.e.
|
|
+** sqlite3_value_subtype() will always return 0).
|
|
+** </dd>
|
|
+** </dl>
|
|
*/
|
|
-#define SQLITE_DETERMINISTIC 0x800
|
|
+#define SQLITE_DETERMINISTIC 0x000000800
|
|
+#define SQLITE_DIRECTONLY 0x000080000
|
|
+#define SQLITE_SUBTYPE 0x000100000
|
|
+#define SQLITE_INNOCUOUS 0x000200000
|
|
|
|
/*
|
|
** CAPI3REF: Deprecated Functions
|
|
@@ -6069,8 +6372,8 @@
|
|
**
|
|
** These routines extract type, size, and content information from
|
|
** [protected sqlite3_value] objects. Protected sqlite3_value objects
|
|
-** are used to pass parameter information into implementation of
|
|
-** [application-defined SQL functions] and [virtual tables].
|
|
+** are used to pass parameter information into the functions that
|
|
+** implement [application-defined SQL functions] and [virtual tables].
|
|
**
|
|
** These routines work only with [protected sqlite3_value] objects.
|
|
** Any attempt to use these routines on an [unprotected sqlite3_value]
|
|
@@ -6127,7 +6430,7 @@
|
|
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
|
|
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
|
|
** interfaces. ^If X comes from an SQL literal value, or a table column,
|
|
-** and expression, then sqlite3_value_frombind(X) returns zero.
|
|
+** or an expression, then sqlite3_value_frombind(X) returns zero.
|
|
**
|
|
** Please pay particular attention to the fact that the pointer returned
|
|
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
|
|
@@ -6213,8 +6516,8 @@
|
|
** routine to allocate memory for storing their state.
|
|
**
|
|
** ^The first time the sqlite3_aggregate_context(C,N) routine is called
|
|
-** for a particular aggregate function, SQLite
|
|
-** allocates N of memory, zeroes out that memory, and returns a pointer
|
|
+** for a particular aggregate function, SQLite allocates
|
|
+** N bytes of memory, zeroes out that memory, and returns a pointer
|
|
** to the new memory. ^On second and subsequent calls to
|
|
** sqlite3_aggregate_context() for the same aggregate function instance,
|
|
** the same buffer is returned. Sqlite3_aggregate_context() is normally
|
|
@@ -6231,7 +6534,7 @@
|
|
**
|
|
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
|
|
** determined by the N parameter on first successful call. Changing the
|
|
-** value of N in subsequent call to sqlite3_aggregate_context() within
|
|
+** value of N in any subsequent call to sqlite3_aggregate_context() within
|
|
** the same aggregate function instance will not resize the memory
|
|
** allocation.)^ Within the xFinal callback, it is customary to set
|
|
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
|
|
@@ -6388,8 +6691,9 @@
|
|
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
|
|
** as the text of an error message. ^SQLite interprets the error
|
|
** message string from sqlite3_result_error() as UTF-8. ^SQLite
|
|
-** interprets the string from sqlite3_result_error16() as UTF-16 in native
|
|
-** byte order. ^If the third parameter to sqlite3_result_error()
|
|
+** interprets the string from sqlite3_result_error16() as UTF-16 using
|
|
+** the same [byte-order determination rules] as [sqlite3_bind_text16()].
|
|
+** ^If the third parameter to sqlite3_result_error()
|
|
** or sqlite3_result_error16() is negative then SQLite takes as the error
|
|
** message all text up through the first zero character.
|
|
** ^If the third parameter to sqlite3_result_error() or
|
|
@@ -6457,6 +6761,25 @@
|
|
** then SQLite makes a copy of the result into space obtained
|
|
** from [sqlite3_malloc()] before it returns.
|
|
**
|
|
+** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and
|
|
+** sqlite3_result_text16be() routines, and for sqlite3_result_text64()
|
|
+** when the encoding is not UTF8, if the input UTF16 begins with a
|
|
+** byte-order mark (BOM, U+FEFF) then the BOM is removed from the
|
|
+** string and the rest of the string is interpreted according to the
|
|
+** byte-order specified by the BOM. ^The byte-order specified by
|
|
+** the BOM at the beginning of the text overrides the byte-order
|
|
+** specified by the interface procedure. ^So, for example, if
|
|
+** sqlite3_result_text16le() is invoked with text that begins
|
|
+** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the
|
|
+** first two bytes of input are skipped and the remaining input
|
|
+** is interpreted as UTF16BE text.
|
|
+**
|
|
+** ^For UTF16 input text to the sqlite3_result_text16(),
|
|
+** sqlite3_result_text16be(), sqlite3_result_text16le(), and
|
|
+** sqlite3_result_text64() routines, if the text contains invalid
|
|
+** UTF16 characters, the invalid characters might be converted
|
|
+** into the unicode replacement character, U+FFFD.
|
|
+**
|
|
** ^The sqlite3_result_value() interface sets the result of
|
|
** the application-defined function to be a copy of the
|
|
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
|
|
@@ -6542,7 +6865,7 @@
|
|
** <li> [SQLITE_UTF16_ALIGNED].
|
|
** </ul>)^
|
|
** ^The eTextRep argument determines the encoding of strings passed
|
|
-** to the collating function callback, xCallback.
|
|
+** to the collating function callback, xCompare.
|
|
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
|
|
** force strings to be UTF16 with native byte order.
|
|
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
|
|
@@ -6551,18 +6874,19 @@
|
|
** ^The fourth argument, pArg, is an application data pointer that is passed
|
|
** through as the first argument to the collating function callback.
|
|
**
|
|
-** ^The fifth argument, xCallback, is a pointer to the collating function.
|
|
+** ^The fifth argument, xCompare, is a pointer to the collating function.
|
|
** ^Multiple collating functions can be registered using the same name but
|
|
** with different eTextRep parameters and SQLite will use whichever
|
|
** function requires the least amount of data transformation.
|
|
-** ^If the xCallback argument is NULL then the collating function is
|
|
+** ^If the xCompare argument is NULL then the collating function is
|
|
** deleted. ^When all collating functions having the same name are deleted,
|
|
** that collation is no longer usable.
|
|
**
|
|
** ^The collating function callback is invoked with a copy of the pArg
|
|
** application data pointer and with two strings in the encoding specified
|
|
-** by the eTextRep argument. The collating function must return an
|
|
-** integer that is negative, zero, or positive
|
|
+** by the eTextRep argument. The two integer parameters to the collating
|
|
+** function callback are the length of the two strings, in bytes. The collating
|
|
+** function must return an integer that is negative, zero, or positive
|
|
** if the first string is less than, equal to, or greater than the second,
|
|
** respectively. A collating function must always return the same answer
|
|
** given the same inputs. If two or more collating functions are registered
|
|
@@ -6579,7 +6903,7 @@
|
|
** </ol>
|
|
**
|
|
** If a collating function fails any of the above constraints and that
|
|
-** collating function is registered and used, then the behavior of SQLite
|
|
+** collating function is registered and used, then the behavior of SQLite
|
|
** is undefined.
|
|
**
|
|
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
|
|
@@ -6661,51 +6985,6 @@
|
|
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
|
);
|
|
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-/*
|
|
-** Specify the key for an encrypted database. This routine should be
|
|
-** called right after sqlite3_open().
|
|
-**
|
|
-** The code to implement this API is not available in the public release
|
|
-** of SQLite.
|
|
-*/
|
|
-SQLITE_API int sqlite3_key(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const void *pKey, int nKey /* The key */
|
|
-);
|
|
-SQLITE_API int sqlite3_key_v2(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const char *zDbName, /* Name of the database */
|
|
- const void *pKey, int nKey /* The key */
|
|
-);
|
|
-
|
|
-/*
|
|
-** Change the key on an open database. If the current database is not
|
|
-** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
|
|
-** database is decrypted.
|
|
-**
|
|
-** The code to implement this API is not available in the public release
|
|
-** of SQLite.
|
|
-*/
|
|
-SQLITE_API int sqlite3_rekey(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const void *pKey, int nKey /* The new key */
|
|
-);
|
|
-SQLITE_API int sqlite3_rekey_v2(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const char *zDbName, /* Name of the database */
|
|
- const void *pKey, int nKey /* The new key */
|
|
-);
|
|
-
|
|
-/*
|
|
-** Specify the activation key for a SEE database. Unless
|
|
-** activated, none of the SEE routines will work.
|
|
-*/
|
|
-SQLITE_API void sqlite3_activate_see(
|
|
- const char *zPassPhrase /* Activation phrase */
|
|
-);
|
|
-#endif
|
|
-
|
|
#ifdef SQLITE_ENABLE_CEROD
|
|
/*
|
|
** Specify the activation key for a CEROD database. Unless
|
|
@@ -6906,16 +7185,31 @@
|
|
** CAPI3REF: Return The Filename For A Database Connection
|
|
** METHOD: sqlite3
|
|
**
|
|
-** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
|
|
-** associated with database N of connection D. ^The main database file
|
|
-** has the name "main". If there is no attached database N on the database
|
|
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
|
|
+** associated with database N of connection D.
|
|
+** ^If there is no attached database N on the database
|
|
** connection D, or if database N is a temporary or in-memory database, then
|
|
** this function will return either a NULL pointer or an empty string.
|
|
**
|
|
+** ^The string value returned by this routine is owned and managed by
|
|
+** the database connection. ^The value will be valid until the database N
|
|
+** is [DETACH]-ed or until the database connection closes.
|
|
+**
|
|
** ^The filename returned by this function is the output of the
|
|
** xFullPathname method of the [VFS]. ^In other words, the filename
|
|
** will be an absolute pathname, even if the filename used
|
|
** to open the database originally was a URI or relative pathname.
|
|
+**
|
|
+** If the filename pointer returned by this routine is not NULL, then it
|
|
+** can be used as the filename input parameter to these routines:
|
|
+** <ul>
|
|
+** <li> [sqlite3_uri_parameter()]
|
|
+** <li> [sqlite3_uri_boolean()]
|
|
+** <li> [sqlite3_uri_int64()]
|
|
+** <li> [sqlite3_filename_database()]
|
|
+** <li> [sqlite3_filename_journal()]
|
|
+** <li> [sqlite3_filename_wal()]
|
|
+** </ul>
|
|
*/
|
|
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
|
|
|
@@ -7065,15 +7359,19 @@
|
|
**
|
|
** ^(The cache sharing mode set by this interface effects all subsequent
|
|
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
|
|
-** Existing database connections continue use the sharing mode
|
|
+** Existing database connections continue to use the sharing mode
|
|
** that was in effect at the time they were opened.)^
|
|
**
|
|
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
|
|
** successfully. An [error code] is returned otherwise.)^
|
|
**
|
|
-** ^Shared cache is disabled by default. But this might change in
|
|
-** future releases of SQLite. Applications that care about shared
|
|
-** cache setting should set it explicitly.
|
|
+** ^Shared cache is disabled by default. It is recommended that it stay
|
|
+** that way. In other words, do not use this routine. This interface
|
|
+** continues to be provided for historical compatibility, but its use is
|
|
+** discouraged. Any use of shared cache is discouraged. If shared cache
|
|
+** must be used, it is recommended that shared cache only be enabled for
|
|
+** individual database connections using the [sqlite3_open_v2()] interface
|
|
+** with the [SQLITE_OPEN_SHAREDCACHE] flag.
|
|
**
|
|
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
|
|
** and will always return SQLITE_MISUSE. On those systems,
|
|
@@ -7120,6 +7418,9 @@
|
|
/*
|
|
** CAPI3REF: Impose A Limit On Heap Size
|
|
**
|
|
+** These interfaces impose limits on the amount of heap memory that will be
|
|
+** by all database connections within a single process.
|
|
+**
|
|
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
|
|
** soft limit on the amount of heap memory that may be allocated by SQLite.
|
|
** ^SQLite strives to keep heap memory utilization below the soft heap
|
|
@@ -7130,20 +7431,41 @@
|
|
** an [SQLITE_NOMEM] error. In other words, the soft heap limit
|
|
** is advisory only.
|
|
**
|
|
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
|
|
-** the soft heap limit prior to the call, or negative in the case of an
|
|
-** error. ^If the argument N is negative
|
|
-** then no change is made to the soft heap limit. Hence, the current
|
|
-** size of the soft heap limit can be determined by invoking
|
|
-** sqlite3_soft_heap_limit64() with a negative argument.
|
|
-**
|
|
-** ^If the argument N is zero then the soft heap limit is disabled.
|
|
+** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
|
|
+** N bytes on the amount of memory that will be allocated. ^The
|
|
+** sqlite3_hard_heap_limit64(N) interface is similar to
|
|
+** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
|
|
+** when the hard heap limit is reached.
|
|
**
|
|
-** ^(The soft heap limit is not enforced in the current implementation
|
|
+** ^The return value from both sqlite3_soft_heap_limit64() and
|
|
+** sqlite3_hard_heap_limit64() is the size of
|
|
+** the heap limit prior to the call, or negative in the case of an
|
|
+** error. ^If the argument N is negative
|
|
+** then no change is made to the heap limit. Hence, the current
|
|
+** size of heap limits can be determined by invoking
|
|
+** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
|
|
+**
|
|
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
|
|
+**
|
|
+** ^The soft heap limit may not be greater than the hard heap limit.
|
|
+** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
|
|
+** is invoked with a value of N that is greater than the hard heap limit,
|
|
+** the the soft heap limit is set to the value of the hard heap limit.
|
|
+** ^The soft heap limit is automatically enabled whenever the hard heap
|
|
+** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
|
|
+** the soft heap limit is outside the range of 1..N, then the soft heap
|
|
+** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
|
|
+** hard heap limit is enabled makes the soft heap limit equal to the
|
|
+** hard heap limit.
|
|
+**
|
|
+** The memory allocation limits can also be adjusted using
|
|
+** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
|
|
+**
|
|
+** ^(The heap limits are not enforced in the current implementation
|
|
** if one or more of following conditions are true:
|
|
**
|
|
** <ul>
|
|
-** <li> The soft heap limit is set to zero.
|
|
+** <li> The limit value is set to zero.
|
|
** <li> Memory accounting is disabled using a combination of the
|
|
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
|
|
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
|
|
@@ -7154,21 +7476,11 @@
|
|
** from the heap.
|
|
** </ul>)^
|
|
**
|
|
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
|
|
-** the soft heap limit is enforced
|
|
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
|
|
-** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
|
|
-** the soft heap limit is enforced on every memory allocation. Without
|
|
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
|
|
-** when memory is allocated by the page cache. Testing suggests that because
|
|
-** the page cache is the predominate memory user in SQLite, most
|
|
-** applications will achieve adequate soft heap limit enforcement without
|
|
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
|
|
-**
|
|
-** The circumstances under which SQLite will enforce the soft heap limit may
|
|
+** The circumstances under which SQLite will enforce the heap limits may
|
|
** changes in future releases of SQLite.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
|
|
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
|
|
|
|
/*
|
|
** CAPI3REF: Deprecated Soft Heap Limit Interface
|
|
@@ -7192,7 +7504,7 @@
|
|
** interface returns SQLITE_OK and fills in the non-NULL pointers in
|
|
** the final five arguments with appropriate values if the specified
|
|
** column exists. ^The sqlite3_table_column_metadata() interface returns
|
|
-** SQLITE_ERROR and if the specified column does not exist.
|
|
+** SQLITE_ERROR if the specified column does not exist.
|
|
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
|
|
** NULL pointer, then this routine simply checks for the existence of the
|
|
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
|
|
@@ -7334,7 +7646,7 @@
|
|
** 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
|
|
+** be enabled 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.
|
|
@@ -7421,7 +7733,7 @@
|
|
** KEYWORDS: sqlite3_module {virtual table module}
|
|
**
|
|
** This structure, sometimes called a "virtual table module",
|
|
-** defines the implementation of a [virtual tables].
|
|
+** defines the implementation of a [virtual table].
|
|
** This structure consists mostly of methods for the module.
|
|
**
|
|
** ^A virtual table module is created by filling in a persistent
|
|
@@ -7518,7 +7830,13 @@
|
|
** the right-hand side of the corresponding aConstraint[] is evaluated
|
|
** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
|
|
** is true, then the constraint is assumed to be fully handled by the
|
|
-** virtual table and is not checked again by SQLite.)^
|
|
+** virtual table and might not be checked again by the byte code.)^ ^(The
|
|
+** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
|
|
+** is left in its default setting of false, the constraint will always be
|
|
+** checked separately in byte code. If the omit flag is change to true, then
|
|
+** the constraint may or may not be checked in byte code. In other words,
|
|
+** when the omit flag is true there is no guarantee that the constraint will
|
|
+** not be checked again using byte code.)^
|
|
**
|
|
** ^The idxNum and idxPtr values are recorded and passed into the
|
|
** [xFilter] method.
|
|
@@ -7558,7 +7876,7 @@
|
|
** If a virtual table extension is
|
|
** used with an SQLite version earlier than 3.8.2, the results of attempting
|
|
** to read or write the estimatedRows field are undefined (but are likely
|
|
-** to included crashing the application). The estimatedRows field should
|
|
+** to include crashing the application). The estimatedRows field should
|
|
** therefore only be used if [sqlite3_libversion_number()] returns a
|
|
** value greater than or equal to 3008002. Similarly, the idxFlags field
|
|
** was added for [version 3.9.0] ([dateof:3.9.0]).
|
|
@@ -7610,7 +7928,7 @@
|
|
/*
|
|
** CAPI3REF: Virtual Table Constraint Operator Codes
|
|
**
|
|
-** These macros defined the allowed values for the
|
|
+** These macros define the allowed values for the
|
|
** [sqlite3_index_info].aConstraint[].op field. Each value represents
|
|
** an operator that is part of a constraint term in the wHERE clause of
|
|
** a query that uses a [virtual table].
|
|
@@ -7656,6 +7974,12 @@
|
|
** ^The sqlite3_create_module()
|
|
** interface is equivalent to sqlite3_create_module_v2() with a NULL
|
|
** destructor.
|
|
+**
|
|
+** ^If the third parameter (the pointer to the sqlite3_module object) is
|
|
+** NULL then no new module is create and any existing modules with the
|
|
+** same name are dropped.
|
|
+**
|
|
+** See also: [sqlite3_drop_modules()]
|
|
*/
|
|
SQLITE_API int sqlite3_create_module(
|
|
sqlite3 *db, /* SQLite connection to register module with */
|
|
@@ -7671,6 +7995,23 @@
|
|
void(*xDestroy)(void*) /* Module destructor function */
|
|
);
|
|
|
|
+/*
|
|
+** CAPI3REF: Remove Unnecessary Virtual Table Implementations
|
|
+** METHOD: sqlite3
|
|
+**
|
|
+** ^The sqlite3_drop_modules(D,L) interface removes all virtual
|
|
+** table modules from database connection D except those named on list L.
|
|
+** The L parameter must be either NULL or a pointer to an array of pointers
|
|
+** to strings where the array is terminated by a single NULL pointer.
|
|
+** ^If the L parameter is NULL, then all virtual table modules are removed.
|
|
+**
|
|
+** See also: [sqlite3_create_module()]
|
|
+*/
|
|
+SQLITE_API int sqlite3_drop_modules(
|
|
+ sqlite3 *db, /* Remove modules from this connection */
|
|
+ const char **azKeep /* Except, do not remove the ones named here */
|
|
+);
|
|
+
|
|
/*
|
|
** CAPI3REF: Virtual Table Instance Object
|
|
** KEYWORDS: sqlite3_vtab
|
|
@@ -8197,7 +8538,7 @@
|
|
** The only difference is that the public sqlite3_XXX functions enumerated
|
|
** above silently ignore any invocations that pass a NULL pointer instead
|
|
** of a valid mutex handle. The implementations of the methods defined
|
|
-** by this structure are not required to handle this case, the results
|
|
+** by this structure are not required to handle this case. The results
|
|
** of passing a NULL pointer instead of a valid mutex handle are undefined
|
|
** (i.e. it is acceptable to provide an implementation that segfaults if
|
|
** it is passed a NULL pointer).
|
|
@@ -8379,14 +8720,14 @@
|
|
#define SQLITE_TESTCTRL_FIRST 5
|
|
#define SQLITE_TESTCTRL_PRNG_SAVE 5
|
|
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
|
|
-#define SQLITE_TESTCTRL_PRNG_RESET 7
|
|
+#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_BITVEC_TEST 8
|
|
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
|
|
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
|
|
#define SQLITE_TESTCTRL_PENDING_BYTE 11
|
|
#define SQLITE_TESTCTRL_ASSERT 12
|
|
#define SQLITE_TESTCTRL_ALWAYS 13
|
|
-#define SQLITE_TESTCTRL_RESERVE 14
|
|
+#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
|
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
|
@@ -8402,7 +8743,9 @@
|
|
#define SQLITE_TESTCTRL_IMPOSTER 25
|
|
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
|
|
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
|
|
-#define SQLITE_TESTCTRL_LAST 27 /* Largest TESTCTRL */
|
|
+#define SQLITE_TESTCTRL_PRNG_SEED 28
|
|
+#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
|
+#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
|
|
|
|
/*
|
|
** CAPI3REF: SQL Keyword Checking
|
|
@@ -8668,7 +9011,7 @@
|
|
**
|
|
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
|
|
** <dd>This parameter records the largest memory allocation request
|
|
-** handed to [pagecache memory allocator]. Only the value returned in the
|
|
+** handed to the [pagecache memory allocator]. Only the value returned in the
|
|
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
|
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
|
**
|
|
@@ -8744,7 +9087,7 @@
|
|
** checked out.</dd>)^
|
|
**
|
|
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
|
|
-** <dd>This parameter returns the number malloc attempts that were
|
|
+** <dd>This parameter returns the number of malloc attempts that were
|
|
** satisfied using lookaside memory. Only the high-water value is meaningful;
|
|
** the current value is always zero.)^
|
|
**
|
|
@@ -8826,7 +9169,7 @@
|
|
** cache overflowing. Transactions are more efficient if they are written
|
|
** to disk all at once. When pages spill mid-transaction, that introduces
|
|
** additional overhead. This parameter can be used help identify
|
|
-** inefficiencies that can be resolve by increasing the cache size.
|
|
+** inefficiencies that can be resolved by increasing the cache size.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
|
|
@@ -8915,7 +9258,7 @@
|
|
**
|
|
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
|
|
** <dd>^This is the number of times that the prepare statement has been
|
|
-** automatically regenerated due to schema changes or change to
|
|
+** automatically regenerated due to schema changes or changes to
|
|
** [bound parameters] that might affect the query plan.
|
|
**
|
|
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
|
|
@@ -9086,7 +9429,7 @@
|
|
**
|
|
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
|
|
** will only use a createFlag of 2 after a prior call with a createFlag of 1
|
|
-** failed.)^ In between the to xFetch() calls, SQLite may
|
|
+** failed.)^ In between the xFetch() calls, SQLite may
|
|
** attempt to unpin one or more cache pages by spilling the content of
|
|
** pinned pages to disk and synching the operating system disk cache.
|
|
**
|
|
@@ -9404,7 +9747,7 @@
|
|
** the first argument to register for a callback that will be invoked
|
|
** when the blocking connections current transaction is concluded. ^The
|
|
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
|
|
-** call that concludes the blocking connections transaction.
|
|
+** call that concludes the blocking connection's transaction.
|
|
**
|
|
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
|
|
** there is a chance that the blocking connection will have already
|
|
@@ -9442,7 +9785,7 @@
|
|
** an unlock-notify callback is a pointer to an array of void* pointers,
|
|
** and the second is the number of entries in the array.
|
|
**
|
|
-** When a blocking connections transaction is concluded, there may be
|
|
+** When a blocking connection's transaction is concluded, there may be
|
|
** more than one blocked connection that has registered for an unlock-notify
|
|
** callback. ^If two or more such blocked connections have specified the
|
|
** same callback function, then instead of invoking the callback function
|
|
@@ -9790,14 +10133,20 @@
|
|
** If this interface is invoked outside the context of an xConnect or
|
|
** xCreate virtual table method then the behavior is undefined.
|
|
**
|
|
-** At present, there is only one option that may be configured using
|
|
-** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
|
|
-** may be added in the future.
|
|
+** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
|
|
+** [database connection] in which the virtual table is being created and
|
|
+** which is passed in as the first argument to the [xConnect] or [xCreate]
|
|
+** method that is invoking sqlite3_vtab_config(). The C parameter is one
|
|
+** of the [virtual table configuration options]. The presence and meaning
|
|
+** of parameters after C depend on which [virtual table configuration option]
|
|
+** is used.
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Configuration Options
|
|
+** KEYWORDS: {virtual table configuration options}
|
|
+** KEYWORDS: {virtual table configuration option}
|
|
**
|
|
** These macros define the various options to the
|
|
** [sqlite3_vtab_config()] interface that [virtual table] implementations
|
|
@@ -9805,7 +10154,7 @@
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
|
|
-** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
|
|
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT</dt>
|
|
** <dd>Calls of the form
|
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
|
|
** where X is an integer. If X is zero, then the [virtual table] whose
|
|
@@ -9834,9 +10183,31 @@
|
|
** return SQLITE_OK. Or, if this is not possible, it may return
|
|
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
|
|
** constraint handling.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
|
|
+** <dd>Calls of the form
|
|
+** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
|
|
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
|
+** prohibits that virtual table from being used from within triggers and
|
|
+** views.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
|
|
+** <dd>Calls of the form
|
|
+** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
|
|
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
|
+** identify that virtual table as being safe to use from within triggers
|
|
+** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
|
|
+** virtual table can do no serious harm even if it is controlled by a
|
|
+** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
|
|
+** flag unless absolutely necessary.
|
|
+** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
|
|
+#define SQLITE_VTAB_INNOCUOUS 2
|
|
+#define SQLITE_VTAB_DIRECTONLY 3
|
|
|
|
/*
|
|
** CAPI3REF: Determine The Virtual Table Conflict Policy
|
|
@@ -9916,15 +10287,15 @@
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
|
|
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
|
|
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be
|
|
** set to the total number of times that the X-th loop has run.</dd>
|
|
**
|
|
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
|
|
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set
|
|
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be set
|
|
** to the total number of rows examined by all iterations of the X-th loop.</dd>
|
|
**
|
|
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
|
|
-** <dd>^The "double" variable pointed to by the T parameter will be set to the
|
|
+** <dd>^The "double" variable pointed to by the V parameter will be set to the
|
|
** query planner's estimate for the average number of rows output from each
|
|
** iteration of the X-th loop. If the query planner's estimates was accurate,
|
|
** then this value will approximate the quotient NVISIT/NLOOP and the
|
|
@@ -9932,17 +10303,17 @@
|
|
** be the NLOOP value for the current loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
|
|
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
|
|
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
|
|
** to a zero-terminated UTF-8 string containing the name of the index or table
|
|
** used for the X-th loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
|
|
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
|
|
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
|
|
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
|
|
** description for the X-th loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
|
|
-** <dd>^The "int" variable pointed to by the T parameter will be set to the
|
|
+** <dd>^The "int" variable pointed to by the V parameter will be set to the
|
|
** "select-id" for the X-th loop. The select-id identifies which query or
|
|
** subquery the loop is part of. The main query has a select-id of zero.
|
|
** The select-id is the same value as is output in the first column
|
|
@@ -10797,7 +11168,7 @@
|
|
** The second argument (xFilter) is the "filter callback". For changes to rows
|
|
** in tables that are not attached to the Session object, the filter is called
|
|
** to determine whether changes to the table's rows should be tracked or not.
|
|
-** If xFilter returns 0, changes is not tracked. Note that once a table is
|
|
+** If xFilter returns 0, changes are not tracked. Note that once a table is
|
|
** attached, xFilter will not be called again.
|
|
*/
|
|
SQLITE_API void sqlite3session_table_filter(
|
|
@@ -10971,7 +11342,7 @@
|
|
** It an error if database zFrom does not exist or does not contain the
|
|
** required compatible table.
|
|
**
|
|
-** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
|
|
+** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
|
|
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
|
|
** may be set to point to a buffer containing an English language error
|
|
** message. It is the responsibility of the caller to free this buffer using
|
|
@@ -11108,7 +11479,7 @@
|
|
** CAPI3REF: Advance A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
-** This function may only be used with iterators created by function
|
|
+** This function may only be used with iterators created by the function
|
|
** [sqlite3changeset_start()]. If it is called on an iterator passed to
|
|
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
|
|
** is returned and the call has no effect.
|
|
@@ -11524,8 +11895,8 @@
|
|
** case, this function fails with SQLITE_SCHEMA. If the input changeset
|
|
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
|
|
** returned. Or, if an out-of-memory condition occurs during processing, this
|
|
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the
|
|
-** final contents of the changegroup is undefined.
|
|
+** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
|
|
+** of the final contents of the changegroup is undefined.
|
|
**
|
|
** If no error occurs, SQLITE_OK is returned.
|
|
*/
|
|
@@ -11700,7 +12071,7 @@
|
|
**
|
|
** It is safe to execute SQL statements, including those that write to the
|
|
** table that the callback related to, from within the xConflict callback.
|
|
-** This can be used to further customize the applications conflict
|
|
+** This can be used to further customize the application's conflict
|
|
** resolution strategy.
|
|
**
|
|
** All changes made by these functions are enclosed in a savepoint transaction.
|
|
@@ -12010,7 +12381,7 @@
|
|
**
|
|
** Argument pIn must point to a buffer containing a changeset nIn bytes
|
|
** in size. This function allocates and populates a buffer with a copy
|
|
-** of the changeset rebased rebased according to the configuration of the
|
|
+** of the changeset rebased according to the configuration of the
|
|
** rebaser object passed as the first argument. If successful, (*ppOut)
|
|
** is set to point to the new buffer containing the rebased changeset and
|
|
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
|
|
@@ -12418,7 +12789,7 @@
|
|
**
|
|
** xSetAuxdata(pFts5, pAux, xDelete)
|
|
**
|
|
-** Save the pointer passed as the second argument as the extension functions
|
|
+** Save the pointer passed as the second argument as the extension function's
|
|
** "auxiliary data". The pointer may then be retrieved by the current or any
|
|
** future invocation of the same fts5 extension function made as part of
|
|
** the same MATCH query using the xGetAuxdata() API.
|
|
@@ -12660,8 +13031,8 @@
|
|
**
|
|
** There are several ways to approach this in FTS5:
|
|
**
|
|
-** <ol><li> By mapping all synonyms to a single token. In this case, the
|
|
-** In the above example, this means that the tokenizer returns the
|
|
+** <ol><li> By mapping all synonyms to a single token. In this case, using
|
|
+** the above example, this means that the tokenizer returns the
|
|
** same token for inputs "first" and "1st". Say that token is in
|
|
** fact "first", so that when the user inserts the document "I won
|
|
** 1st place" entries are added to the index for tokens "i", "won",
|
|
@@ -12982,9 +13353,12 @@
|
|
|
|
/*
|
|
** The maximum value of a ?nnn wildcard that the parser will accept.
|
|
+** If the value exceeds 32767 then extra space is required for the Expr
|
|
+** structure. But otherwise, we believe that the number can be as large
|
|
+** as a signed 32-bit integer can hold.
|
|
*/
|
|
#ifndef SQLITE_MAX_VARIABLE_NUMBER
|
|
-# define SQLITE_MAX_VARIABLE_NUMBER 999
|
|
+# define SQLITE_MAX_VARIABLE_NUMBER 32766
|
|
#endif
|
|
|
|
/* Maximum page size. The upper bound on this value is 65536. This a limit
|
|
@@ -13073,6 +13447,21 @@
|
|
#pragma warn -spa /* Suspicious pointer arithmetic */
|
|
#endif
|
|
|
|
+/*
|
|
+** WAL mode depends on atomic aligned 32-bit loads and stores in a few
|
|
+** places. The following macros try to make this explicit.
|
|
+*/
|
|
+#ifndef __has_feature
|
|
+# define __has_feature(x) 0 /* compatibility with non-clang compilers */
|
|
+#endif
|
|
+#if GCC_VERSION>=4007000 || __has_feature(c_atomic)
|
|
+# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
|
|
+# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
|
|
+#else
|
|
+# define AtomicLoad(PTR) (*(PTR))
|
|
+# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
|
|
+#endif
|
|
+
|
|
/*
|
|
** Include standard header files as necessary
|
|
*/
|
|
@@ -13099,15 +13488,15 @@
|
|
** So we have to define the macros in different ways depending on the
|
|
** compiler.
|
|
*/
|
|
-#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
|
|
+#if defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
|
|
+# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
|
|
+# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
|
|
+#elif defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)(__PTRDIFF_TYPE__)(X))
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(__PTRDIFF_TYPE__)(X))
|
|
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)&((char*)0)[X])
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0))
|
|
-#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
|
|
-# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
|
|
-# define SQLITE_PTR_TO_INT(X) ((int)(intptr_t)(X))
|
|
#else /* Generates a warning - but it always works */
|
|
# define SQLITE_INT_TO_PTR(X) ((void*)(X))
|
|
# define SQLITE_PTR_TO_INT(X) ((int)(X))
|
|
@@ -13333,6 +13722,26 @@
|
|
# define NEVER(X) (X)
|
|
#endif
|
|
|
|
+/*
|
|
+** The harmless(X) macro indicates that expression X is usually false
|
|
+** but can be true without causing any problems, but we don't know of
|
|
+** any way to cause X to be true.
|
|
+**
|
|
+** In debugging and testing builds, this macro will abort if X is ever
|
|
+** true. In this way, developers are alerted to a possible test case
|
|
+** that causes X to be true. If a harmless macro ever fails, that is
|
|
+** an opportunity to change the macro into a testcase() and add a new
|
|
+** test case to the test suite.
|
|
+**
|
|
+** For normal production builds, harmless(X) is a no-op, since it does
|
|
+** not matter whether expression X is true or false.
|
|
+*/
|
|
+#ifdef SQLITE_DEBUG
|
|
+# define harmless(X) assert(!(X));
|
|
+#else
|
|
+# define harmless(X)
|
|
+#endif
|
|
+
|
|
/*
|
|
** Some conditionals are optimizations only. In other words, if the
|
|
** conditionals are replaced with a constant 1 (true) or 0 (false) then
|
|
@@ -13597,100 +14006,105 @@
|
|
#define TK_VIEW 79
|
|
#define TK_VIRTUAL 80
|
|
#define TK_WITH 81
|
|
-#define TK_CURRENT 82
|
|
-#define TK_FOLLOWING 83
|
|
-#define TK_PARTITION 84
|
|
-#define TK_PRECEDING 85
|
|
-#define TK_RANGE 86
|
|
-#define TK_UNBOUNDED 87
|
|
-#define TK_EXCLUDE 88
|
|
-#define TK_GROUPS 89
|
|
-#define TK_OTHERS 90
|
|
-#define TK_TIES 91
|
|
-#define TK_REINDEX 92
|
|
-#define TK_RENAME 93
|
|
-#define TK_CTIME_KW 94
|
|
-#define TK_ANY 95
|
|
-#define TK_BITAND 96
|
|
-#define TK_BITOR 97
|
|
-#define TK_LSHIFT 98
|
|
-#define TK_RSHIFT 99
|
|
-#define TK_PLUS 100
|
|
-#define TK_MINUS 101
|
|
-#define TK_STAR 102
|
|
-#define TK_SLASH 103
|
|
-#define TK_REM 104
|
|
-#define TK_CONCAT 105
|
|
-#define TK_COLLATE 106
|
|
-#define TK_BITNOT 107
|
|
-#define TK_ON 108
|
|
-#define TK_INDEXED 109
|
|
-#define TK_STRING 110
|
|
-#define TK_JOIN_KW 111
|
|
-#define TK_CONSTRAINT 112
|
|
-#define TK_DEFAULT 113
|
|
-#define TK_NULL 114
|
|
-#define TK_PRIMARY 115
|
|
-#define TK_UNIQUE 116
|
|
-#define TK_CHECK 117
|
|
-#define TK_REFERENCES 118
|
|
-#define TK_AUTOINCR 119
|
|
-#define TK_INSERT 120
|
|
-#define TK_DELETE 121
|
|
-#define TK_UPDATE 122
|
|
-#define TK_SET 123
|
|
-#define TK_DEFERRABLE 124
|
|
-#define TK_FOREIGN 125
|
|
-#define TK_DROP 126
|
|
-#define TK_UNION 127
|
|
-#define TK_ALL 128
|
|
-#define TK_EXCEPT 129
|
|
-#define TK_INTERSECT 130
|
|
-#define TK_SELECT 131
|
|
-#define TK_VALUES 132
|
|
-#define TK_DISTINCT 133
|
|
-#define TK_DOT 134
|
|
-#define TK_FROM 135
|
|
-#define TK_JOIN 136
|
|
-#define TK_USING 137
|
|
-#define TK_ORDER 138
|
|
-#define TK_GROUP 139
|
|
-#define TK_HAVING 140
|
|
-#define TK_LIMIT 141
|
|
-#define TK_WHERE 142
|
|
-#define TK_INTO 143
|
|
-#define TK_NOTHING 144
|
|
-#define TK_FLOAT 145
|
|
-#define TK_BLOB 146
|
|
-#define TK_INTEGER 147
|
|
-#define TK_VARIABLE 148
|
|
-#define TK_CASE 149
|
|
-#define TK_WHEN 150
|
|
-#define TK_THEN 151
|
|
-#define TK_ELSE 152
|
|
-#define TK_INDEX 153
|
|
-#define TK_ALTER 154
|
|
-#define TK_ADD 155
|
|
-#define TK_WINDOW 156
|
|
-#define TK_OVER 157
|
|
-#define TK_FILTER 158
|
|
-#define TK_TRUEFALSE 159
|
|
-#define TK_ISNOT 160
|
|
-#define TK_FUNCTION 161
|
|
-#define TK_COLUMN 162
|
|
-#define TK_AGG_FUNCTION 163
|
|
-#define TK_AGG_COLUMN 164
|
|
-#define TK_UMINUS 165
|
|
-#define TK_UPLUS 166
|
|
-#define TK_TRUTH 167
|
|
-#define TK_REGISTER 168
|
|
-#define TK_VECTOR 169
|
|
-#define TK_SELECT_COLUMN 170
|
|
-#define TK_IF_NULL_ROW 171
|
|
-#define TK_ASTERISK 172
|
|
-#define TK_SPAN 173
|
|
-#define TK_SPACE 174
|
|
-#define TK_ILLEGAL 175
|
|
+#define TK_NULLS 82
|
|
+#define TK_FIRST 83
|
|
+#define TK_LAST 84
|
|
+#define TK_CURRENT 85
|
|
+#define TK_FOLLOWING 86
|
|
+#define TK_PARTITION 87
|
|
+#define TK_PRECEDING 88
|
|
+#define TK_RANGE 89
|
|
+#define TK_UNBOUNDED 90
|
|
+#define TK_EXCLUDE 91
|
|
+#define TK_GROUPS 92
|
|
+#define TK_OTHERS 93
|
|
+#define TK_TIES 94
|
|
+#define TK_GENERATED 95
|
|
+#define TK_ALWAYS 96
|
|
+#define TK_REINDEX 97
|
|
+#define TK_RENAME 98
|
|
+#define TK_CTIME_KW 99
|
|
+#define TK_ANY 100
|
|
+#define TK_BITAND 101
|
|
+#define TK_BITOR 102
|
|
+#define TK_LSHIFT 103
|
|
+#define TK_RSHIFT 104
|
|
+#define TK_PLUS 105
|
|
+#define TK_MINUS 106
|
|
+#define TK_STAR 107
|
|
+#define TK_SLASH 108
|
|
+#define TK_REM 109
|
|
+#define TK_CONCAT 110
|
|
+#define TK_COLLATE 111
|
|
+#define TK_BITNOT 112
|
|
+#define TK_ON 113
|
|
+#define TK_INDEXED 114
|
|
+#define TK_STRING 115
|
|
+#define TK_JOIN_KW 116
|
|
+#define TK_CONSTRAINT 117
|
|
+#define TK_DEFAULT 118
|
|
+#define TK_NULL 119
|
|
+#define TK_PRIMARY 120
|
|
+#define TK_UNIQUE 121
|
|
+#define TK_CHECK 122
|
|
+#define TK_REFERENCES 123
|
|
+#define TK_AUTOINCR 124
|
|
+#define TK_INSERT 125
|
|
+#define TK_DELETE 126
|
|
+#define TK_UPDATE 127
|
|
+#define TK_SET 128
|
|
+#define TK_DEFERRABLE 129
|
|
+#define TK_FOREIGN 130
|
|
+#define TK_DROP 131
|
|
+#define TK_UNION 132
|
|
+#define TK_ALL 133
|
|
+#define TK_EXCEPT 134
|
|
+#define TK_INTERSECT 135
|
|
+#define TK_SELECT 136
|
|
+#define TK_VALUES 137
|
|
+#define TK_DISTINCT 138
|
|
+#define TK_DOT 139
|
|
+#define TK_FROM 140
|
|
+#define TK_JOIN 141
|
|
+#define TK_USING 142
|
|
+#define TK_ORDER 143
|
|
+#define TK_GROUP 144
|
|
+#define TK_HAVING 145
|
|
+#define TK_LIMIT 146
|
|
+#define TK_WHERE 147
|
|
+#define TK_INTO 148
|
|
+#define TK_NOTHING 149
|
|
+#define TK_FLOAT 150
|
|
+#define TK_BLOB 151
|
|
+#define TK_INTEGER 152
|
|
+#define TK_VARIABLE 153
|
|
+#define TK_CASE 154
|
|
+#define TK_WHEN 155
|
|
+#define TK_THEN 156
|
|
+#define TK_ELSE 157
|
|
+#define TK_INDEX 158
|
|
+#define TK_ALTER 159
|
|
+#define TK_ADD 160
|
|
+#define TK_WINDOW 161
|
|
+#define TK_OVER 162
|
|
+#define TK_FILTER 163
|
|
+#define TK_COLUMN 164
|
|
+#define TK_AGG_FUNCTION 165
|
|
+#define TK_AGG_COLUMN 166
|
|
+#define TK_TRUEFALSE 167
|
|
+#define TK_ISNOT 168
|
|
+#define TK_FUNCTION 169
|
|
+#define TK_UMINUS 170
|
|
+#define TK_UPLUS 171
|
|
+#define TK_TRUTH 172
|
|
+#define TK_REGISTER 173
|
|
+#define TK_VECTOR 174
|
|
+#define TK_SELECT_COLUMN 175
|
|
+#define TK_IF_NULL_ROW 176
|
|
+#define TK_ASTERISK 177
|
|
+#define TK_SPAN 178
|
|
+#define TK_SPACE 179
|
|
+#define TK_ILLEGAL 180
|
|
|
|
/************** End of parse.h ***********************************************/
|
|
/************** Continuing where we left off in sqliteInt.h ******************/
|
|
@@ -14101,20 +14515,6 @@
|
|
# define SQLITE_DEFAULT_MMAP_SIZE SQLITE_MAX_MMAP_SIZE
|
|
#endif
|
|
|
|
-/*
|
|
-** Only one of SQLITE_ENABLE_STAT3 or SQLITE_ENABLE_STAT4 can be defined.
|
|
-** Priority is given to SQLITE_ENABLE_STAT4. If either are defined, also
|
|
-** define SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-*/
|
|
-#ifdef SQLITE_ENABLE_STAT4
|
|
-# undef SQLITE_ENABLE_STAT3
|
|
-# define SQLITE_ENABLE_STAT3_OR_STAT4 1
|
|
-#elif SQLITE_ENABLE_STAT3
|
|
-# define SQLITE_ENABLE_STAT3_OR_STAT4 1
|
|
-#elif SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-# undef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-#endif
|
|
-
|
|
/*
|
|
** SELECTTRACE_ENABLED will be either 1 or 0 depending on whether or not
|
|
** the Select query generator tracing logic is turned on.
|
|
@@ -14139,7 +14539,6 @@
|
|
int (*xBusyHandler)(void *,int); /* The busy callback */
|
|
void *pBusyArg; /* First arg to busy callback */
|
|
int nBusy; /* Incremented with each busy call */
|
|
- u8 bExtraFileArg; /* Include sqlite3_file as callback arg */
|
|
};
|
|
|
|
/*
|
|
@@ -14302,6 +14701,7 @@
|
|
** A bit in a Bitmask
|
|
*/
|
|
#define MASKBIT(n) (((Bitmask)1)<<(n))
|
|
+#define MASKBIT64(n) (((u64)1)<<(n))
|
|
#define MASKBIT32(n) (((unsigned int)1)<<(n))
|
|
#define ALLBITS ((Bitmask)-1)
|
|
|
|
@@ -14396,7 +14796,7 @@
|
|
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
|
|
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
|
|
-SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*);
|
|
+SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree*);
|
|
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
|
|
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
|
|
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
|
|
@@ -14628,6 +15028,8 @@
|
|
SQLITE_PRIVATE int sqlite3BtreeEof(BtCursor*);
|
|
SQLITE_PRIVATE int sqlite3BtreePrevious(BtCursor*, int flags);
|
|
SQLITE_PRIVATE i64 sqlite3BtreeIntegerKey(BtCursor*);
|
|
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor*);
|
|
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor*);
|
|
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
|
SQLITE_PRIVATE i64 sqlite3BtreeOffset(BtCursor*);
|
|
#endif
|
|
@@ -14636,7 +15038,7 @@
|
|
SQLITE_PRIVATE u32 sqlite3BtreePayloadSize(BtCursor*);
|
|
SQLITE_PRIVATE sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
|
|
|
|
-SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
|
|
+SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,int*aRoot,int nRoot,int,int*);
|
|
SQLITE_PRIVATE struct Pager *sqlite3BtreePager(Btree*);
|
|
SQLITE_PRIVATE i64 sqlite3BtreeRowCountEst(BtCursor*);
|
|
|
|
@@ -14656,9 +15058,7 @@
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorIsValidNN(BtCursor*);
|
|
|
|
-#ifndef SQLITE_OMIT_BTREECOUNT
|
|
-SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *, i64 *);
|
|
-#endif
|
|
+SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3*, BtCursor*, i64*);
|
|
|
|
#ifdef SQLITE_TEST
|
|
SQLITE_PRIVATE int sqlite3BtreeCursorInfo(BtCursor*, int*, int);
|
|
@@ -14914,30 +15314,30 @@
|
|
#define OP_SeekLE 23 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_SeekGE 24 /* jump, synopsis: key=r[P3@P4] */
|
|
#define OP_SeekGT 25 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_IfNoHope 26 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_NoConflict 27 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_NotFound 28 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_Found 29 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_SeekRowid 30 /* jump, synopsis: intkey=r[P3] */
|
|
-#define OP_NotExists 31 /* jump, synopsis: intkey=r[P3] */
|
|
-#define OP_Last 32 /* jump */
|
|
-#define OP_IfSmaller 33 /* jump */
|
|
-#define OP_SorterSort 34 /* jump */
|
|
-#define OP_Sort 35 /* jump */
|
|
-#define OP_Rewind 36 /* jump */
|
|
-#define OP_IdxLE 37 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_IdxGT 38 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_IdxLT 39 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_IdxGE 40 /* jump, synopsis: key=r[P3@P4] */
|
|
-#define OP_RowSetRead 41 /* jump, synopsis: r[P3]=rowset(P1) */
|
|
-#define OP_RowSetTest 42 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
|
|
+#define OP_IfNotOpen 26 /* jump, synopsis: if( !csr[P1] ) goto P2 */
|
|
+#define OP_IfNoHope 27 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_NoConflict 28 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_NotFound 29 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_Found 30 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_SeekRowid 31 /* jump, synopsis: intkey=r[P3] */
|
|
+#define OP_NotExists 32 /* jump, synopsis: intkey=r[P3] */
|
|
+#define OP_Last 33 /* jump */
|
|
+#define OP_IfSmaller 34 /* jump */
|
|
+#define OP_SorterSort 35 /* jump */
|
|
+#define OP_Sort 36 /* jump */
|
|
+#define OP_Rewind 37 /* jump */
|
|
+#define OP_IdxLE 38 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_IdxGT 39 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_IdxLT 40 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_IdxGE 41 /* jump, synopsis: key=r[P3@P4] */
|
|
+#define OP_RowSetRead 42 /* jump, synopsis: r[P3]=rowset(P1) */
|
|
#define OP_Or 43 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
|
|
#define OP_And 44 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
|
|
-#define OP_Program 45 /* jump */
|
|
-#define OP_FkIfZero 46 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
|
|
-#define OP_IfPos 47 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
|
|
-#define OP_IfNotZero 48 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
|
|
-#define OP_DecrJumpZero 49 /* jump, synopsis: if (--r[P1])==0 goto P2 */
|
|
+#define OP_RowSetTest 45 /* jump, synopsis: if r[P3] in rowset(P1) goto P2 */
|
|
+#define OP_Program 46 /* jump */
|
|
+#define OP_FkIfZero 47 /* jump, synopsis: if fkctr[P1]==0 goto P2 */
|
|
+#define OP_IfPos 48 /* jump, synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
|
|
+#define OP_IfNotZero 49 /* jump, synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
|
|
#define OP_IsNull 50 /* jump, same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
|
|
#define OP_NotNull 51 /* jump, same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
|
|
#define OP_Ne 52 /* jump, same as TK_NE, synopsis: IF r[P3]!=r[P1] */
|
|
@@ -14947,83 +15347,83 @@
|
|
#define OP_Lt 56 /* jump, same as TK_LT, synopsis: IF r[P3]<r[P1] */
|
|
#define OP_Ge 57 /* jump, same as TK_GE, synopsis: IF r[P3]>=r[P1] */
|
|
#define OP_ElseNotEq 58 /* jump, same as TK_ESCAPE */
|
|
-#define OP_IncrVacuum 59 /* jump */
|
|
-#define OP_VNext 60 /* jump */
|
|
-#define OP_Init 61 /* jump, synopsis: Start at P2 */
|
|
-#define OP_PureFunc0 62
|
|
-#define OP_Function0 63 /* synopsis: r[P3]=func(r[P2@P5]) */
|
|
-#define OP_PureFunc 64
|
|
-#define OP_Function 65 /* synopsis: r[P3]=func(r[P2@P5]) */
|
|
-#define OP_Return 66
|
|
-#define OP_EndCoroutine 67
|
|
-#define OP_HaltIfNull 68 /* synopsis: if r[P3]=null halt */
|
|
-#define OP_Halt 69
|
|
-#define OP_Integer 70 /* synopsis: r[P2]=P1 */
|
|
-#define OP_Int64 71 /* synopsis: r[P2]=P4 */
|
|
-#define OP_String 72 /* synopsis: r[P2]='P4' (len=P1) */
|
|
-#define OP_Null 73 /* synopsis: r[P2..P3]=NULL */
|
|
-#define OP_SoftNull 74 /* synopsis: r[P1]=NULL */
|
|
-#define OP_Blob 75 /* synopsis: r[P2]=P4 (len=P1) */
|
|
-#define OP_Variable 76 /* synopsis: r[P2]=parameter(P1,P4) */
|
|
-#define OP_Move 77 /* synopsis: r[P2@P3]=r[P1@P3] */
|
|
-#define OP_Copy 78 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
|
|
-#define OP_SCopy 79 /* synopsis: r[P2]=r[P1] */
|
|
-#define OP_IntCopy 80 /* synopsis: r[P2]=r[P1] */
|
|
-#define OP_ResultRow 81 /* synopsis: output=r[P1@P2] */
|
|
-#define OP_CollSeq 82
|
|
-#define OP_AddImm 83 /* synopsis: r[P1]=r[P1]+P2 */
|
|
-#define OP_RealAffinity 84
|
|
-#define OP_Cast 85 /* synopsis: affinity(r[P1]) */
|
|
-#define OP_Permutation 86
|
|
-#define OP_Compare 87 /* synopsis: r[P1@P3] <-> r[P2@P3] */
|
|
-#define OP_IsTrue 88 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
|
|
-#define OP_Offset 89 /* synopsis: r[P3] = sqlite_offset(P1) */
|
|
-#define OP_Column 90 /* synopsis: r[P3]=PX */
|
|
-#define OP_Affinity 91 /* synopsis: affinity(r[P1@P2]) */
|
|
-#define OP_MakeRecord 92 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
|
|
-#define OP_Count 93 /* synopsis: r[P2]=count() */
|
|
-#define OP_ReadCookie 94
|
|
-#define OP_SetCookie 95
|
|
-#define OP_BitAnd 96 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
|
|
-#define OP_BitOr 97 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
|
|
-#define OP_ShiftLeft 98 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
|
|
-#define OP_ShiftRight 99 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
|
|
-#define OP_Add 100 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
|
|
-#define OP_Subtract 101 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
|
|
-#define OP_Multiply 102 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
|
|
-#define OP_Divide 103 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
|
|
-#define OP_Remainder 104 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
|
|
-#define OP_Concat 105 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
|
|
-#define OP_ReopenIdx 106 /* synopsis: root=P2 iDb=P3 */
|
|
-#define OP_BitNot 107 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
|
|
-#define OP_OpenRead 108 /* synopsis: root=P2 iDb=P3 */
|
|
-#define OP_OpenWrite 109 /* synopsis: root=P2 iDb=P3 */
|
|
-#define OP_String8 110 /* same as TK_STRING, synopsis: r[P2]='P4' */
|
|
-#define OP_OpenDup 111
|
|
-#define OP_OpenAutoindex 112 /* synopsis: nColumn=P2 */
|
|
-#define OP_OpenEphemeral 113 /* synopsis: nColumn=P2 */
|
|
-#define OP_SorterOpen 114
|
|
-#define OP_SequenceTest 115 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
|
|
-#define OP_OpenPseudo 116 /* synopsis: P3 columns in r[P2] */
|
|
-#define OP_Close 117
|
|
-#define OP_ColumnsUsed 118
|
|
-#define OP_SeekHit 119 /* synopsis: seekHit=P2 */
|
|
-#define OP_Sequence 120 /* synopsis: r[P2]=cursor[P1].ctr++ */
|
|
-#define OP_NewRowid 121 /* synopsis: r[P2]=rowid */
|
|
-#define OP_Insert 122 /* synopsis: intkey=r[P3] data=r[P2] */
|
|
-#define OP_Delete 123
|
|
-#define OP_ResetCount 124
|
|
-#define OP_SorterCompare 125 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
|
|
-#define OP_SorterData 126 /* synopsis: r[P2]=data */
|
|
-#define OP_RowData 127 /* synopsis: r[P2]=data */
|
|
-#define OP_Rowid 128 /* synopsis: r[P2]=rowid */
|
|
-#define OP_NullRow 129
|
|
-#define OP_SeekEnd 130
|
|
+#define OP_DecrJumpZero 59 /* jump, synopsis: if (--r[P1])==0 goto P2 */
|
|
+#define OP_IncrVacuum 60 /* jump */
|
|
+#define OP_VNext 61 /* jump */
|
|
+#define OP_Init 62 /* jump, synopsis: Start at P2 */
|
|
+#define OP_PureFunc 63 /* synopsis: r[P3]=func(r[P2@NP]) */
|
|
+#define OP_Function 64 /* synopsis: r[P3]=func(r[P2@NP]) */
|
|
+#define OP_Return 65
|
|
+#define OP_EndCoroutine 66
|
|
+#define OP_HaltIfNull 67 /* synopsis: if r[P3]=null halt */
|
|
+#define OP_Halt 68
|
|
+#define OP_Integer 69 /* synopsis: r[P2]=P1 */
|
|
+#define OP_Int64 70 /* synopsis: r[P2]=P4 */
|
|
+#define OP_String 71 /* synopsis: r[P2]='P4' (len=P1) */
|
|
+#define OP_Null 72 /* synopsis: r[P2..P3]=NULL */
|
|
+#define OP_SoftNull 73 /* synopsis: r[P1]=NULL */
|
|
+#define OP_Blob 74 /* synopsis: r[P2]=P4 (len=P1) */
|
|
+#define OP_Variable 75 /* synopsis: r[P2]=parameter(P1,P4) */
|
|
+#define OP_Move 76 /* synopsis: r[P2@P3]=r[P1@P3] */
|
|
+#define OP_Copy 77 /* synopsis: r[P2@P3+1]=r[P1@P3+1] */
|
|
+#define OP_SCopy 78 /* synopsis: r[P2]=r[P1] */
|
|
+#define OP_IntCopy 79 /* synopsis: r[P2]=r[P1] */
|
|
+#define OP_ResultRow 80 /* synopsis: output=r[P1@P2] */
|
|
+#define OP_CollSeq 81
|
|
+#define OP_AddImm 82 /* synopsis: r[P1]=r[P1]+P2 */
|
|
+#define OP_RealAffinity 83
|
|
+#define OP_Cast 84 /* synopsis: affinity(r[P1]) */
|
|
+#define OP_Permutation 85
|
|
+#define OP_Compare 86 /* synopsis: r[P1@P3] <-> r[P2@P3] */
|
|
+#define OP_IsTrue 87 /* synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 */
|
|
+#define OP_Offset 88 /* synopsis: r[P3] = sqlite_offset(P1) */
|
|
+#define OP_Column 89 /* synopsis: r[P3]=PX */
|
|
+#define OP_Affinity 90 /* synopsis: affinity(r[P1@P2]) */
|
|
+#define OP_MakeRecord 91 /* synopsis: r[P3]=mkrec(r[P1@P2]) */
|
|
+#define OP_Count 92 /* synopsis: r[P2]=count() */
|
|
+#define OP_ReadCookie 93
|
|
+#define OP_SetCookie 94
|
|
+#define OP_ReopenIdx 95 /* synopsis: root=P2 iDb=P3 */
|
|
+#define OP_OpenRead 96 /* synopsis: root=P2 iDb=P3 */
|
|
+#define OP_OpenWrite 97 /* synopsis: root=P2 iDb=P3 */
|
|
+#define OP_OpenDup 98
|
|
+#define OP_OpenAutoindex 99 /* synopsis: nColumn=P2 */
|
|
+#define OP_OpenEphemeral 100 /* synopsis: nColumn=P2 */
|
|
+#define OP_BitAnd 101 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
|
|
+#define OP_BitOr 102 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
|
|
+#define OP_ShiftLeft 103 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
|
|
+#define OP_ShiftRight 104 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
|
|
+#define OP_Add 105 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
|
|
+#define OP_Subtract 106 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
|
|
+#define OP_Multiply 107 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
|
|
+#define OP_Divide 108 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
|
|
+#define OP_Remainder 109 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
|
|
+#define OP_Concat 110 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
|
|
+#define OP_SorterOpen 111
|
|
+#define OP_BitNot 112 /* same as TK_BITNOT, synopsis: r[P2]= ~r[P1] */
|
|
+#define OP_SequenceTest 113 /* synopsis: if( cursor[P1].ctr++ ) pc = P2 */
|
|
+#define OP_OpenPseudo 114 /* synopsis: P3 columns in r[P2] */
|
|
+#define OP_String8 115 /* same as TK_STRING, synopsis: r[P2]='P4' */
|
|
+#define OP_Close 116
|
|
+#define OP_ColumnsUsed 117
|
|
+#define OP_SeekHit 118 /* synopsis: seekHit=P2 */
|
|
+#define OP_Sequence 119 /* synopsis: r[P2]=cursor[P1].ctr++ */
|
|
+#define OP_NewRowid 120 /* synopsis: r[P2]=rowid */
|
|
+#define OP_Insert 121 /* synopsis: intkey=r[P3] data=r[P2] */
|
|
+#define OP_Delete 122
|
|
+#define OP_ResetCount 123
|
|
+#define OP_SorterCompare 124 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
|
|
+#define OP_SorterData 125 /* synopsis: r[P2]=data */
|
|
+#define OP_RowData 126 /* synopsis: r[P2]=data */
|
|
+#define OP_Rowid 127 /* synopsis: r[P2]=rowid */
|
|
+#define OP_NullRow 128
|
|
+#define OP_SeekEnd 129
|
|
+#define OP_IdxInsert 130 /* synopsis: key=r[P2] */
|
|
#define OP_SorterInsert 131 /* synopsis: key=r[P2] */
|
|
-#define OP_IdxInsert 132 /* synopsis: key=r[P2] */
|
|
-#define OP_IdxDelete 133 /* synopsis: key=r[P2@P3] */
|
|
-#define OP_DeferredSeek 134 /* synopsis: Move P3 to P1.rowid if needed */
|
|
-#define OP_IdxRowid 135 /* synopsis: r[P2]=rowid */
|
|
+#define OP_IdxDelete 132 /* synopsis: key=r[P2@P3] */
|
|
+#define OP_DeferredSeek 133 /* synopsis: Move P3 to P1.rowid if needed */
|
|
+#define OP_IdxRowid 134 /* synopsis: r[P2]=rowid */
|
|
+#define OP_FinishSeek 135
|
|
#define OP_Destroy 136
|
|
#define OP_Clear 137
|
|
#define OP_ResetSorter 138
|
|
@@ -15033,12 +15433,12 @@
|
|
#define OP_LoadAnalysis 142
|
|
#define OP_DropTable 143
|
|
#define OP_DropIndex 144
|
|
-#define OP_Real 145 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
|
|
-#define OP_DropTrigger 146
|
|
-#define OP_IntegrityCk 147
|
|
-#define OP_RowSetAdd 148 /* synopsis: rowset(P1)=r[P2] */
|
|
-#define OP_Param 149
|
|
-#define OP_FkCounter 150 /* synopsis: fkctr[P1]+=P2 */
|
|
+#define OP_DropTrigger 145
|
|
+#define OP_IntegrityCk 146
|
|
+#define OP_RowSetAdd 147 /* synopsis: rowset(P1)=r[P2] */
|
|
+#define OP_Param 148
|
|
+#define OP_FkCounter 149 /* synopsis: fkctr[P1]+=P2 */
|
|
+#define OP_Real 150 /* same as TK_FLOAT, synopsis: r[P2]=P4 */
|
|
#define OP_MemMax 151 /* synopsis: r[P1]=max(r[P1],r[P2]) */
|
|
#define OP_OffsetLimit 152 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
|
|
#define OP_AggInverse 153 /* synopsis: accum=r[P3] inverse(r[P2@P5]) */
|
|
@@ -15047,20 +15447,23 @@
|
|
#define OP_AggValue 156 /* synopsis: r[P3]=value N=P2 */
|
|
#define OP_AggFinal 157 /* synopsis: accum=r[P1] N=P2 */
|
|
#define OP_Expire 158
|
|
-#define OP_TableLock 159 /* synopsis: iDb=P1 root=P2 write=P3 */
|
|
-#define OP_VBegin 160
|
|
-#define OP_VCreate 161
|
|
-#define OP_VDestroy 162
|
|
-#define OP_VOpen 163
|
|
-#define OP_VColumn 164 /* synopsis: r[P3]=vcolumn(P2) */
|
|
-#define OP_VRename 165
|
|
-#define OP_Pagecount 166
|
|
-#define OP_MaxPgcnt 167
|
|
-#define OP_Trace 168
|
|
-#define OP_CursorHint 169
|
|
-#define OP_Noop 170
|
|
-#define OP_Explain 171
|
|
-#define OP_Abortable 172
|
|
+#define OP_CursorLock 159
|
|
+#define OP_CursorUnlock 160
|
|
+#define OP_TableLock 161 /* synopsis: iDb=P1 root=P2 write=P3 */
|
|
+#define OP_VBegin 162
|
|
+#define OP_VCreate 163
|
|
+#define OP_VDestroy 164
|
|
+#define OP_VOpen 165
|
|
+#define OP_VColumn 166 /* synopsis: r[P3]=vcolumn(P2) */
|
|
+#define OP_VRename 167
|
|
+#define OP_Pagecount 168
|
|
+#define OP_MaxPgcnt 169
|
|
+#define OP_Trace 170
|
|
+#define OP_CursorHint 171
|
|
+#define OP_ReleaseReg 172 /* synopsis: release r[P1@P2] mask P3 */
|
|
+#define OP_Noop 173
|
|
+#define OP_Explain 174
|
|
+#define OP_Abortable 175
|
|
|
|
/* Properties such as "out2" or "jump" that are specified in
|
|
** comments following the "case" for each opcode in the vdbe.c
|
|
@@ -15076,25 +15479,26 @@
|
|
/* 0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x10,\
|
|
/* 8 */ 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x03, 0x03,\
|
|
/* 16 */ 0x01, 0x01, 0x03, 0x12, 0x03, 0x01, 0x09, 0x09,\
|
|
-/* 24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
|
|
-/* 32 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
|
|
-/* 40 */ 0x01, 0x23, 0x0b, 0x26, 0x26, 0x01, 0x01, 0x03,\
|
|
+/* 24 */ 0x09, 0x09, 0x01, 0x09, 0x09, 0x09, 0x09, 0x09,\
|
|
+/* 32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
|
|
+/* 40 */ 0x01, 0x01, 0x23, 0x26, 0x26, 0x0b, 0x01, 0x01,\
|
|
/* 48 */ 0x03, 0x03, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
|
|
-/* 56 */ 0x0b, 0x0b, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00,\
|
|
-/* 64 */ 0x00, 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10,\
|
|
-/* 72 */ 0x10, 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,\
|
|
-/* 80 */ 0x10, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00,\
|
|
-/* 88 */ 0x12, 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
|
|
-/* 96 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,\
|
|
-/* 104 */ 0x26, 0x26, 0x00, 0x12, 0x00, 0x00, 0x10, 0x00,\
|
|
-/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
|
-/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
|
-/* 128 */ 0x10, 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10,\
|
|
+/* 56 */ 0x0b, 0x0b, 0x01, 0x03, 0x01, 0x01, 0x01, 0x00,\
|
|
+/* 64 */ 0x00, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
|
|
+/* 72 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
|
|
+/* 80 */ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x12,\
|
|
+/* 88 */ 0x20, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
|
|
+/* 96 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x26, 0x26, 0x26,\
|
|
+/* 104 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\
|
|
+/* 112 */ 0x12, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x10,\
|
|
+/* 120 */ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
|
|
+/* 128 */ 0x00, 0x00, 0x04, 0x04, 0x00, 0x00, 0x10, 0x00,\
|
|
/* 136 */ 0x10, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,\
|
|
-/* 144 */ 0x00, 0x10, 0x00, 0x00, 0x06, 0x10, 0x00, 0x04,\
|
|
+/* 144 */ 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x10, 0x04,\
|
|
/* 152 */ 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
|
-/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
|
|
-/* 168 */ 0x00, 0x00, 0x00, 0x00, 0x00,}
|
|
+/* 160 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
|
+/* 168 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
|
|
+}
|
|
|
|
/* The sqlite3P2Values() routine is able to run faster if it knows
|
|
** the value of the largest JUMP opcode. The smaller the maximum
|
|
@@ -15102,7 +15506,7 @@
|
|
** generated this include file strives to group all JUMP opcodes
|
|
** together near the beginning of the list.
|
|
*/
|
|
-#define SQLITE_MX_JUMP_OPCODE 61 /* Maximum JUMP opcode */
|
|
+#define SQLITE_MX_JUMP_OPCODE 62 /* Maximum JUMP opcode */
|
|
|
|
/************** End of opcodes.h *********************************************/
|
|
/************** Continuing where we left off in vdbe.h ***********************/
|
|
@@ -15118,6 +15522,7 @@
|
|
** for a description of what each of these routines does.
|
|
*/
|
|
SQLITE_PRIVATE Vdbe *sqlite3VdbeCreate(Parse*);
|
|
+SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe*);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp0(Vdbe*,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp1(Vdbe*,int,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp2(Vdbe*,int,int,int);
|
|
@@ -15128,6 +15533,7 @@
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp4(Vdbe*,int,int,int,int,const char *zP4,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp4Dup8(Vdbe*,int,int,int,int,const u8*,int);
|
|
SQLITE_PRIVATE int sqlite3VdbeAddOp4Int(Vdbe*,int,int,int,int,int);
|
|
+SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(Parse*,int,int,int,int,const FuncDef*,int);
|
|
SQLITE_PRIVATE void sqlite3VdbeEndCoroutine(Vdbe*,int);
|
|
#if defined(SQLITE_DEBUG) && !defined(SQLITE_TEST_REALLOC_STRESS)
|
|
SQLITE_PRIVATE void sqlite3VdbeVerifyNoMallocRequired(Vdbe *p, int N);
|
|
@@ -15161,14 +15567,20 @@
|
|
# define sqlite3ExplainBreakpoint(A,B) /*no-op*/
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2);
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3);
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe*, int addr, u8);
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe*, int addr, int P1);
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe*, int addr, int P2);
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe*, int addr, int P3);
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe*, u16 P5);
|
|
SQLITE_PRIVATE void sqlite3VdbeJumpHere(Vdbe*, int addr);
|
|
+SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe*, int addr);
|
|
SQLITE_PRIVATE int sqlite3VdbeChangeToNoop(Vdbe*, int addr);
|
|
SQLITE_PRIVATE int sqlite3VdbeDeletePriorOpcode(Vdbe*, u8 op);
|
|
+#ifdef SQLITE_DEBUG
|
|
+SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(Parse*,int addr, int n, u32 mask, int);
|
|
+#else
|
|
+# define sqlite3VdbeReleaseRegisters(P,A,N,M,F)
|
|
+#endif
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
|
|
SQLITE_PRIVATE void sqlite3VdbeAppendP4(Vdbe*, void *pP4, int p4type);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetP4KeyInfo(Parse*, Index*);
|
|
@@ -15217,11 +15629,13 @@
|
|
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
|
|
SQLITE_PRIVATE RecordCompare sqlite3VdbeFindCompare(UnpackedRecord*);
|
|
|
|
-#ifndef SQLITE_OMIT_TRIGGER
|
|
SQLITE_PRIVATE void sqlite3VdbeLinkSubProgram(Vdbe *, SubProgram *);
|
|
-#endif
|
|
+SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe*);
|
|
|
|
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context*);
|
|
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
|
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3*);
|
|
+#endif
|
|
|
|
/* Use SQLITE_ENABLE_COMMENTS to enable generation of extra comments on
|
|
** each VDBE opcode.
|
|
@@ -15458,9 +15872,6 @@
|
|
/* Functions used to configure a Pager object. */
|
|
SQLITE_PRIVATE void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
|
|
SQLITE_PRIVATE int sqlite3PagerSetPagesize(Pager*, u32*, int);
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager*,Pager*);
|
|
-#endif
|
|
SQLITE_PRIVATE int sqlite3PagerMaxPageCount(Pager*, int);
|
|
SQLITE_PRIVATE void sqlite3PagerSetCachesize(Pager*, int);
|
|
SQLITE_PRIVATE int sqlite3PagerSetSpillsize(Pager*, int);
|
|
@@ -15510,14 +15921,22 @@
|
|
SQLITE_PRIVATE int sqlite3PagerOpenWal(Pager *pPager, int *pisOpen);
|
|
SQLITE_PRIVATE int sqlite3PagerCloseWal(Pager *pPager, sqlite3*);
|
|
# ifdef SQLITE_ENABLE_SNAPSHOT
|
|
-SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager *pPager, sqlite3_snapshot **ppSnapshot);
|
|
-SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot);
|
|
+SQLITE_PRIVATE int sqlite3PagerSnapshotGet(Pager*, sqlite3_snapshot **ppSnapshot);
|
|
+SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager*, sqlite3_snapshot *pSnapshot);
|
|
SQLITE_PRIVATE int sqlite3PagerSnapshotRecover(Pager *pPager);
|
|
SQLITE_PRIVATE int sqlite3PagerSnapshotCheck(Pager *pPager, sqlite3_snapshot *pSnapshot);
|
|
SQLITE_PRIVATE void sqlite3PagerSnapshotUnlock(Pager *pPager);
|
|
# endif
|
|
#endif
|
|
|
|
+#if !defined(SQLITE_OMIT_WAL) && defined(SQLITE_ENABLE_SETLK_TIMEOUT)
|
|
+SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager*, int);
|
|
+SQLITE_PRIVATE void sqlite3PagerWalDb(Pager*, sqlite3*);
|
|
+#else
|
|
+# define sqlite3PagerWalWriteLock(y,z) SQLITE_OK
|
|
+# define sqlite3PagerWalDb(x,y)
|
|
+#endif
|
|
+
|
|
#ifdef SQLITE_DIRECT_OVERFLOW_READ
|
|
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno);
|
|
#endif
|
|
@@ -15533,7 +15952,7 @@
|
|
SQLITE_PRIVATE int sqlite3PagerRefcount(Pager*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3PagerMemUsed(Pager*);
|
|
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager*, int);
|
|
+SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager*, int);
|
|
SQLITE_PRIVATE sqlite3_vfs *sqlite3PagerVfs(Pager*);
|
|
SQLITE_PRIVATE sqlite3_file *sqlite3PagerFile(Pager*);
|
|
SQLITE_PRIVATE sqlite3_file *sqlite3PagerJrnlFile(Pager*);
|
|
@@ -15543,21 +15962,12 @@
|
|
SQLITE_PRIVATE void sqlite3PagerCacheStat(Pager *, int, int, int *);
|
|
SQLITE_PRIVATE void sqlite3PagerClearCache(Pager*);
|
|
SQLITE_PRIVATE int sqlite3SectorSize(sqlite3_file *);
|
|
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
-SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager);
|
|
-#else
|
|
-# define sqlite3PagerResetLockTimeout(X)
|
|
-#endif
|
|
|
|
/* Functions used to truncate the database file. */
|
|
SQLITE_PRIVATE void sqlite3PagerTruncateImage(Pager*,Pgno);
|
|
|
|
SQLITE_PRIVATE void sqlite3PagerRekey(DbPage*, Pgno, u16);
|
|
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_WAL)
|
|
-SQLITE_PRIVATE void *sqlite3PagerCodec(DbPage *);
|
|
-#endif
|
|
-
|
|
/* Functions to support testing and debugging. */
|
|
#if !defined(NDEBUG) || defined(SQLITE_TEST)
|
|
SQLITE_PRIVATE Pgno sqlite3PagerPagenumber(DbPage*);
|
|
@@ -16121,6 +16531,7 @@
|
|
#define MUTEX_LOGIC(X)
|
|
#else
|
|
#define MUTEX_LOGIC(X) X
|
|
+SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
|
|
#endif /* defined(SQLITE_MUTEX_OMIT) */
|
|
|
|
/************** End of mutex.h ***********************************************/
|
|
@@ -16224,7 +16635,6 @@
|
|
*/
|
|
#define DB_SchemaLoaded 0x0001 /* The schema has been loaded */
|
|
#define DB_UnresetViews 0x0002 /* Some views have defined column names */
|
|
-#define DB_Empty 0x0004 /* The file is empty (length 0 bytes) */
|
|
#define DB_ResetWanted 0x0008 /* Reset the schema when nSchemaLock==0 */
|
|
|
|
/*
|
|
@@ -16252,15 +16662,47 @@
|
|
** is shared by multiple database connections. Therefore, while parsing
|
|
** schema information, the Lookaside.bEnabled flag is cleared so that
|
|
** lookaside allocations are not used to construct the schema objects.
|
|
+**
|
|
+** New lookaside allocations are only allowed if bDisable==0. When
|
|
+** bDisable is greater than zero, sz is set to zero which effectively
|
|
+** disables lookaside without adding a new test for the bDisable flag
|
|
+** in a performance-critical path. sz should be set by to szTrue whenever
|
|
+** bDisable changes back to zero.
|
|
+**
|
|
+** Lookaside buffers are initially held on the pInit list. As they are
|
|
+** used and freed, they are added back to the pFree list. New allocations
|
|
+** come off of pFree first, then pInit as a fallback. This dual-list
|
|
+** allows use to compute a high-water mark - the maximum number of allocations
|
|
+** outstanding at any point in the past - by subtracting the number of
|
|
+** allocations on the pInit list from the total number of allocations.
|
|
+**
|
|
+** Enhancement on 2019-12-12: Two-size-lookaside
|
|
+** The default lookaside configuration is 100 slots of 1200 bytes each.
|
|
+** The larger slot sizes are important for performance, but they waste
|
|
+** a lot of space, as most lookaside allocations are less than 128 bytes.
|
|
+** The two-size-lookaside enhancement breaks up the lookaside allocation
|
|
+** into two pools: One of 128-byte slots and the other of the default size
|
|
+** (1200-byte) slots. Allocations are filled from the small-pool first,
|
|
+** failing over to the full-size pool if that does not work. Thus more
|
|
+** lookaside slots are available while also using less memory.
|
|
+** This enhancement can be omitted by compiling with
|
|
+** SQLITE_OMIT_TWOSIZE_LOOKASIDE.
|
|
*/
|
|
struct Lookaside {
|
|
u32 bDisable; /* Only operate the lookaside when zero */
|
|
u16 sz; /* Size of each buffer in bytes */
|
|
+ u16 szTrue; /* True value of sz, even if disabled */
|
|
u8 bMalloced; /* True if pStart obtained from sqlite3_malloc() */
|
|
u32 nSlot; /* Number of lookaside slots allocated */
|
|
u32 anStat[3]; /* 0: hits. 1: size misses. 2: full misses */
|
|
LookasideSlot *pInit; /* List of buffers not previously used */
|
|
LookasideSlot *pFree; /* List of available buffers */
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ LookasideSlot *pSmallInit; /* List of small buffers not prediously used */
|
|
+ LookasideSlot *pSmallFree; /* List of available small buffers */
|
|
+ void *pMiddle; /* First byte past end of full-size buffers and
|
|
+ ** the first byte of LOOKASIDE_SMALL buffers */
|
|
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
void *pStart; /* First byte of available memory space */
|
|
void *pEnd; /* First byte past end of available space */
|
|
};
|
|
@@ -16268,6 +16710,17 @@
|
|
LookasideSlot *pNext; /* Next buffer in the list of free buffers */
|
|
};
|
|
|
|
+#define DisableLookaside db->lookaside.bDisable++;db->lookaside.sz=0
|
|
+#define EnableLookaside db->lookaside.bDisable--;\
|
|
+ db->lookaside.sz=db->lookaside.bDisable?0:db->lookaside.szTrue
|
|
+
|
|
+/* Size of the smaller allocations in two-size lookside */
|
|
+#ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+# define LOOKASIDE_SMALL 0
|
|
+#else
|
|
+# define LOOKASIDE_SMALL 128
|
|
+#endif
|
|
+
|
|
/*
|
|
** A hash table for built-in function definitions. (Application-defined
|
|
** functions use a regular table table from hash.h.)
|
|
@@ -16339,7 +16792,7 @@
|
|
struct sqlite3 {
|
|
sqlite3_vfs *pVfs; /* OS Interface */
|
|
struct Vdbe *pVdbe; /* List of active virtual machines */
|
|
- CollSeq *pDfltColl; /* The default collating sequence (BINARY) */
|
|
+ CollSeq *pDfltColl; /* BINARY collseq for the database encoding */
|
|
sqlite3_mutex *mutex; /* Connection mutex */
|
|
Db *aDb; /* All backends */
|
|
int nDb; /* Number of backends currently in use */
|
|
@@ -16379,6 +16832,7 @@
|
|
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
|
|
unsigned imposterTable : 1; /* Building an imposter table */
|
|
unsigned reopenMemdb : 1; /* ATTACH is really a reopen using MemDB */
|
|
+ char **azInit; /* "type", "name", and "tbl_name" columns */
|
|
} init;
|
|
int nVdbeActive; /* Number of VDBEs currently running */
|
|
int nVdbeRead; /* Number of active VDBEs that read or write */
|
|
@@ -16441,6 +16895,7 @@
|
|
BusyHandler busyHandler; /* Busy callback */
|
|
Db aDbStatic[2]; /* Static space for the 2 default backends */
|
|
Savepoint *pSavepoint; /* List of active savepoints */
|
|
+ int nAnalysisLimit; /* Number of index rows to ANALYZE */
|
|
int busyTimeout; /* Busy handler timeout, in msec */
|
|
int nSavepoint; /* Number of non-transaction savepoints */
|
|
int nStatement; /* Number of nested statement-transactions */
|
|
@@ -16475,6 +16930,13 @@
|
|
#define SCHEMA_ENC(db) ((db)->aDb[0].pSchema->enc)
|
|
#define ENC(db) ((db)->enc)
|
|
|
|
+/*
|
|
+** A u64 constant where the lower 32 bits are all zeros. Only the
|
|
+** upper 32 bits are included in the argument. Necessary because some
|
|
+** C-compilers still do not accept LL integer literals.
|
|
+*/
|
|
+#define HI(X) ((u64)(X)<<32)
|
|
+
|
|
/*
|
|
** Possible values for the sqlite3.flags.
|
|
**
|
|
@@ -16490,9 +16952,8 @@
|
|
#define SQLITE_CkptFullFSync 0x00000010 /* Use full fsync for checkpoint */
|
|
#define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */
|
|
#define SQLITE_ShortColNames 0x00000040 /* Show short columns names */
|
|
-#define SQLITE_CountRows 0x00000080 /* Count rows changed by INSERT, */
|
|
- /* DELETE, or UPDATE and return */
|
|
- /* the count using a callback. */
|
|
+#define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and
|
|
+ ** vtabs in the schema definition */
|
|
#define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */
|
|
/* result set is empty */
|
|
#define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */
|
|
@@ -16517,16 +16978,19 @@
|
|
#define SQLITE_Defensive 0x10000000 /* Input SQL is likely hostile */
|
|
#define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/
|
|
#define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/
|
|
+#define SQLITE_EnableView 0x80000000 /* Enable the use of views */
|
|
+#define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */
|
|
+ /* DELETE, or UPDATE and return */
|
|
+ /* the count using a callback. */
|
|
|
|
/* Flags used only if debugging */
|
|
-#define HI(X) ((u64)(X)<<32)
|
|
#ifdef SQLITE_DEBUG
|
|
-#define SQLITE_SqlTrace HI(0x0001) /* Debug print SQL as it executes */
|
|
-#define SQLITE_VdbeListing HI(0x0002) /* Debug listings of VDBE progs */
|
|
-#define SQLITE_VdbeTrace HI(0x0004) /* True to trace VDBE execution */
|
|
-#define SQLITE_VdbeAddopTrace HI(0x0008) /* Trace sqlite3VdbeAddOp() calls */
|
|
-#define SQLITE_VdbeEQP HI(0x0010) /* Debug EXPLAIN QUERY PLAN */
|
|
-#define SQLITE_ParserTrace HI(0x0020) /* PRAGMA parser_trace=ON */
|
|
+#define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */
|
|
+#define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */
|
|
+#define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */
|
|
+#define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */
|
|
+#define SQLITE_VdbeEQP HI(0x1000000) /* Debug EXPLAIN QUERY PLAN */
|
|
+#define SQLITE_ParserTrace HI(0x2000000) /* PRAGMA parser_trace=ON */
|
|
#endif
|
|
|
|
/*
|
|
@@ -16537,6 +17001,8 @@
|
|
#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
|
|
#define DBFLAG_VacuumInto 0x0008 /* Currently running VACUUM INTO */
|
|
#define DBFLAG_SchemaKnownOk 0x0010 /* Schema is known to be valid */
|
|
+#define DBFLAG_InternalFunc 0x0020 /* Allow use of internal functions */
|
|
+#define DBFLAG_EncodingFixed 0x0040 /* No longer possible to change enc. */
|
|
|
|
/*
|
|
** Bits of the sqlite3.dbOptFlags field that are used by the
|
|
@@ -16554,8 +17020,8 @@
|
|
#define SQLITE_OmitNoopJoin 0x0100 /* Omit unused tables in joins */
|
|
#define SQLITE_CountOfView 0x0200 /* The count-of-view optimization */
|
|
#define SQLITE_CursorHints 0x0400 /* Add OP_CursorHint opcodes */
|
|
-#define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */
|
|
- /* TH3 expects the Stat34 ^^^^^^ value to be 0x0800. Don't change it */
|
|
+#define SQLITE_Stat4 0x0800 /* Use STAT4 data */
|
|
+ /* TH3 expects the Stat4 ^^^^^^ value to be 0x0800. Don't change it */
|
|
#define SQLITE_PushDown 0x1000 /* The push-down optimization */
|
|
#define SQLITE_SimplifyJoin 0x2000 /* Convert LEFT JOIN to JOIN */
|
|
#define SQLITE_SkipScan 0x4000 /* Skip-scans */
|
|
@@ -16643,6 +17109,8 @@
|
|
** SQLITE_FUNC_LENGTH == OPFLAG_LENGTHARG
|
|
** SQLITE_FUNC_TYPEOF == OPFLAG_TYPEOFARG
|
|
** SQLITE_FUNC_CONSTANT == SQLITE_DETERMINISTIC from the API
|
|
+** SQLITE_FUNC_DIRECT == SQLITE_DIRECTONLY from the API
|
|
+** SQLITE_FUNC_UNSAFE == SQLITE_INNOCUOUS
|
|
** SQLITE_FUNC_ENCMASK depends on SQLITE_UTF* macros in the API
|
|
*/
|
|
#define SQLITE_FUNC_ENCMASK 0x0003 /* SQLITE_UTF8, SQLITE_UTF16BE or UTF16LE */
|
|
@@ -16653,16 +17121,29 @@
|
|
#define SQLITE_FUNC_LENGTH 0x0040 /* Built-in length() function */
|
|
#define SQLITE_FUNC_TYPEOF 0x0080 /* Built-in typeof() function */
|
|
#define SQLITE_FUNC_COUNT 0x0100 /* Built-in count(*) aggregate */
|
|
-#define SQLITE_FUNC_COALESCE 0x0200 /* Built-in coalesce() or ifnull() */
|
|
+/* 0x0200 -- available for reuse */
|
|
#define SQLITE_FUNC_UNLIKELY 0x0400 /* Built-in unlikely() function */
|
|
#define SQLITE_FUNC_CONSTANT 0x0800 /* Constant inputs give a constant output */
|
|
#define SQLITE_FUNC_MINMAX 0x1000 /* True for min() and max() aggregates */
|
|
#define SQLITE_FUNC_SLOCHNG 0x2000 /* "Slow Change". Value constant during a
|
|
** single query - might change over time */
|
|
-#define SQLITE_FUNC_AFFINITY 0x4000 /* Built-in affinity() function */
|
|
+#define SQLITE_FUNC_TEST 0x4000 /* Built-in testing functions */
|
|
#define SQLITE_FUNC_OFFSET 0x8000 /* Built-in sqlite_offset() function */
|
|
#define SQLITE_FUNC_WINDOW 0x00010000 /* Built-in window-only function */
|
|
#define SQLITE_FUNC_INTERNAL 0x00040000 /* For use by NestedParse() only */
|
|
+#define SQLITE_FUNC_DIRECT 0x00080000 /* Not for use in TRIGGERs or VIEWs */
|
|
+#define SQLITE_FUNC_SUBTYPE 0x00100000 /* Result likely to have sub-type */
|
|
+#define SQLITE_FUNC_UNSAFE 0x00200000 /* Function has side effects */
|
|
+#define SQLITE_FUNC_INLINE 0x00400000 /* Functions implemented in-line */
|
|
+
|
|
+/* Identifier numbers for each in-line function */
|
|
+#define INLINEFUNC_coalesce 0
|
|
+#define INLINEFUNC_implies_nonnull_row 1
|
|
+#define INLINEFUNC_expr_implies_expr 2
|
|
+#define INLINEFUNC_expr_compare 3
|
|
+#define INLINEFUNC_affinity 4
|
|
+#define INLINEFUNC_iif 5
|
|
+#define INLINEFUNC_unlikely 99 /* Default case */
|
|
|
|
/*
|
|
** The following three macros, FUNCTION(), LIKEFUNC() and AGGREGATE() are
|
|
@@ -16678,6 +17159,22 @@
|
|
** VFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag.
|
|
**
|
|
+** SFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
+** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
|
|
+** adds the SQLITE_DIRECTONLY flag.
|
|
+**
|
|
+** INLINE_FUNC(zName, nArg, iFuncId, mFlags)
|
|
+** zName is the name of a function that is implemented by in-line
|
|
+** byte code rather than by the usual callbacks. The iFuncId
|
|
+** parameter determines the function id. The mFlags parameter is
|
|
+** optional SQLITE_FUNC_ flags for this function.
|
|
+**
|
|
+** TEST_FUNC(zName, nArg, iFuncId, mFlags)
|
|
+** zName is the name of a test-only function implemented by in-line
|
|
+** byte code rather than by the usual callbacks. The iFuncId
|
|
+** parameter determines the function id. The mFlags parameter is
|
|
+** optional SQLITE_FUNC_ flags for this function.
|
|
+**
|
|
** DFUNCTION(zName, nArg, iArg, bNC, xFunc)
|
|
** Like FUNCTION except it omits the SQLITE_FUNC_CONSTANT flag and
|
|
** adds the SQLITE_FUNC_SLOCHNG flag. Used for date & time functions
|
|
@@ -16717,6 +17214,16 @@
|
|
#define VFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_UTF8|(bNC*SQLITE_FUNC_NEEDCOLL), \
|
|
SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
+#define SFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
+ {nArg, SQLITE_UTF8|SQLITE_DIRECTONLY|SQLITE_FUNC_UNSAFE, \
|
|
+ SQLITE_INT_TO_PTR(iArg), 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
+#define INLINE_FUNC(zName, nArg, iArg, mFlags) \
|
|
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
|
|
+ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
|
|
+#define TEST_FUNC(zName, nArg, iArg, mFlags) \
|
|
+ {nArg, SQLITE_UTF8|SQLITE_FUNC_INTERNAL|SQLITE_FUNC_TEST| \
|
|
+ SQLITE_FUNC_INLINE|SQLITE_FUNC_CONSTANT|(mFlags), \
|
|
+ SQLITE_INT_TO_PTR(iArg), 0, noopFunc, 0, 0, 0, #zName, {0} }
|
|
#define DFUNCTION(zName, nArg, iArg, bNC, xFunc) \
|
|
{nArg, SQLITE_FUNC_SLOCHNG|SQLITE_UTF8, \
|
|
0, 0, xFunc, 0, 0, 0, #zName, {0} }
|
|
@@ -16732,12 +17239,6 @@
|
|
#define LIKEFUNC(zName, nArg, arg, flags) \
|
|
{nArg, SQLITE_FUNC_CONSTANT|SQLITE_UTF8|flags, \
|
|
(void *)arg, 0, likeFunc, 0, 0, 0, #zName, {0} }
|
|
-#define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue) \
|
|
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL), \
|
|
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,0,#zName, {0}}
|
|
-#define AGGREGATE2(zName, nArg, arg, nc, xStep, xFinal, extraFlags) \
|
|
- {nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|extraFlags, \
|
|
- SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xFinal,0,#zName, {0}}
|
|
#define WAGGREGATE(zName, nArg, arg, nc, xStep, xFinal, xValue, xInverse, f) \
|
|
{nArg, SQLITE_UTF8|(nc*SQLITE_FUNC_NEEDCOLL)|f, \
|
|
SQLITE_INT_TO_PTR(arg), 0, xStep,xFinal,xValue,xInverse,#zName, {0}}
|
|
@@ -16776,32 +17277,53 @@
|
|
struct Module {
|
|
const sqlite3_module *pModule; /* Callback pointers */
|
|
const char *zName; /* Name passed to create_module() */
|
|
+ int nRefModule; /* Number of pointers to this object */
|
|
void *pAux; /* pAux passed to create_module() */
|
|
void (*xDestroy)(void *); /* Module destructor function */
|
|
Table *pEpoTab; /* Eponymous table for this module */
|
|
};
|
|
|
|
/*
|
|
-** information about each column of an SQL table is held in an instance
|
|
-** of this structure.
|
|
+** Information about each column of an SQL table is held in an instance
|
|
+** of the Column structure, in the Table.aCol[] array.
|
|
+**
|
|
+** Definitions:
|
|
+**
|
|
+** "table column index" This is the index of the column in the
|
|
+** Table.aCol[] array, and also the index of
|
|
+** the column in the original CREATE TABLE stmt.
|
|
+**
|
|
+** "storage column index" This is the index of the column in the
|
|
+** record BLOB generated by the OP_MakeRecord
|
|
+** opcode. The storage column index is less than
|
|
+** or equal to the table column index. It is
|
|
+** equal if and only if there are no VIRTUAL
|
|
+** columns to the left.
|
|
*/
|
|
struct Column {
|
|
char *zName; /* Name of this column, \000, then the type */
|
|
- Expr *pDflt; /* Default value of this column */
|
|
+ Expr *pDflt; /* Default value or GENERATED ALWAYS AS value */
|
|
char *zColl; /* Collating sequence. If NULL, use the default */
|
|
u8 notNull; /* An OE_ code for handling a NOT NULL constraint */
|
|
char affinity; /* One of the SQLITE_AFF_... values */
|
|
u8 szEst; /* Estimated size of value in this column. sizeof(INT)==1 */
|
|
- u8 colFlags; /* Boolean properties. See COLFLAG_ defines below */
|
|
+ u8 hName; /* Column name hash for faster lookup */
|
|
+ u16 colFlags; /* Boolean properties. See COLFLAG_ defines below */
|
|
};
|
|
|
|
/* Allowed values for Column.colFlags:
|
|
*/
|
|
-#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
|
|
-#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
|
|
-#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
|
|
-#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
|
|
+#define COLFLAG_PRIMKEY 0x0001 /* Column is part of the primary key */
|
|
+#define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */
|
|
+#define COLFLAG_HASTYPE 0x0004 /* Type name follows column name */
|
|
+#define COLFLAG_UNIQUE 0x0008 /* Column def contains "UNIQUE" or "PK" */
|
|
#define COLFLAG_SORTERREF 0x0010 /* Use sorter-refs with this column */
|
|
+#define COLFLAG_VIRTUAL 0x0020 /* GENERATED ALWAYS AS ... VIRTUAL */
|
|
+#define COLFLAG_STORED 0x0040 /* GENERATED ALWAYS AS ... STORED */
|
|
+#define COLFLAG_NOTAVAIL 0x0080 /* STORED column not yet calculated */
|
|
+#define COLFLAG_BUSY 0x0100 /* Blocks recursion on GENERATED columns */
|
|
+#define COLFLAG_GENERATED 0x0060 /* Combo: _STORED, _VIRTUAL */
|
|
+#define COLFLAG_NOINSERT 0x0062 /* Combo: _HIDDEN, _STORED, _VIRTUAL */
|
|
|
|
/*
|
|
** A "Collating Sequence" is defined by an instance of the following
|
|
@@ -16841,11 +17363,12 @@
|
|
** Note also that the numeric types are grouped together so that testing
|
|
** for a numeric type is a single comparison. And the BLOB type is first.
|
|
*/
|
|
-#define SQLITE_AFF_BLOB 'A'
|
|
-#define SQLITE_AFF_TEXT 'B'
|
|
-#define SQLITE_AFF_NUMERIC 'C'
|
|
-#define SQLITE_AFF_INTEGER 'D'
|
|
-#define SQLITE_AFF_REAL 'E'
|
|
+#define SQLITE_AFF_NONE 0x40 /* '@' */
|
|
+#define SQLITE_AFF_BLOB 0x41 /* 'A' */
|
|
+#define SQLITE_AFF_TEXT 0x42 /* 'B' */
|
|
+#define SQLITE_AFF_NUMERIC 0x43 /* 'C' */
|
|
+#define SQLITE_AFF_INTEGER 0x44 /* 'D' */
|
|
+#define SQLITE_AFF_REAL 0x45 /* 'E' */
|
|
|
|
#define sqlite3IsNumericAffinity(X) ((X)>=SQLITE_AFF_NUMERIC)
|
|
|
|
@@ -16918,10 +17441,17 @@
|
|
sqlite3_vtab *pVtab; /* Pointer to vtab instance */
|
|
int nRef; /* Number of pointers to this structure */
|
|
u8 bConstraint; /* True if constraints are supported */
|
|
+ u8 eVtabRisk; /* Riskiness of allowing hacker access */
|
|
int iSavepoint; /* Depth of the SAVEPOINT stack */
|
|
VTable *pNext; /* Next in linked list (see above) */
|
|
};
|
|
|
|
+/* Allowed values for VTable.eVtabRisk
|
|
+*/
|
|
+#define SQLITE_VTABRISK_Low 0
|
|
+#define SQLITE_VTABRISK_Normal 1
|
|
+#define SQLITE_VTABRISK_High 2
|
|
+
|
|
/*
|
|
** The schema for each SQL table and view is represented in memory
|
|
** by an instance of the following structure.
|
|
@@ -16940,6 +17470,7 @@
|
|
u32 tabFlags; /* Mask of TF_* values */
|
|
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
|
|
i16 nCol; /* Number of columns in this table */
|
|
+ i16 nNVCol; /* Number of columns that are not VIRTUAL */
|
|
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
|
|
LogEst szTabRow; /* Estimated size of each table row in bytes */
|
|
#ifdef SQLITE_ENABLE_COSTMULT
|
|
@@ -16966,20 +17497,28 @@
|
|
** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
|
|
** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
|
|
** the TF_OOOHidden attribute would apply in this case. Such tables require
|
|
-** special handling during INSERT processing.
|
|
+** special handling during INSERT processing. The "OOO" means "Out Of Order".
|
|
+**
|
|
+** Constraints:
|
|
+**
|
|
+** TF_HasVirtual == COLFLAG_Virtual
|
|
+** TF_HasStored == COLFLAG_Stored
|
|
*/
|
|
#define TF_Readonly 0x0001 /* Read-only system table */
|
|
#define TF_Ephemeral 0x0002 /* An ephemeral table */
|
|
#define TF_HasPrimaryKey 0x0004 /* Table has a primary key */
|
|
#define TF_Autoincrement 0x0008 /* Integer primary key is autoincrement */
|
|
#define TF_HasStat1 0x0010 /* nRowLogEst set from sqlite_stat1 */
|
|
-#define TF_WithoutRowid 0x0020 /* No rowid. PRIMARY KEY is the key */
|
|
-#define TF_NoVisibleRowid 0x0040 /* No user-visible "rowid" column */
|
|
-#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
|
|
+#define TF_HasVirtual 0x0020 /* Has one or more VIRTUAL columns */
|
|
+#define TF_HasStored 0x0040 /* Has one or more STORED columns */
|
|
+#define TF_HasGenerated 0x0060 /* Combo: HasVirtual + HasStored */
|
|
+#define TF_WithoutRowid 0x0080 /* No rowid. PRIMARY KEY is the key */
|
|
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
|
|
** Index.aiRowLogEst[] values */
|
|
-#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
|
|
-#define TF_Shadow 0x0400 /* True for a shadow table */
|
|
+#define TF_NoVisibleRowid 0x0200 /* No user-visible "rowid" column */
|
|
+#define TF_OOOHidden 0x0400 /* Out-of-Order hidden columns */
|
|
+#define TF_HasNotNull 0x0800 /* Contains NOT NULL constraints */
|
|
+#define TF_Shadow 0x1000 /* True for a shadow table */
|
|
|
|
/*
|
|
** Test to see whether or not a table is a virtual table. This is
|
|
@@ -16988,8 +17527,11 @@
|
|
*/
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
# define IsVirtual(X) ((X)->nModuleArg)
|
|
+# define ExprIsVtab(X) \
|
|
+ ((X)->op==TK_COLUMN && (X)->y.pTab!=0 && (X)->y.pTab->nModuleArg)
|
|
#else
|
|
# define IsVirtual(X) 0
|
|
+# define ExprIsVtab(X) 0
|
|
#endif
|
|
|
|
/*
|
|
@@ -17113,10 +17655,16 @@
|
|
u16 nKeyField; /* Number of key columns in the index */
|
|
u16 nAllField; /* Total columns, including key plus others */
|
|
sqlite3 *db; /* The database connection */
|
|
- u8 *aSortOrder; /* Sort order for each column. */
|
|
+ u8 *aSortFlags; /* Sort order for each column. */
|
|
CollSeq *aColl[1]; /* Collating sequence for each term of the key */
|
|
};
|
|
|
|
+/*
|
|
+** Allowed bit values for entries in the KeyInfo.aSortFlags[] array.
|
|
+*/
|
|
+#define KEYINFO_ORDER_DESC 0x01 /* DESC sort order */
|
|
+#define KEYINFO_ORDER_BIGNULL 0x02 /* NULL is larger than any other value */
|
|
+
|
|
/*
|
|
** This object holds a record which has been parsed out into individual
|
|
** fields, for the purposes of doing a comparison.
|
|
@@ -17224,7 +17772,8 @@
|
|
unsigned hasStat1:1; /* aiRowLogEst values come from sqlite_stat1 */
|
|
unsigned bNoQuery:1; /* Do not use this index to optimize queries */
|
|
unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
int nSample; /* Number of elements in aSample[] */
|
|
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
|
|
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
|
|
@@ -17256,7 +17805,7 @@
|
|
#define XN_EXPR (-2) /* Indexed column is an expression */
|
|
|
|
/*
|
|
-** Each sample stored in the sqlite_stat3 table is represented in memory
|
|
+** Each sample stored in the sqlite_stat4 table is represented in memory
|
|
** using a structure of this type. See documentation at the top of the
|
|
** analyze.c source file for additional information.
|
|
*/
|
|
@@ -17294,7 +17843,7 @@
|
|
** code for a SELECT that contains aggregate functions.
|
|
**
|
|
** If Expr.op==TK_AGG_COLUMN or TK_AGG_FUNCTION then Expr.pAggInfo is a
|
|
-** pointer to this structure. The Expr.iColumn field is the index in
|
|
+** pointer to this structure. The Expr.iAgg field is the index in
|
|
** AggInfo.aCol[] or AggInfo.aFunc[] of information needed to generate
|
|
** code for that node.
|
|
**
|
|
@@ -17340,10 +17889,10 @@
|
|
** it uses less memory in the Expr object, which is a big memory user
|
|
** in systems with lots of prepared statements. And few applications
|
|
** need more than about 10 or 20 variables. But some extreme users want
|
|
-** to have prepared statements with over 32767 variables, and for them
|
|
+** to have prepared statements with over 32766 variables, and for them
|
|
** the option is available (at compile-time).
|
|
*/
|
|
-#if SQLITE_MAX_VARIABLE_NUMBER<=32767
|
|
+#if SQLITE_MAX_VARIABLE_NUMBER<32767
|
|
typedef i16 ynVar;
|
|
#else
|
|
typedef int ynVar;
|
|
@@ -17414,7 +17963,14 @@
|
|
*/
|
|
struct Expr {
|
|
u8 op; /* Operation performed by this node */
|
|
- char affinity; /* The affinity of the column or 0 if not a column */
|
|
+ char affExpr; /* affinity, or RAISE type */
|
|
+ u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
|
|
+ ** TK_COLUMN: the value of p5 for OP_Column
|
|
+ ** TK_AGG_FUNCTION: nesting depth
|
|
+ ** TK_FUNCTION: NC_SelfRef flag if needs OP_PureFunc */
|
|
+#ifdef SQLITE_DEBUG
|
|
+ u8 vvaFlags; /* Verification flags. */
|
|
+#endif
|
|
u32 flags; /* Various flags. EP_* See below */
|
|
union {
|
|
char *zToken; /* Token value. Zero terminated and dequoted */
|
|
@@ -17445,20 +18001,19 @@
|
|
** TK_REGISTER: register number
|
|
** TK_TRIGGER: 1 -> new, 0 -> old
|
|
** EP_Unlikely: 134217728 times likelihood
|
|
+ ** TK_IN: ephemerial table holding RHS
|
|
+ ** TK_SELECT_COLUMN: Number of columns on the LHS
|
|
** TK_SELECT: 1st register of result vector */
|
|
ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid.
|
|
** TK_VARIABLE: variable number (always >= 1).
|
|
** TK_SELECT_COLUMN: column of the result vector */
|
|
i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
|
|
i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */
|
|
- u8 op2; /* TK_REGISTER/TK_TRUTH: original value of Expr.op
|
|
- ** TK_COLUMN: the value of p5 for OP_Column
|
|
- ** TK_AGG_FUNCTION: nesting depth */
|
|
AggInfo *pAggInfo; /* Used by TK_AGG_COLUMN and TK_AGG_FUNCTION */
|
|
union {
|
|
Table *pTab; /* TK_COLUMN: Table containing column. Can be NULL
|
|
** for a column of an index on an expression */
|
|
- Window *pWin; /* TK_FUNCTION: Window definition for the func */
|
|
+ Window *pWin; /* EP_WinFunc: Window/Filter defn for a function */
|
|
struct { /* TK_IN, TK_SELECT, and TK_EXISTS */
|
|
int iAddr; /* Subroutine entry address */
|
|
int regReturn; /* Register used to hold return address */
|
|
@@ -17473,36 +18028,38 @@
|
|
** EP_Agg == NC_HasAgg == SF_HasAgg
|
|
** EP_Win == NC_HasWin
|
|
*/
|
|
-#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
|
|
-#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
|
|
-#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
|
|
-#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
|
|
-#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
|
|
-#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
|
|
-#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
|
|
-#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
|
|
-#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
|
|
-#define EP_Generic 0x000200 /* Ignore COLLATE or affinity on this tree */
|
|
-#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
|
|
-#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
|
|
-#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
|
|
-#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
|
|
-#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
|
-#define EP_Win 0x008000 /* Contains window functions */
|
|
-#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
|
|
-#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
|
|
-#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
|
-#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
|
|
-#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
|
|
-#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
|
|
-#define EP_Alias 0x400000 /* Is an alias for a result set column */
|
|
-#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
|
|
-#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
|
|
-#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
|
|
-#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
|
|
-#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
|
|
-#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
|
|
-#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
|
|
+#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
|
|
+#define EP_Distinct 0x000002 /* Aggregate function with DISTINCT keyword */
|
|
+#define EP_HasFunc 0x000004 /* Contains one or more functions of any kind */
|
|
+#define EP_FixedCol 0x000008 /* TK_Column with a known fixed value */
|
|
+#define EP_Agg 0x000010 /* Contains one or more aggregate functions */
|
|
+#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
|
|
+#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
|
|
+#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
|
|
+#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE operator */
|
|
+#define EP_Commuted 0x000200 /* Comparison operator has been commuted */
|
|
+#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
|
|
+#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
|
|
+#define EP_Skip 0x001000 /* Operator does not contribute to affinity */
|
|
+#define EP_Reduced 0x002000 /* Expr struct EXPR_REDUCEDSIZE bytes only */
|
|
+#define EP_TokenOnly 0x004000 /* Expr struct EXPR_TOKENONLYSIZE bytes only */
|
|
+#define EP_Win 0x008000 /* Contains window functions */
|
|
+#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
|
|
+ /* 0x020000 // available for reuse */
|
|
+#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
|
|
+#define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */
|
|
+#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
|
|
+#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
|
|
+#define EP_Alias 0x400000 /* Is an alias for a result set column */
|
|
+#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
|
|
+#define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */
|
|
+#define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */
|
|
+#define EP_Quoted 0x4000000 /* TK_ID was originally quoted */
|
|
+#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
|
|
+#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
|
|
+#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
|
|
+#define EP_FromDDL 0x40000000 /* Originates from sqlite_master */
|
|
+ /* 0x80000000 // Available */
|
|
|
|
/*
|
|
** The EP_Propagate mask is a set of properties that automatically propagate
|
|
@@ -17521,14 +18078,24 @@
|
|
#define ExprAlwaysTrue(E) (((E)->flags&(EP_FromJoin|EP_IsTrue))==EP_IsTrue)
|
|
#define ExprAlwaysFalse(E) (((E)->flags&(EP_FromJoin|EP_IsFalse))==EP_IsFalse)
|
|
|
|
+
|
|
+/* Flags for use with Expr.vvaFlags
|
|
+*/
|
|
+#define EP_NoReduce 0x01 /* Cannot EXPRDUP_REDUCE this Expr */
|
|
+#define EP_Immutable 0x02 /* Do not change this Expr node */
|
|
+
|
|
/* The ExprSetVVAProperty() macro is used for Verification, Validation,
|
|
** and Accreditation only. It works like ExprSetProperty() during VVA
|
|
** processes but is a no-op for delivery.
|
|
*/
|
|
#ifdef SQLITE_DEBUG
|
|
-# define ExprSetVVAProperty(E,P) (E)->flags|=(P)
|
|
+# define ExprSetVVAProperty(E,P) (E)->vvaFlags|=(P)
|
|
+# define ExprHasVVAProperty(E,P) (((E)->vvaFlags&(P))!=0)
|
|
+# define ExprClearVVAProperties(E) (E)->vvaFlags = 0
|
|
#else
|
|
# define ExprSetVVAProperty(E,P)
|
|
+# define ExprHasVVAProperty(E,P) 0
|
|
+# define ExprClearVVAProperties(E)
|
|
#endif
|
|
|
|
/*
|
|
@@ -17546,6 +18113,18 @@
|
|
*/
|
|
#define EXPRDUP_REDUCE 0x0001 /* Used reduced-size Expr nodes */
|
|
|
|
+/*
|
|
+** True if the expression passed as an argument was a function with
|
|
+** an OVER() clause (a window function).
|
|
+*/
|
|
+#ifdef SQLITE_OMIT_WINDOWFUNC
|
|
+# define IsWindowFunc(p) 0
|
|
+#else
|
|
+# define IsWindowFunc(p) ( \
|
|
+ ExprHasProperty((p), EP_WinFunc) && p->y.pWin->eFrmType!=TK_FILTER \
|
|
+ )
|
|
+#endif
|
|
+
|
|
/*
|
|
** A list of expressions. Each expression may optionally have a
|
|
** name. An expr/name combination can be used in several ways, such
|
|
@@ -17554,25 +18133,31 @@
|
|
** also be used as the argument to a function, in which case the a.zName
|
|
** field is not used.
|
|
**
|
|
-** By default the Expr.zSpan field holds a human-readable description of
|
|
-** the expression that is used in the generation of error messages and
|
|
-** column labels. In this case, Expr.zSpan is typically the text of a
|
|
-** column expression as it exists in a SELECT statement. However, if
|
|
-** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
|
|
-** of the result column in the form: DATABASE.TABLE.COLUMN. This later
|
|
-** form is used for name resolution with nested FROM clauses.
|
|
+** In order to try to keep memory usage down, the Expr.a.zEName field
|
|
+** is used for multiple purposes:
|
|
+**
|
|
+** eEName Usage
|
|
+** ---------- -------------------------
|
|
+** ENAME_NAME (1) the AS of result set column
|
|
+** (2) COLUMN= of an UPDATE
|
|
+**
|
|
+** ENAME_TAB DB.TABLE.NAME used to resolve names
|
|
+** of subqueries
|
|
+**
|
|
+** ENAME_SPAN Text of the original result set
|
|
+** expression.
|
|
*/
|
|
struct ExprList {
|
|
int nExpr; /* Number of expressions on the list */
|
|
struct ExprList_item { /* For each expression in the list */
|
|
Expr *pExpr; /* The parse tree for this expression */
|
|
- char *zName; /* Token associated with this expression */
|
|
- char *zSpan; /* Original text of the expression */
|
|
- u8 sortOrder; /* 1 for DESC or 0 for ASC */
|
|
+ char *zEName; /* Token associated with this expression */
|
|
+ u8 sortFlags; /* Mask of KEYINFO_ORDER_* flags */
|
|
+ unsigned eEName :2; /* Meaning of zEName */
|
|
unsigned done :1; /* A flag to indicate when processing is finished */
|
|
- unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
|
|
unsigned reusable :1; /* Constant expression is reusable */
|
|
unsigned bSorterRef :1; /* Defer evaluation until after sorting */
|
|
+ unsigned bNulls: 1; /* True if explicit "NULLS FIRST/LAST" */
|
|
union {
|
|
struct {
|
|
u16 iOrderByCol; /* For ORDER BY, column number in result set */
|
|
@@ -17583,6 +18168,13 @@
|
|
} a[1]; /* One slot for each expression in the list */
|
|
};
|
|
|
|
+/*
|
|
+** Allowed values for Expr.a.eEName
|
|
+*/
|
|
+#define ENAME_NAME 0 /* The AS clause of a result set */
|
|
+#define ENAME_SPAN 1 /* Complete text of the result set expression */
|
|
+#define ENAME_TAB 2 /* "DB.TABLE.NAME" for the result set */
|
|
+
|
|
/*
|
|
** An instance of this structure can hold a simple list of identifiers,
|
|
** such as the list "a,b,c" in the following statements:
|
|
@@ -17646,6 +18238,7 @@
|
|
unsigned isCorrelated :1; /* True if sub-query is correlated */
|
|
unsigned viaCoroutine :1; /* Implemented as a co-routine */
|
|
unsigned isRecursive :1; /* True for recursive reference in WITH */
|
|
+ unsigned fromDDL :1; /* Comes from sqlite_master */
|
|
} fg;
|
|
int iCursor; /* The VDBE cursor number used to access this table */
|
|
Expr *pOn; /* The ON clause of a join */
|
|
@@ -17749,21 +18342,24 @@
|
|
** NC_HasWin == EP_Win
|
|
**
|
|
*/
|
|
-#define NC_AllowAgg 0x0001 /* Aggregate functions are allowed here */
|
|
-#define NC_PartIdx 0x0002 /* True if resolving a partial index WHERE */
|
|
-#define NC_IsCheck 0x0004 /* True if resolving names in a CHECK constraint */
|
|
-#define NC_InAggFunc 0x0008 /* True if analyzing arguments to an agg func */
|
|
-#define NC_HasAgg 0x0010 /* One or more aggregate functions seen */
|
|
-#define NC_IdxExpr 0x0020 /* True if resolving columns of CREATE INDEX */
|
|
-#define NC_VarSelect 0x0040 /* A correlated subquery has been seen */
|
|
-#define NC_UEList 0x0080 /* True if uNC.pEList is used */
|
|
-#define NC_UAggInfo 0x0100 /* True if uNC.pAggInfo is used */
|
|
-#define NC_UUpsert 0x0200 /* True if uNC.pUpsert is used */
|
|
-#define NC_MinMaxAgg 0x1000 /* min/max aggregates seen. See note above */
|
|
-#define NC_Complex 0x2000 /* True if a function or subquery seen */
|
|
-#define NC_AllowWin 0x4000 /* Window functions are allowed here */
|
|
-#define NC_HasWin 0x8000 /* One or more window functions seen */
|
|
-#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
|
|
+#define NC_AllowAgg 0x00001 /* Aggregate functions are allowed here */
|
|
+#define NC_PartIdx 0x00002 /* True if resolving a partial index WHERE */
|
|
+#define NC_IsCheck 0x00004 /* True if resolving a CHECK constraint */
|
|
+#define NC_GenCol 0x00008 /* True for a GENERATED ALWAYS AS clause */
|
|
+#define NC_HasAgg 0x00010 /* One or more aggregate functions seen */
|
|
+#define NC_IdxExpr 0x00020 /* True if resolving columns of CREATE INDEX */
|
|
+#define NC_SelfRef 0x0002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */
|
|
+#define NC_VarSelect 0x00040 /* A correlated subquery has been seen */
|
|
+#define NC_UEList 0x00080 /* True if uNC.pEList is used */
|
|
+#define NC_UAggInfo 0x00100 /* True if uNC.pAggInfo is used */
|
|
+#define NC_UUpsert 0x00200 /* True if uNC.pUpsert is used */
|
|
+#define NC_MinMaxAgg 0x01000 /* min/max aggregates seen. See note above */
|
|
+#define NC_Complex 0x02000 /* True if a function or subquery seen */
|
|
+#define NC_AllowWin 0x04000 /* Window functions are allowed here */
|
|
+#define NC_HasWin 0x08000 /* One or more window functions seen */
|
|
+#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
|
|
+#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
|
|
+#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_master */
|
|
|
|
/*
|
|
** An instance of the following object describes a single ON CONFLICT
|
|
@@ -17813,13 +18409,13 @@
|
|
** sequences for the ORDER BY clause.
|
|
*/
|
|
struct Select {
|
|
- ExprList *pEList; /* The fields of the result */
|
|
u8 op; /* One of: TK_UNION TK_ALL TK_INTERSECT TK_EXCEPT */
|
|
LogEst nSelectRow; /* Estimated number of result rows */
|
|
u32 selFlags; /* Various SF_* values */
|
|
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
|
|
u32 selId; /* Unique identifier number for this SELECT */
|
|
int addrOpenEphm[2]; /* OP_OpenEphem opcodes related to this select */
|
|
+ ExprList *pEList; /* The fields of the result */
|
|
SrcList *pSrc; /* The FROM clause */
|
|
Expr *pWhere; /* The WHERE clause */
|
|
ExprList *pGroupBy; /* The GROUP BY clause */
|
|
@@ -17844,25 +18440,28 @@
|
|
** SF_MinMaxAgg == NC_MinMaxAgg == SQLITE_FUNC_MINMAX
|
|
** SF_FixedLimit == WHERE_USE_LIMIT
|
|
*/
|
|
-#define SF_Distinct 0x00001 /* Output should be DISTINCT */
|
|
-#define SF_All 0x00002 /* Includes the ALL keyword */
|
|
-#define SF_Resolved 0x00004 /* Identifiers have been resolved */
|
|
-#define SF_Aggregate 0x00008 /* Contains agg functions or a GROUP BY */
|
|
-#define SF_HasAgg 0x00010 /* Contains aggregate functions */
|
|
-#define SF_UsesEphemeral 0x00020 /* Uses the OpenEphemeral opcode */
|
|
-#define SF_Expanded 0x00040 /* sqlite3SelectExpand() called on this */
|
|
-#define SF_HasTypeInfo 0x00080 /* FROM subqueries have Table metadata */
|
|
-#define SF_Compound 0x00100 /* Part of a compound query */
|
|
-#define SF_Values 0x00200 /* Synthesized from VALUES clause */
|
|
-#define SF_MultiValue 0x00400 /* Single VALUES term with multiple rows */
|
|
-#define SF_NestedFrom 0x00800 /* Part of a parenthesized FROM clause */
|
|
-#define SF_MinMaxAgg 0x01000 /* Aggregate containing min() or max() */
|
|
-#define SF_Recursive 0x02000 /* The recursive part of a recursive CTE */
|
|
-#define SF_FixedLimit 0x04000 /* nSelectRow set by a constant LIMIT */
|
|
-#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
|
|
-#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
|
|
-#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
|
|
-#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
|
|
+#define SF_Distinct 0x0000001 /* Output should be DISTINCT */
|
|
+#define SF_All 0x0000002 /* Includes the ALL keyword */
|
|
+#define SF_Resolved 0x0000004 /* Identifiers have been resolved */
|
|
+#define SF_Aggregate 0x0000008 /* Contains agg functions or a GROUP BY */
|
|
+#define SF_HasAgg 0x0000010 /* Contains aggregate functions */
|
|
+#define SF_UsesEphemeral 0x0000020 /* Uses the OpenEphemeral opcode */
|
|
+#define SF_Expanded 0x0000040 /* sqlite3SelectExpand() called on this */
|
|
+#define SF_HasTypeInfo 0x0000080 /* FROM subqueries have Table metadata */
|
|
+#define SF_Compound 0x0000100 /* Part of a compound query */
|
|
+#define SF_Values 0x0000200 /* Synthesized from VALUES clause */
|
|
+#define SF_MultiValue 0x0000400 /* Single VALUES term with multiple rows */
|
|
+#define SF_NestedFrom 0x0000800 /* Part of a parenthesized FROM clause */
|
|
+#define SF_MinMaxAgg 0x0001000 /* Aggregate containing min() or max() */
|
|
+#define SF_Recursive 0x0002000 /* The recursive part of a recursive CTE */
|
|
+#define SF_FixedLimit 0x0004000 /* nSelectRow set by a constant LIMIT */
|
|
+#define SF_MaybeConvert 0x0008000 /* Need convertCompoundSelectToSubquery() */
|
|
+#define SF_Converted 0x0010000 /* By convertCompoundSelectToSubquery() */
|
|
+#define SF_IncludeHidden 0x0020000 /* Include hidden columns in output */
|
|
+#define SF_ComplexResult 0x0040000 /* Result contains subquery or function */
|
|
+#define SF_WhereBegin 0x0080000 /* Really a WhereBegin() call. Debug Only */
|
|
+#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
|
|
+#define SF_View 0x0200000 /* SELECT statement is a view */
|
|
|
|
/*
|
|
** The results of a SELECT can be distributed in several ways, as defined
|
|
@@ -18142,8 +18741,8 @@
|
|
|
|
#define PARSE_MODE_NORMAL 0
|
|
#define PARSE_MODE_DECLARE_VTAB 1
|
|
-#define PARSE_MODE_RENAME_COLUMN 2
|
|
-#define PARSE_MODE_RENAME_TABLE 3
|
|
+#define PARSE_MODE_RENAME 2
|
|
+#define PARSE_MODE_UNMAP 3
|
|
|
|
/*
|
|
** Sizes and pointers of various parts of the Parse object.
|
|
@@ -18165,7 +18764,7 @@
|
|
#if defined(SQLITE_OMIT_ALTERTABLE)
|
|
#define IN_RENAME_OBJECT 0
|
|
#else
|
|
- #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME_COLUMN)
|
|
+ #define IN_RENAME_OBJECT (pParse->eParseMode>=PARSE_MODE_RENAME)
|
|
#endif
|
|
|
|
#if defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE)
|
|
@@ -18316,7 +18915,7 @@
|
|
struct DbFixer {
|
|
Parse *pParse; /* The parsing context. Error messages written here */
|
|
Schema *pSchema; /* Fix items to this schema */
|
|
- int bVarOnly; /* Check for variable references only */
|
|
+ u8 bTemp; /* True for TEMP schema entries */
|
|
const char *zDb; /* Make sure all objects are contained in this database */
|
|
const char *zType; /* Type of the container - used for error messages */
|
|
const Token *pName; /* Name of the container - used for error messages */
|
|
@@ -18367,11 +18966,12 @@
|
|
*/
|
|
struct Sqlite3Config {
|
|
int bMemstat; /* True to enable memory status */
|
|
- int bCoreMutex; /* True to enable core mutexing */
|
|
- int bFullMutex; /* True to enable full mutexing */
|
|
- int bOpenUri; /* True to interpret filenames as URIs */
|
|
- int bUseCis; /* Use covering indices for full-scans */
|
|
- int bSmallMalloc; /* Avoid large memory allocations if true */
|
|
+ u8 bCoreMutex; /* True to enable core mutexing */
|
|
+ u8 bFullMutex; /* True to enable full mutexing */
|
|
+ u8 bOpenUri; /* True to interpret filenames as URIs */
|
|
+ u8 bUseCis; /* Use covering indices for full-scans */
|
|
+ u8 bSmallMalloc; /* Avoid large memory allocations if true */
|
|
+ u8 bExtraSchemaChecks; /* Verify type,name,tbl_name in schema */
|
|
int mxStrlen; /* Maximum string length */
|
|
int neverCorrupt; /* Database is always well-formed */
|
|
int szLookaside; /* Default lookaside buffer size */
|
|
@@ -18420,9 +19020,9 @@
|
|
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
|
#endif
|
|
int bLocaltimeFault; /* True to fail localtime() calls */
|
|
- int bInternalFunctions; /* Internal SQL functions are visible */
|
|
int iOnceResetThreshold; /* When to reset OP_Once counters */
|
|
u32 szSorterRef; /* Min size in bytes to use sorter-refs */
|
|
+ unsigned int iPrngSeed; /* Alternative fixed seed for the PRNG */
|
|
};
|
|
|
|
/*
|
|
@@ -18452,7 +19052,7 @@
|
|
int (*xSelectCallback)(Walker*,Select*); /* Callback for SELECTs */
|
|
void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
|
|
int walkerDepth; /* Number of subqueries */
|
|
- u8 eCode; /* A small processing code */
|
|
+ u16 eCode; /* A small processing code */
|
|
union { /* Extra data for callback */
|
|
NameContext *pNC; /* Naming context */
|
|
int n; /* A counter */
|
|
@@ -18468,6 +19068,8 @@
|
|
struct WindowRewrite *pRewrite; /* Window rewrite context */
|
|
struct WhereConst *pConst; /* WHERE clause constants */
|
|
struct RenameCtx *pRename; /* RENAME COLUMN context */
|
|
+ struct Table *pTab; /* Table of generated column */
|
|
+ struct SrcList_item *pSrcItem; /* A single FROM clause item */
|
|
} u;
|
|
};
|
|
|
|
@@ -18480,6 +19082,9 @@
|
|
SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker*, Select*);
|
|
SQLITE_PRIVATE int sqlite3SelectWalkFail(Walker*, Select*);
|
|
+SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker*,Select*);
|
|
+SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker*,Select*);
|
|
+
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3SelectWalkAssert2(Walker*, Select*);
|
|
#endif
|
|
@@ -18519,10 +19124,11 @@
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
/*
|
|
-** This object is used in various ways, all related to window functions
|
|
+** This object is used in various ways, most (but not all) related to window
|
|
+** functions.
|
|
**
|
|
** (1) A single instance of this structure is attached to the
|
|
-** the Expr.pWin field for each window function in an expression tree.
|
|
+** the Expr.y.pWin field for each window function in an expression tree.
|
|
** This object holds the information contained in the OVER clause,
|
|
** plus additional fields used during code generation.
|
|
**
|
|
@@ -18533,6 +19139,10 @@
|
|
** (3) The terms of the WINDOW clause of a SELECT are instances of this
|
|
** object on a linked list attached to Select.pWinDefn.
|
|
**
|
|
+** (4) For an aggregate function with a FILTER clause, an instance
|
|
+** of this object is stored in Expr.y.pWin with eFrmType set to
|
|
+** TK_FILTER. In this case the only field used is Window.pFilter.
|
|
+**
|
|
** The uses (1) and (2) are really the same Window object that just happens
|
|
** to be accessible in two different ways. Use case (3) are separate objects.
|
|
*/
|
|
@@ -18548,12 +19158,13 @@
|
|
u8 eExclude; /* TK_NO, TK_CURRENT, TK_TIES, TK_GROUP, or 0 */
|
|
Expr *pStart; /* Expression for "<expr> PRECEDING" */
|
|
Expr *pEnd; /* Expression for "<expr> FOLLOWING" */
|
|
+ Window **ppThis; /* Pointer to this object in Select.pWin list */
|
|
Window *pNextWin; /* Next window function belonging to this SELECT */
|
|
Expr *pFilter; /* The FILTER expression */
|
|
FuncDef *pFunc; /* The function */
|
|
int iEphCsr; /* Partition buffer or Peer buffer */
|
|
- int regAccum;
|
|
- int regResult;
|
|
+ int regAccum; /* Accumulator */
|
|
+ int regResult; /* Interim result */
|
|
int csrApp; /* Function cursor (used by min/max) */
|
|
int regApp; /* Function register (also used by min/max) */
|
|
int regPart; /* Array of registers for PARTITION BY values */
|
|
@@ -18563,15 +19174,19 @@
|
|
int regOne; /* Register containing constant value 1 */
|
|
int regStartRowid;
|
|
int regEndRowid;
|
|
+ u8 bExprArgs; /* Defer evaluation of window function arguments
|
|
+ ** due to the SQLITE_SUBTYPE flag */
|
|
};
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3*, Window*);
|
|
+SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window*);
|
|
SQLITE_PRIVATE void sqlite3WindowListDelete(sqlite3 *db, Window *p);
|
|
SQLITE_PRIVATE Window *sqlite3WindowAlloc(Parse*, int, int, Expr*, int , Expr*, u8);
|
|
SQLITE_PRIVATE void sqlite3WindowAttach(Parse*, Expr*, Window*);
|
|
-SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*);
|
|
-SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Window*);
|
|
+SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin);
|
|
+SQLITE_PRIVATE int sqlite3WindowCompare(Parse*, Window*, Window*, int);
|
|
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse*, Select*);
|
|
SQLITE_PRIVATE void sqlite3WindowCodeStep(Parse*, Select*, WhereInfo*, int, int);
|
|
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse*, Select*);
|
|
SQLITE_PRIVATE int sqlite3ExpandSubquery(Parse*, struct SrcList_item*);
|
|
@@ -18614,13 +19229,16 @@
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3NomemError(int);
|
|
SQLITE_PRIVATE int sqlite3IoerrnomemError(int);
|
|
-SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
|
|
# define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__)
|
|
# define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__)
|
|
-# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
|
|
#else
|
|
# define SQLITE_NOMEM_BKPT SQLITE_NOMEM
|
|
# define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM
|
|
+#endif
|
|
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
|
|
+SQLITE_PRIVATE int sqlite3CorruptPgnoError(int,Pgno);
|
|
+# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P))
|
|
+#else
|
|
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
|
|
#endif
|
|
|
|
@@ -18837,12 +19455,13 @@
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAnd(Parse*,Expr*, Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprSimplifiedAndOr(Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*, int);
|
|
+SQLITE_PRIVATE void sqlite3ExprFunctionUsable(Parse*,Expr*,FuncDef*);
|
|
SQLITE_PRIVATE void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
|
|
SQLITE_PRIVATE void sqlite3ExprDelete(sqlite3*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
|
|
SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
|
SQLITE_PRIVATE ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
|
-SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int);
|
|
+SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList*,int,int);
|
|
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
|
|
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
|
|
@@ -18861,11 +19480,18 @@
|
|
SQLITE_PRIVATE void sqlite3CommitInternalChanges(sqlite3*);
|
|
SQLITE_PRIVATE void sqlite3DeleteColumnNames(sqlite3*,Table*);
|
|
SQLITE_PRIVATE int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
|
|
-SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*);
|
|
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*);
|
|
+SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
|
|
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
|
|
SQLITE_PRIVATE void sqlite3OpenMasterTable(Parse *, int);
|
|
SQLITE_PRIVATE Index *sqlite3PrimaryKeyIndex(Table*);
|
|
-SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index*, i16);
|
|
+SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index*, i16);
|
|
+#ifdef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
|
|
+# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
|
|
+#else
|
|
+SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table*, i16);
|
|
+SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table*, i16);
|
|
+#endif
|
|
SQLITE_PRIVATE void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
|
|
#if SQLITE_ENABLE_HIDDEN_COLUMNS
|
|
SQLITE_PRIVATE void sqlite3ColumnPropertiesFromName(Table*, Column*);
|
|
@@ -18878,14 +19504,11 @@
|
|
SQLITE_PRIVATE void sqlite3AddCheckConstraint(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3AddDefaultValue(Parse*,Expr*,const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3AddCollateType(Parse*, Token*);
|
|
+SQLITE_PRIVATE void sqlite3AddGenerated(Parse*,Expr*,Token*);
|
|
SQLITE_PRIVATE void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
|
|
SQLITE_PRIVATE int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
|
sqlite3_vfs**,char**,char **);
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-SQLITE_PRIVATE int sqlite3CodecQueryParameters(sqlite3*,const char*,const char*);
|
|
-#else
|
|
-# define sqlite3CodecQueryParameters(A,B,C) 0
|
|
-#endif
|
|
+#define sqlite3CodecQueryParameters(A,B,C) 0
|
|
SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
|
|
|
|
#ifdef SQLITE_UNTESTABLE
|
|
@@ -18935,6 +19558,9 @@
|
|
# define sqlite3AutoincrementEnd(X)
|
|
#endif
|
|
SQLITE_PRIVATE void sqlite3Insert(Parse*, SrcList*, Select*, IdList*, int, Upsert*);
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(Parse*, int, Table*);
|
|
+#endif
|
|
SQLITE_PRIVATE void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
|
|
SQLITE_PRIVATE IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
|
|
SQLITE_PRIVATE int sqlite3IdListIndex(IdList*,const char*);
|
|
@@ -18957,6 +19583,7 @@
|
|
SQLITE_PRIVATE Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
|
|
Expr*,ExprList*,u32,Expr*);
|
|
SQLITE_PRIVATE void sqlite3SelectDelete(sqlite3*, Select*);
|
|
+SQLITE_PRIVATE void sqlite3SelectReset(Parse*, Select*);
|
|
SQLITE_PRIVATE Table *sqlite3SrcListLookup(Parse*, SrcList*);
|
|
SQLITE_PRIVATE int sqlite3IsReadOnly(Parse*, Table*, int);
|
|
SQLITE_PRIVATE void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
|
|
@@ -18979,17 +19606,20 @@
|
|
#define ONEPASS_OFF 0 /* Use of ONEPASS not allowed */
|
|
#define ONEPASS_SINGLE 1 /* ONEPASS valid for a single row update */
|
|
#define ONEPASS_MULTI 2 /* ONEPASS is valid for multiple rows */
|
|
+SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo*);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeLoadIndexColumn(Parse*, Index*, int, int, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, u8);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse*, int, int, int);
|
|
SQLITE_PRIVATE void sqlite3ExprCode(Parse*, Expr*, int);
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(Parse*, Column*, int);
|
|
+#endif
|
|
SQLITE_PRIVATE void sqlite3ExprCodeCopy(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse*, Expr*, int);
|
|
-SQLITE_PRIVATE int sqlite3ExprCodeAtInit(Parse*, Expr*, int);
|
|
+SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeTarget(Parse*, Expr*, int);
|
|
-SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse*, Expr*, int);
|
|
SQLITE_PRIVATE int sqlite3ExprCodeExprList(Parse*, ExprList*, int, int, u8);
|
|
#define SQLITE_ECEL_DUP 0x01 /* Deep, not shallow copies */
|
|
#define SQLITE_ECEL_FACTOR 0x02 /* Factor out constant terms */
|
|
@@ -19031,6 +19661,7 @@
|
|
SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
|
|
SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
|
|
SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
|
|
+SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char*);
|
|
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprTruthValue(const Expr*);
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
|
|
@@ -19126,6 +19757,7 @@
|
|
#endif
|
|
|
|
SQLITE_PRIVATE int sqlite3JoinType(Parse*, Token*, Token*, Token*);
|
|
+SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr*,int);
|
|
SQLITE_PRIVATE void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
|
|
SQLITE_PRIVATE void sqlite3DeferForeignKey(Parse*, int);
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
@@ -19140,6 +19772,7 @@
|
|
# define sqlite3AuthContextPush(a,b,c)
|
|
# define sqlite3AuthContextPop(a) ((void)(a))
|
|
#endif
|
|
+SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName);
|
|
SQLITE_PRIVATE void sqlite3Attach(Parse*, Expr*, Expr*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3Detach(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3FixInit(DbFixer*, Parse*, int, const char*, const Token*);
|
|
@@ -19163,7 +19796,7 @@
|
|
SQLITE_PRIVATE LogEst sqlite3LogEstFromDouble(double);
|
|
#endif
|
|
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
|
|
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
|
|
+ defined(SQLITE_ENABLE_STAT4) || \
|
|
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
|
|
SQLITE_PRIVATE u64 sqlite3LogEstToInt(LogEst);
|
|
#endif
|
|
@@ -19188,6 +19821,8 @@
|
|
*/
|
|
#define getVarint32(A,B) \
|
|
(u8)((*(A)<(u8)0x80)?((B)=(u32)*(A)),1:sqlite3GetVarint32((A),(u32 *)&(B)))
|
|
+#define getVarint32NR(A,B) \
|
|
+ B=(u32)*(A);if(B>=0x80)sqlite3GetVarint32((A),(u32*)&(B))
|
|
#define putVarint32(A,B) \
|
|
(u8)(((u32)(B)<(u32)0x80)?(*(A)=(unsigned char)(B)),1:\
|
|
sqlite3PutVarint((A),(B)))
|
|
@@ -19197,10 +19832,10 @@
|
|
|
|
SQLITE_PRIVATE const char *sqlite3IndexAffinityStr(sqlite3*, Index*);
|
|
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe*, Table*, int);
|
|
-SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
|
-SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
|
+SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2);
|
|
+SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity);
|
|
SQLITE_PRIVATE char sqlite3TableColumnAffinity(Table*,int);
|
|
-SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr);
|
|
+SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr);
|
|
SQLITE_PRIVATE int sqlite3Atoi64(const char*, i64*, int, u8);
|
|
SQLITE_PRIVATE int sqlite3DecOrHexToI64(const char*, i64*);
|
|
SQLITE_PRIVATE void sqlite3ErrorWithMsg(sqlite3*, int, const char*,...);
|
|
@@ -19223,15 +19858,17 @@
|
|
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
|
|
SQLITE_PRIVATE int sqlite3IsBinary(const CollSeq*);
|
|
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
|
|
-SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
|
|
-SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr);
|
|
-SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,Expr*,Expr*);
|
|
+SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8);
|
|
+SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr);
|
|
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr);
|
|
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse*,const Expr*,const Expr*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
|
|
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
|
|
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr*);
|
|
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
|
|
SQLITE_PRIVATE int sqlite3WritableSchema(sqlite3*);
|
|
-SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *, const char *);
|
|
+SQLITE_PRIVATE int sqlite3CheckObjectName(Parse*, const char*,const char*,const char*);
|
|
SQLITE_PRIVATE void sqlite3VdbeSetChanges(sqlite3 *, int);
|
|
SQLITE_PRIVATE int sqlite3AddInt64(i64*,i64);
|
|
SQLITE_PRIVATE int sqlite3SubInt64(i64*,i64);
|
|
@@ -19264,7 +19901,6 @@
|
|
SQLITE_PRIVATE const char sqlite3StrBINARY[];
|
|
SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[];
|
|
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[];
|
|
-SQLITE_PRIVATE const Token sqlite3IntTokens[];
|
|
SQLITE_PRIVATE SQLITE_WSD struct Sqlite3Config sqlite3Config;
|
|
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
|
|
#ifndef SQLITE_OMIT_WSD
|
|
@@ -19286,7 +19922,14 @@
|
|
SQLITE_PRIVATE int sqlite3CodeSubselect(Parse*, Expr*);
|
|
SQLITE_PRIVATE void sqlite3SelectPrep(Parse*, Select*, NameContext*);
|
|
SQLITE_PRIVATE void sqlite3SelectWrongNumTermsError(Parse *pParse, Select *p);
|
|
-SQLITE_PRIVATE int sqlite3MatchSpanName(const char*, const char*, const char*, const char*);
|
|
+SQLITE_PRIVATE int sqlite3MatchEName(
|
|
+ const struct ExprList_item*,
|
|
+ const char*,
|
|
+ const char*,
|
|
+ const char*
|
|
+);
|
|
+SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr*);
|
|
+SQLITE_PRIVATE u8 sqlite3StrIHash(const char*);
|
|
SQLITE_PRIVATE int sqlite3ResolveExprNames(NameContext*, Expr*);
|
|
SQLITE_PRIVATE int sqlite3ResolveExprListNames(NameContext*, ExprList*);
|
|
SQLITE_PRIVATE void sqlite3ResolveSelectNames(Parse*, Select*, NameContext*);
|
|
@@ -19302,7 +19945,7 @@
|
|
SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(Parse*, u8, CollSeq *, const char*);
|
|
SQLITE_PRIVATE char sqlite3AffinityType(const char*, Column*);
|
|
SQLITE_PRIVATE void sqlite3Analyze(Parse*, Token*, Token*);
|
|
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*, sqlite3_file*);
|
|
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler*);
|
|
SQLITE_PRIVATE int sqlite3FindDb(sqlite3*, Token*);
|
|
SQLITE_PRIVATE int sqlite3FindDbName(sqlite3 *, const char *);
|
|
SQLITE_PRIVATE int sqlite3AnalysisLoad(sqlite3*,int iDB);
|
|
@@ -19318,6 +19961,7 @@
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoRef(KeyInfo*);
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoOfIndex(Parse*, Index*);
|
|
SQLITE_PRIVATE KeyInfo *sqlite3KeyInfoFromExprList(Parse*, ExprList*, int, int);
|
|
+SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse*, ExprList*);
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3KeyInfoIsWriteable(KeyInfo*);
|
|
@@ -19350,8 +19994,7 @@
|
|
# define sqlite3ExprCheckIN(x,y) SQLITE_OK
|
|
#endif
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void);
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
SQLITE_PRIVATE int sqlite3Stat4ProbeSetValue(
|
|
Parse*,Index*,UnpackedRecord**,Expr*,int,int,int*);
|
|
SQLITE_PRIVATE int sqlite3Stat4ValueFromExpr(Parse*, Expr*, u8, sqlite3_value**);
|
|
@@ -19398,6 +20041,7 @@
|
|
# define sqlite3VtabInSync(db) 0
|
|
# define sqlite3VtabLock(X)
|
|
# define sqlite3VtabUnlock(X)
|
|
+# define sqlite3VtabModuleUnref(D,X)
|
|
# define sqlite3VtabUnlockList(X)
|
|
# define sqlite3VtabSavepoint(X, Y, Z) SQLITE_OK
|
|
# define sqlite3GetVTable(X,Y) ((VTable*)0)
|
|
@@ -19409,6 +20053,7 @@
|
|
SQLITE_PRIVATE int sqlite3VtabCommit(sqlite3 *db);
|
|
SQLITE_PRIVATE void sqlite3VtabLock(VTable *);
|
|
SQLITE_PRIVATE void sqlite3VtabUnlock(VTable *);
|
|
+SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3*,Module*);
|
|
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3*);
|
|
SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *, int, int);
|
|
SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
|
|
@@ -19422,6 +20067,14 @@
|
|
);
|
|
# define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
|
|
#endif
|
|
+SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db);
|
|
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName);
|
|
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3*,Table*,const char*);
|
|
+#else
|
|
+# define sqlite3ShadowTableName(A,B) 0
|
|
+# define sqlite3IsShadowTableOf(A,B,C) 0
|
|
+#endif
|
|
SQLITE_PRIVATE int sqlite3VtabEponymousTableInit(Parse*,Module*);
|
|
SQLITE_PRIVATE void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
|
|
SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse*,Table*);
|
|
@@ -19443,7 +20096,8 @@
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3Reprepare(Vdbe*);
|
|
SQLITE_PRIVATE void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
|
|
-SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);
|
|
+SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse*,const Expr*);
|
|
+SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(Parse *, const Expr*, const Expr*);
|
|
SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3*);
|
|
SQLITE_PRIVATE const char *sqlite3JournalModename(int);
|
|
#ifndef SQLITE_OMIT_WAL
|
|
@@ -19749,7 +20403,6 @@
|
|
** non-ASCII UTF character. Hence the test for whether or not a character is
|
|
** part of an identifier is 0x46.
|
|
*/
|
|
-#ifdef SQLITE_ASCII
|
|
SQLITE_PRIVATE const unsigned char sqlite3CtypeMap[256] = {
|
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 00..07 ........ */
|
|
0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, /* 08..0f ........ */
|
|
@@ -19787,7 +20440,6 @@
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, /* f0..f7 ........ */
|
|
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40 /* f8..ff ........ */
|
|
};
|
|
-#endif
|
|
|
|
/* EVIDENCE-OF: R-02982-34736 In order to maintain full backwards
|
|
** compatibility for legacy applications, the URI filename capability is
|
|
@@ -19799,16 +20451,9 @@
|
|
** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
|
|
** disabled. The default value may be changed by compiling with the
|
|
** SQLITE_USE_URI symbol defined.
|
|
-**
|
|
-** URI filenames are enabled by default if SQLITE_HAS_CODEC is
|
|
-** enabled.
|
|
*/
|
|
#ifndef SQLITE_USE_URI
|
|
-# ifdef SQLITE_HAS_CODEC
|
|
-# define SQLITE_USE_URI 1
|
|
-# else
|
|
-# define SQLITE_USE_URI 0
|
|
-# endif
|
|
+# define SQLITE_USE_URI 0
|
|
#endif
|
|
|
|
/* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
|
|
@@ -19852,9 +20497,18 @@
|
|
** changed as start-time using sqlite3_config(SQLITE_CONFIG_LOOKASIDE)
|
|
** or at run-time for an individual database connection using
|
|
** sqlite3_db_config(db, SQLITE_DBCONFIG_LOOKASIDE);
|
|
+**
|
|
+** With the two-size-lookaside enhancement, less lookaside is required.
|
|
+** The default configuration of 1200,40 actually provides 30 1200-byte slots
|
|
+** and 93 128-byte slots, which is more lookaside than is available
|
|
+** using the older 1200,100 configuration without two-size-lookaside.
|
|
*/
|
|
#ifndef SQLITE_DEFAULT_LOOKASIDE
|
|
-# define SQLITE_DEFAULT_LOOKASIDE 1200,100
|
|
+# ifdef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+# define SQLITE_DEFAULT_LOOKASIDE 1200,100 /* 120KB of memory */
|
|
+# else
|
|
+# define SQLITE_DEFAULT_LOOKASIDE 1200,40 /* 48KB of memory */
|
|
+# endif
|
|
#endif
|
|
|
|
|
|
@@ -19876,6 +20530,7 @@
|
|
SQLITE_USE_URI, /* bOpenUri */
|
|
SQLITE_ALLOW_COVERING_INDEX_SCAN, /* bUseCis */
|
|
0, /* bSmallMalloc */
|
|
+ 1, /* bExtraSchemaChecks */
|
|
0x7ffffffe, /* mxStrlen */
|
|
0, /* neverCorrupt */
|
|
SQLITE_DEFAULT_LOOKASIDE, /* szLookaside, nLookaside */
|
|
@@ -19919,9 +20574,9 @@
|
|
0, /* xTestCallback */
|
|
#endif
|
|
0, /* bLocaltimeFault */
|
|
- 0, /* bInternalFunctions */
|
|
0x7ffffffe, /* iOnceResetThreshold */
|
|
SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */
|
|
+ 0, /* iPrngSeed */
|
|
};
|
|
|
|
/*
|
|
@@ -19931,14 +20586,6 @@
|
|
*/
|
|
SQLITE_PRIVATE FuncDefHash sqlite3BuiltinFunctions;
|
|
|
|
-/*
|
|
-** Constant tokens for values 0 and 1.
|
|
-*/
|
|
-SQLITE_PRIVATE const Token sqlite3IntTokens[] = {
|
|
- { "0", 1 },
|
|
- { "1", 1 }
|
|
-};
|
|
-
|
|
#ifdef VDBE_PROFILE
|
|
/*
|
|
** The following performance counter can be used in place of
|
|
@@ -20036,7 +20683,8 @@
|
|
** "explain" P4 display logic is enabled.
|
|
*/
|
|
#if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \
|
|
- || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)
|
|
+ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) \
|
|
+ || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
# define VDBE_DISPLAY_P4 1
|
|
#else
|
|
# define VDBE_DISPLAY_P4 0
|
|
@@ -20291,7 +20939,8 @@
|
|
** True if Mem X is a NULL-nochng type.
|
|
*/
|
|
#define MemNullNochng(X) \
|
|
- ((X)->flags==(MEM_Null|MEM_Zero) && (X)->n==0 && (X)->u.nZero==0)
|
|
+ (((X)->flags&MEM_TypeMask)==(MEM_Null|MEM_Zero) \
|
|
+ && (X)->n==0 && (X)->u.nZero==0)
|
|
|
|
/*
|
|
** Return true if a memory cell is not marked as invalid. This macro
|
|
@@ -20422,9 +21071,9 @@
|
|
u8 errorAction; /* Recovery action to do in case of an error */
|
|
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
|
u8 prepFlags; /* SQLITE_PREPARE_* flags */
|
|
+ u8 doingRerun; /* True if rerunning after an auto-reprepare */
|
|
bft expired:2; /* 1: recompile VM immediately 2: when convenient */
|
|
bft explain:2; /* True if EXPLAIN present on SQL command */
|
|
- bft doingRerun:1; /* True if rerunning after an auto-reprepare */
|
|
bft changeCntOn:1; /* True to update the change-counter */
|
|
bft runOnlyOnce:1; /* Automatically expire on reset */
|
|
bft usesStmtJournal:1; /* True if uses a statement journal */
|
|
@@ -20487,11 +21136,11 @@
|
|
SQLITE_PRIVATE void sqlite3VdbeError(Vdbe*, const char *, ...);
|
|
SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *, VdbeCursor*);
|
|
void sqliteVdbePopStack(Vdbe*,int);
|
|
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor*);
|
|
SQLITE_PRIVATE int sqlite3VdbeCursorMoveto(VdbeCursor**, int*);
|
|
SQLITE_PRIVATE int sqlite3VdbeCursorRestore(VdbeCursor*);
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialTypeLen(u32);
|
|
SQLITE_PRIVATE u8 sqlite3VdbeOneByteSerialTypeLen(u8);
|
|
-SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem*, int, u32*);
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialPut(unsigned char*, Mem*, u32);
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialGet(const unsigned char*, u32, Mem*);
|
|
SQLITE_PRIVATE void sqlite3VdbeDeleteAuxData(sqlite3*, AuxData**, int, int);
|
|
@@ -20500,7 +21149,14 @@
|
|
SQLITE_PRIVATE int sqlite3VdbeIdxKeyCompare(sqlite3*,VdbeCursor*,UnpackedRecord*,int*);
|
|
SQLITE_PRIVATE int sqlite3VdbeIdxRowid(sqlite3*, BtCursor*, i64*);
|
|
SQLITE_PRIVATE int sqlite3VdbeExec(Vdbe*);
|
|
-#ifndef SQLITE_OMIT_EXPLAIN
|
|
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
+SQLITE_PRIVATE int sqlite3VdbeNextOpcode(Vdbe*,Mem*,int,int*,int*,Op**);
|
|
+SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3*,Op*);
|
|
+#endif
|
|
+#if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS)
|
|
+SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(sqlite3*,const Op*,const char*);
|
|
+#endif
|
|
+#if !defined(SQLITE_OMIT_EXPLAIN)
|
|
SQLITE_PRIVATE int sqlite3VdbeList(Vdbe*);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VdbeHalt(Vdbe*);
|
|
@@ -20534,14 +21190,15 @@
|
|
SQLITE_PRIVATE void sqlite3VdbeIntegerAffinity(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemRealify(Mem*);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemNumerify(Mem*);
|
|
-SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem*,u8,u8);
|
|
+SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem*,u8,u8);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(BtCursor*,u32,u32,Mem*);
|
|
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(BtCursor*,u32,Mem*);
|
|
SQLITE_PRIVATE void sqlite3VdbeMemRelease(Mem *p);
|
|
SQLITE_PRIVATE int sqlite3VdbeMemFinalize(Mem*, FuncDef*);
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem*, Mem*, FuncDef*);
|
|
#endif
|
|
-#ifndef SQLITE_OMIT_EXPLAIN
|
|
+#if !defined(SQLITE_OMIT_EXPLAIN) || defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
SQLITE_PRIVATE const char *sqlite3OpcodeName(int);
|
|
#endif
|
|
SQLITE_PRIVATE int sqlite3VdbeMemGrow(Mem *pMem, int n, int preserve);
|
|
@@ -20600,7 +21257,7 @@
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE void sqlite3VdbePrintSql(Vdbe*);
|
|
-SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf);
|
|
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr);
|
|
#endif
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
SQLITE_PRIVATE int sqlite3VdbeMemTranslate(Mem*, u8);
|
|
@@ -20792,6 +21449,10 @@
|
|
SQLITE_PRIVATE int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
|
|
u32 nInit = countLookasideSlots(db->lookaside.pInit);
|
|
u32 nFree = countLookasideSlots(db->lookaside.pFree);
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ nInit += countLookasideSlots(db->lookaside.pSmallInit);
|
|
+ nFree += countLookasideSlots(db->lookaside.pSmallFree);
|
|
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
|
|
return db->lookaside.nSlot - (nInit+nFree);
|
|
}
|
|
@@ -20824,6 +21485,15 @@
|
|
db->lookaside.pInit = db->lookaside.pFree;
|
|
db->lookaside.pFree = 0;
|
|
}
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ p = db->lookaside.pSmallFree;
|
|
+ if( p ){
|
|
+ while( p->pNext ) p = p->pNext;
|
|
+ p->pNext = db->lookaside.pSmallInit;
|
|
+ db->lookaside.pSmallInit = db->lookaside.pSmallFree;
|
|
+ db->lookaside.pSmallFree = 0;
|
|
+ }
|
|
+#endif
|
|
}
|
|
break;
|
|
}
|
|
@@ -21608,12 +22278,12 @@
|
|
double rLimit; /* Maximum NNN value for this transform */
|
|
double rXform; /* Constant used for this transform */
|
|
} aXformType[] = {
|
|
- { 0, 6, "second", 464269060800.0, 86400000.0/(24.0*60.0*60.0) },
|
|
- { 0, 6, "minute", 7737817680.0, 86400000.0/(24.0*60.0) },
|
|
- { 0, 4, "hour", 128963628.0, 86400000.0/24.0 },
|
|
- { 0, 3, "day", 5373485.0, 86400000.0 },
|
|
- { 1, 5, "month", 176546.0, 30.0*86400000.0 },
|
|
- { 2, 4, "year", 14713.0, 365.0*86400000.0 },
|
|
+ { 0, 6, "second", 464269060800.0, 1000.0 },
|
|
+ { 0, 6, "minute", 7737817680.0, 60000.0 },
|
|
+ { 0, 4, "hour", 128963628.0, 3600000.0 },
|
|
+ { 0, 3, "day", 5373485.0, 86400000.0 },
|
|
+ { 1, 5, "month", 176546.0, 2592000000.0 },
|
|
+ { 2, 4, "year", 14713.0, 31536000000.0 },
|
|
};
|
|
|
|
/*
|
|
@@ -21675,7 +22345,7 @@
|
|
r = p->s*1000.0 + 210866760000000.0;
|
|
if( r>=0.0 && r<464269060800000.0 ){
|
|
clearYMD_HMS_TZ(p);
|
|
- p->iJD = (sqlite3_int64)r;
|
|
+ p->iJD = (sqlite3_int64)(r + 0.5);
|
|
p->validJD = 1;
|
|
p->rawS = 0;
|
|
rc = 0;
|
|
@@ -22454,7 +23124,7 @@
|
|
** down into the VFS layer. Some SQLITE_OPEN_ flags (for example,
|
|
** SQLITE_OPEN_FULLMUTEX or SQLITE_OPEN_SHAREDCACHE) are blocked before
|
|
** reaching the VFS. */
|
|
- rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x87f7f, pFlagsOut);
|
|
+ rc = pVfs->xOpen(pVfs, zPath, pFile, flags & 0x1087f7f, pFlagsOut);
|
|
assert( rc==SQLITE_OK || pFile->pMethods==0 );
|
|
return rc;
|
|
}
|
|
@@ -22497,7 +23167,15 @@
|
|
}
|
|
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
|
SQLITE_PRIVATE int sqlite3OsRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
|
- return pVfs->xRandomness(pVfs, nByte, zBufOut);
|
|
+ if( sqlite3Config.iPrngSeed ){
|
|
+ memset(zBufOut, 0, nByte);
|
|
+ if( ALWAYS(nByte>(signed)sizeof(unsigned)) ) nByte = sizeof(unsigned int);
|
|
+ memcpy(zBufOut, &sqlite3Config.iPrngSeed, nByte);
|
|
+ return SQLITE_OK;
|
|
+ }else{
|
|
+ return pVfs->xRandomness(pVfs, nByte, zBufOut);
|
|
+ }
|
|
+
|
|
}
|
|
SQLITE_PRIVATE int sqlite3OsSleep(sqlite3_vfs *pVfs, int nMicro){
|
|
return pVfs->xSleep(pVfs, nMicro);
|
|
@@ -25165,6 +25843,7 @@
|
|
GLOBAL(int, mutexIsInit) = 1;
|
|
#endif
|
|
|
|
+ sqlite3MemoryBarrier();
|
|
return rc;
|
|
}
|
|
|
|
@@ -25964,7 +26643,7 @@
|
|
******************************************************************************
|
|
**
|
|
** This file contains inline asm code for retrieving "high-performance"
|
|
-** counters for x86 class CPUs.
|
|
+** counters for x86 and x86_64 class CPUs.
|
|
*/
|
|
#ifndef SQLITE_HWTIME_H
|
|
#define SQLITE_HWTIME_H
|
|
@@ -25975,8 +26654,9 @@
|
|
** processor and returns that value. This can be used for high-res
|
|
** profiling.
|
|
*/
|
|
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
+#if !defined(__STRICT_ANSI__) && \
|
|
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
@@ -25997,7 +26677,7 @@
|
|
|
|
#endif
|
|
|
|
-#elif (defined(__GNUC__) && defined(__x86_64__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long val;
|
|
@@ -26005,7 +26685,7 @@
|
|
return val;
|
|
}
|
|
|
|
-#elif (defined(__GNUC__) && defined(__ppc__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long long retval;
|
|
@@ -26022,14 +26702,13 @@
|
|
|
|
#else
|
|
|
|
- #error Need implementation of sqlite3Hwtime() for your platform.
|
|
-
|
|
/*
|
|
- ** To compile without implementing sqlite3Hwtime() for your platform,
|
|
- ** you can remove the above #error and use the following
|
|
- ** stub function. You will lose timing support for many
|
|
- ** of the debugging and testing utilities, but it should at
|
|
- ** least compile and run.
|
|
+ ** asm() is needed for hardware timing support. Without asm(),
|
|
+ ** disable the sqlite3Hwtime() routine.
|
|
+ **
|
|
+ ** sqlite3Hwtime() is only used for some obscure debugging
|
|
+ ** and analysis configurations, not in any deliverable, so this
|
|
+ ** should not be a great loss.
|
|
*/
|
|
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
|
|
|
|
@@ -26613,19 +27292,27 @@
|
|
#endif
|
|
}
|
|
|
|
+/*
|
|
+** Default value of the hard heap limit. 0 means "no limit".
|
|
+*/
|
|
+#ifndef SQLITE_MAX_MEMORY
|
|
+# define SQLITE_MAX_MEMORY 0
|
|
+#endif
|
|
+
|
|
/*
|
|
** State information local to the memory allocation subsystem.
|
|
*/
|
|
static SQLITE_WSD struct Mem0Global {
|
|
sqlite3_mutex *mutex; /* Mutex to serialize access */
|
|
sqlite3_int64 alarmThreshold; /* The soft heap limit */
|
|
+ sqlite3_int64 hardLimit; /* The hard upper bound on memory */
|
|
|
|
/*
|
|
** True if heap is nearly "full" where "full" is defined by the
|
|
** sqlite3_soft_heap_limit() setting.
|
|
*/
|
|
int nearlyFull;
|
|
-} mem0 = { 0, 0, 0 };
|
|
+} mem0 = { 0, SQLITE_MAX_MEMORY, SQLITE_MAX_MEMORY, 0 };
|
|
|
|
#define mem0 GLOBAL(struct Mem0Global, mem0)
|
|
|
|
@@ -26655,8 +27342,15 @@
|
|
#endif
|
|
|
|
/*
|
|
-** Set the soft heap-size limit for the library. Passing a zero or
|
|
-** negative value indicates no limit.
|
|
+** Set the soft heap-size limit for the library. An argument of
|
|
+** zero disables the limit. A negative argument is a no-op used to
|
|
+** obtain the return value.
|
|
+**
|
|
+** The return value is the value of the heap limit just before this
|
|
+** interface was called.
|
|
+**
|
|
+** If the hard heap limit is enabled, then the soft heap limit cannot
|
|
+** be disabled nor raised above the hard heap limit.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
|
|
sqlite3_int64 priorLimit;
|
|
@@ -26672,9 +27366,12 @@
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
return priorLimit;
|
|
}
|
|
+ if( mem0.hardLimit>0 && (n>mem0.hardLimit || n==0) ){
|
|
+ n = mem0.hardLimit;
|
|
+ }
|
|
mem0.alarmThreshold = n;
|
|
nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
|
- mem0.nearlyFull = (n>0 && n<=nUsed);
|
|
+ AtomicStore(&mem0.nearlyFull, n>0 && n<=nUsed);
|
|
sqlite3_mutex_leave(mem0.mutex);
|
|
excess = sqlite3_memory_used() - n;
|
|
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
|
|
@@ -26685,6 +27382,37 @@
|
|
sqlite3_soft_heap_limit64(n);
|
|
}
|
|
|
|
+/*
|
|
+** Set the hard heap-size limit for the library. An argument of zero
|
|
+** disables the hard heap limit. A negative argument is a no-op used
|
|
+** to obtain the return value without affecting the hard heap limit.
|
|
+**
|
|
+** The return value is the value of the hard heap limit just prior to
|
|
+** calling this interface.
|
|
+**
|
|
+** Setting the hard heap limit will also activate the soft heap limit
|
|
+** and constrain the soft heap limit to be no more than the hard heap
|
|
+** limit.
|
|
+*/
|
|
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 n){
|
|
+ sqlite3_int64 priorLimit;
|
|
+#ifndef SQLITE_OMIT_AUTOINIT
|
|
+ int rc = sqlite3_initialize();
|
|
+ if( rc ) return -1;
|
|
+#endif
|
|
+ sqlite3_mutex_enter(mem0.mutex);
|
|
+ priorLimit = mem0.hardLimit;
|
|
+ if( n>=0 ){
|
|
+ mem0.hardLimit = n;
|
|
+ if( n<mem0.alarmThreshold || mem0.alarmThreshold==0 ){
|
|
+ mem0.alarmThreshold = n;
|
|
+ }
|
|
+ }
|
|
+ sqlite3_mutex_leave(mem0.mutex);
|
|
+ return priorLimit;
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
** Initialize the memory allocation subsystem.
|
|
*/
|
|
@@ -26711,7 +27439,7 @@
|
|
** sqlite3_soft_heap_limit().
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3HeapNearlyFull(void){
|
|
- return mem0.nearlyFull;
|
|
+ return AtomicLoad(&mem0.nearlyFull);
|
|
}
|
|
|
|
/*
|
|
@@ -26771,21 +27499,21 @@
|
|
** following xRoundup() call. */
|
|
nFull = sqlite3GlobalConfig.m.xRoundup(n);
|
|
|
|
-#ifdef SQLITE_MAX_MEMORY
|
|
- if( sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED)+nFull>SQLITE_MAX_MEMORY ){
|
|
- *pp = 0;
|
|
- return;
|
|
- }
|
|
-#endif
|
|
-
|
|
sqlite3StatusHighwater(SQLITE_STATUS_MALLOC_SIZE, n);
|
|
if( mem0.alarmThreshold>0 ){
|
|
sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
|
if( nUsed >= mem0.alarmThreshold - nFull ){
|
|
- mem0.nearlyFull = 1;
|
|
+ AtomicStore(&mem0.nearlyFull, 1);
|
|
sqlite3MallocAlarm(nFull);
|
|
+ if( mem0.hardLimit ){
|
|
+ nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
|
|
+ if( nUsed >= mem0.hardLimit - nFull ){
|
|
+ *pp = 0;
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
}else{
|
|
- mem0.nearlyFull = 0;
|
|
+ AtomicStore(&mem0.nearlyFull, 0);
|
|
}
|
|
}
|
|
p = sqlite3GlobalConfig.m.xMalloc(nFull);
|
|
@@ -26864,10 +27592,17 @@
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
return sqlite3GlobalConfig.m.xSize(p);
|
|
}
|
|
+static int lookasideMallocSize(sqlite3 *db, void *p){
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ return p<db->lookaside.pMiddle ? db->lookaside.szTrue : LOOKASIDE_SMALL;
|
|
+#else
|
|
+ return db->lookaside.szTrue;
|
|
+#endif
|
|
+}
|
|
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
|
|
assert( p!=0 );
|
|
- if( db==0 || !isLookaside(db,p) ){
|
|
#ifdef SQLITE_DEBUG
|
|
+ if( db==0 || !isLookaside(db,p) ){
|
|
if( db==0 ){
|
|
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
|
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
|
|
@@ -26875,12 +27610,23 @@
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
}
|
|
+ }
|
|
#endif
|
|
- return sqlite3GlobalConfig.m.xSize(p);
|
|
- }else{
|
|
- assert( sqlite3_mutex_held(db->mutex) );
|
|
- return db->lookaside.sz;
|
|
+ if( db ){
|
|
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
|
+ assert( sqlite3_mutex_held(db->mutex) );
|
|
+ return LOOKASIDE_SMALL;
|
|
+ }
|
|
+#endif
|
|
+ if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
|
+ assert( sqlite3_mutex_held(db->mutex) );
|
|
+ return db->lookaside.szTrue;
|
|
+ }
|
|
+ }
|
|
}
|
|
+ return sqlite3GlobalConfig.m.xSize(p);
|
|
}
|
|
SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
|
|
assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
|
|
@@ -26927,15 +27673,27 @@
|
|
measureAllocationSize(db, p);
|
|
return;
|
|
}
|
|
- if( isLookaside(db, p) ){
|
|
- LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
+ if( ((uptr)p)<(uptr)(db->lookaside.pEnd) ){
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ if( ((uptr)p)>=(uptr)(db->lookaside.pMiddle) ){
|
|
+ LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
#ifdef SQLITE_DEBUG
|
|
- /* Trash all content in the buffer being freed */
|
|
- memset(p, 0xaa, db->lookaside.sz);
|
|
+ memset(p, 0xaa, LOOKASIDE_SMALL); /* Trash freed content */
|
|
#endif
|
|
- pBuf->pNext = db->lookaside.pFree;
|
|
- db->lookaside.pFree = pBuf;
|
|
- return;
|
|
+ pBuf->pNext = db->lookaside.pSmallFree;
|
|
+ db->lookaside.pSmallFree = pBuf;
|
|
+ return;
|
|
+ }
|
|
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
+ if( ((uptr)p)>=(uptr)(db->lookaside.pStart) ){
|
|
+ LookasideSlot *pBuf = (LookasideSlot*)p;
|
|
+#ifdef SQLITE_DEBUG
|
|
+ memset(p, 0xaa, db->lookaside.szTrue); /* Trash freed content */
|
|
+#endif
|
|
+ pBuf->pNext = db->lookaside.pFree;
|
|
+ db->lookaside.pFree = pBuf;
|
|
+ return;
|
|
+ }
|
|
}
|
|
}
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
@@ -26984,10 +27742,12 @@
|
|
sqlite3MallocAlarm(nDiff);
|
|
}
|
|
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
|
+#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
if( pNew==0 && mem0.alarmThreshold>0 ){
|
|
sqlite3MallocAlarm((int)nBytes);
|
|
pNew = sqlite3GlobalConfig.m.xRealloc(pOld, nNew);
|
|
}
|
|
+#endif
|
|
if( pNew ){
|
|
nNew = sqlite3MallocSize(pNew);
|
|
sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
|
|
@@ -27091,23 +27851,37 @@
|
|
assert( db!=0 );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
assert( db->pnBytesFreed==0 );
|
|
- if( db->lookaside.bDisable==0 ){
|
|
- assert( db->mallocFailed==0 );
|
|
- if( n>db->lookaside.sz ){
|
|
- db->lookaside.anStat[1]++;
|
|
- }else if( (pBuf = db->lookaside.pFree)!=0 ){
|
|
- db->lookaside.pFree = pBuf->pNext;
|
|
+ if( n>db->lookaside.sz ){
|
|
+ if( !db->lookaside.bDisable ){
|
|
+ db->lookaside.anStat[1]++;
|
|
+ }else if( db->mallocFailed ){
|
|
+ return 0;
|
|
+ }
|
|
+ return dbMallocRawFinish(db, n);
|
|
+ }
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ if( n<=LOOKASIDE_SMALL ){
|
|
+ if( (pBuf = db->lookaside.pSmallFree)!=0 ){
|
|
+ db->lookaside.pSmallFree = pBuf->pNext;
|
|
db->lookaside.anStat[0]++;
|
|
return (void*)pBuf;
|
|
- }else if( (pBuf = db->lookaside.pInit)!=0 ){
|
|
- db->lookaside.pInit = pBuf->pNext;
|
|
+ }else if( (pBuf = db->lookaside.pSmallInit)!=0 ){
|
|
+ db->lookaside.pSmallInit = pBuf->pNext;
|
|
db->lookaside.anStat[0]++;
|
|
return (void*)pBuf;
|
|
- }else{
|
|
- db->lookaside.anStat[2]++;
|
|
}
|
|
- }else if( db->mallocFailed ){
|
|
- return 0;
|
|
+ }
|
|
+#endif
|
|
+ if( (pBuf = db->lookaside.pFree)!=0 ){
|
|
+ db->lookaside.pFree = pBuf->pNext;
|
|
+ db->lookaside.anStat[0]++;
|
|
+ return (void*)pBuf;
|
|
+ }else if( (pBuf = db->lookaside.pInit)!=0 ){
|
|
+ db->lookaside.pInit = pBuf->pNext;
|
|
+ db->lookaside.anStat[0]++;
|
|
+ return (void*)pBuf;
|
|
+ }else{
|
|
+ db->lookaside.anStat[2]++;
|
|
}
|
|
#else
|
|
assert( db!=0 );
|
|
@@ -27131,7 +27905,16 @@
|
|
assert( db!=0 );
|
|
if( p==0 ) return sqlite3DbMallocRawNN(db, n);
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
- if( isLookaside(db,p) && n<=db->lookaside.sz ) return p;
|
|
+ if( ((uptr)p)<(uptr)db->lookaside.pEnd ){
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ if( ((uptr)p)>=(uptr)db->lookaside.pMiddle ){
|
|
+ if( n<=LOOKASIDE_SMALL ) return p;
|
|
+ }else
|
|
+#endif
|
|
+ if( ((uptr)p)>=(uptr)db->lookaside.pStart ){
|
|
+ if( n<=db->lookaside.szTrue ) return p;
|
|
+ }
|
|
+ }
|
|
return dbReallocFinish(db, p, n);
|
|
}
|
|
static SQLITE_NOINLINE void *dbReallocFinish(sqlite3 *db, void *p, u64 n){
|
|
@@ -27142,14 +27925,14 @@
|
|
if( isLookaside(db, p) ){
|
|
pNew = sqlite3DbMallocRawNN(db, n);
|
|
if( pNew ){
|
|
- memcpy(pNew, p, db->lookaside.sz);
|
|
+ memcpy(pNew, p, lookasideMallocSize(db, p));
|
|
sqlite3DbFree(db, p);
|
|
}
|
|
}else{
|
|
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
|
|
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
|
|
- pNew = sqlite3_realloc64(p, n);
|
|
+ pNew = sqlite3Realloc(p, n);
|
|
if( !pNew ){
|
|
sqlite3OomFault(db);
|
|
}
|
|
@@ -27239,9 +28022,9 @@
|
|
if( db->mallocFailed==0 && db->bBenignMalloc==0 ){
|
|
db->mallocFailed = 1;
|
|
if( db->nVdbeExec>0 ){
|
|
- db->u1.isInterrupted = 1;
|
|
+ AtomicStore(&db->u1.isInterrupted, 1);
|
|
}
|
|
- db->lookaside.bDisable++;
|
|
+ DisableLookaside;
|
|
if( db->pParse ){
|
|
db->pParse->rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
@@ -27258,9 +28041,9 @@
|
|
SQLITE_PRIVATE void sqlite3OomClear(sqlite3 *db){
|
|
if( db->mallocFailed && db->nVdbeExec==0 ){
|
|
db->mallocFailed = 0;
|
|
- db->u1.isInterrupted = 0;
|
|
+ AtomicStore(&db->u1.isInterrupted, 0);
|
|
assert( db->lookaside.bDisable>0 );
|
|
- db->lookaside.bDisable--;
|
|
+ EnableLookaside;
|
|
}
|
|
}
|
|
|
|
@@ -27496,6 +28279,13 @@
|
|
#endif
|
|
#define etBUFSIZE SQLITE_PRINT_BUF_SIZE /* Size of the output buffer */
|
|
|
|
+/*
|
|
+** Hard limit on the precision of floating-point conversions.
|
|
+*/
|
|
+#ifndef SQLITE_PRINTF_PRECISION_LIMIT
|
|
+# define SQLITE_FP_PRECISION_LIMIT 100000000
|
|
+#endif
|
|
+
|
|
/*
|
|
** Render a string given by "fmt" into the StrAccum object.
|
|
*/
|
|
@@ -27696,6 +28486,8 @@
|
|
** xtype The class of the conversion.
|
|
** infop Pointer to the appropriate info struct.
|
|
*/
|
|
+ assert( width>=0 );
|
|
+ assert( precision>=(-1) );
|
|
switch( xtype ){
|
|
case etPOINTER:
|
|
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
|
|
@@ -27817,6 +28609,11 @@
|
|
length = 0;
|
|
#else
|
|
if( precision<0 ) precision = 6; /* Set default precision */
|
|
+#ifdef SQLITE_FP_PRECISION_LIMIT
|
|
+ if( precision>SQLITE_FP_PRECISION_LIMIT ){
|
|
+ precision = SQLITE_FP_PRECISION_LIMIT;
|
|
+ }
|
|
+#endif
|
|
if( realvalue<0.0 ){
|
|
realvalue = -realvalue;
|
|
prefix = '-';
|
|
@@ -28099,7 +28896,7 @@
|
|
}
|
|
isnull = escarg==0;
|
|
if( isnull ) escarg = (xtype==etSQLESCAPE2 ? "NULL" : "(NULL)");
|
|
- /* For %q, %Q, and %w, the precision is the number of byte (or
|
|
+ /* For %q, %Q, and %w, the precision is the number of bytes (or
|
|
** characters if the ! flags is present) to use from the input.
|
|
** Because of the extra quoting characters inserted, the number
|
|
** of output characters may be larger than the precision.
|
|
@@ -28226,7 +29023,7 @@
|
|
if( p->db ){
|
|
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
|
|
}else{
|
|
- zNew = sqlite3_realloc64(zOld, p->nAlloc);
|
|
+ zNew = sqlite3Realloc(zOld, p->nAlloc);
|
|
}
|
|
if( zNew ){
|
|
assert( p->zText!=0 || p->nChar==0 );
|
|
@@ -28568,7 +29365,7 @@
|
|
SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
|
|
va_list ap;
|
|
StrAccum acc;
|
|
- char zBuf[500];
|
|
+ char zBuf[SQLITE_PRINT_BUF_SIZE*10];
|
|
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
va_start(ap,zFormat);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
@@ -28668,7 +29465,7 @@
|
|
va_start(ap, zFormat);
|
|
sqlite3_str_vappendf(&acc, zFormat, ap);
|
|
va_end(ap);
|
|
- assert( acc.nChar>0 );
|
|
+ assert( acc.nChar>0 || acc.accError );
|
|
sqlite3_str_append(&acc, "\n", 1);
|
|
}
|
|
sqlite3StrAccumFinish(&acc);
|
|
@@ -28708,7 +29505,7 @@
|
|
char cSep = '(';
|
|
int j;
|
|
for(j=0; j<pCte->pCols->nExpr; j++){
|
|
- sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
|
|
+ sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zEName);
|
|
cSep = ',';
|
|
}
|
|
sqlite3_str_appendf(&x, ")");
|
|
@@ -28733,15 +29530,15 @@
|
|
StrAccum x;
|
|
char zLine[100];
|
|
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
|
- sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
|
|
+ sqlite3_str_appendf(&x, "{%d:*}", pItem->iCursor);
|
|
if( pItem->zDatabase ){
|
|
sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
|
|
}else if( pItem->zName ){
|
|
sqlite3_str_appendf(&x, " %s", pItem->zName);
|
|
}
|
|
if( pItem->pTab ){
|
|
- sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p",
|
|
- pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab);
|
|
+ sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
|
|
+ pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
|
|
}
|
|
if( pItem->zAlias ){
|
|
sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
|
|
@@ -28749,6 +29546,9 @@
|
|
if( pItem->fg.jointype & JT_LEFT ){
|
|
sqlite3_str_appendf(&x, " LEFT-JOIN");
|
|
}
|
|
+ if( pItem->fg.fromDDL ){
|
|
+ sqlite3_str_appendf(&x, " DDL");
|
|
+ }
|
|
sqlite3StrAccumFinish(&x);
|
|
sqlite3TreeViewItem(pView, zLine, i<pSrc->nSrc-1);
|
|
if( pItem->pSelect ){
|
|
@@ -28778,13 +29578,17 @@
|
|
sqlite3TreeViewPush(pView, 1);
|
|
}
|
|
do{
|
|
- sqlite3TreeViewLine(pView,
|
|
- "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
|
|
- ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
|
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
|
|
- p->selId, p, p->selFlags,
|
|
- (int)p->nSelectRow
|
|
- );
|
|
+ if( p->selFlags & SF_WhereBegin ){
|
|
+ sqlite3TreeViewLine(pView, "sqlite3WhereBegin()");
|
|
+ }else{
|
|
+ sqlite3TreeViewLine(pView,
|
|
+ "SELECT%s%s (%u/%p) selFlags=0x%x nSelectRow=%d",
|
|
+ ((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
|
|
+ ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""),
|
|
+ p->selId, p, p->selFlags,
|
|
+ (int)p->nSelectRow
|
|
+ );
|
|
+ }
|
|
if( cnt++ ) sqlite3TreeViewPop(pView);
|
|
if( p->pPrior ){
|
|
n = 1000;
|
|
@@ -28801,7 +29605,10 @@
|
|
if( p->pWinDefn ) n++;
|
|
#endif
|
|
}
|
|
- sqlite3TreeViewExprList(pView, p->pEList, (n--)>0, "result-set");
|
|
+ if( p->pEList ){
|
|
+ sqlite3TreeViewExprList(pView, p->pEList, n>0, "result-set");
|
|
+ }
|
|
+ n--;
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
if( p->pWin ){
|
|
Window *pX;
|
|
@@ -28990,20 +29797,28 @@
|
|
SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
|
const char *zBinOp = 0; /* Binary operator */
|
|
const char *zUniOp = 0; /* Unary operator */
|
|
- char zFlgs[60];
|
|
+ char zFlgs[200];
|
|
pView = sqlite3TreeViewPush(pView, moreToFollow);
|
|
if( pExpr==0 ){
|
|
sqlite3TreeViewLine(pView, "nil");
|
|
sqlite3TreeViewPop(pView);
|
|
return;
|
|
}
|
|
- if( pExpr->flags ){
|
|
+ if( pExpr->flags || pExpr->affExpr || pExpr->vvaFlags ){
|
|
+ StrAccum x;
|
|
+ sqlite3StrAccumInit(&x, 0, zFlgs, sizeof(zFlgs), 0);
|
|
+ sqlite3_str_appendf(&x, " fg.af=%x.%c",
|
|
+ pExpr->flags, pExpr->affExpr ? pExpr->affExpr : 'n');
|
|
if( ExprHasProperty(pExpr, EP_FromJoin) ){
|
|
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x iRJT=%d",
|
|
- pExpr->flags, pExpr->iRightJoinTable);
|
|
- }else{
|
|
- sqlite3_snprintf(sizeof(zFlgs),zFlgs," flags=0x%x",pExpr->flags);
|
|
+ sqlite3_str_appendf(&x, " iRJT=%d", pExpr->iRightJoinTable);
|
|
+ }
|
|
+ if( ExprHasProperty(pExpr, EP_FromDDL) ){
|
|
+ sqlite3_str_appendf(&x, " DDL");
|
|
}
|
|
+ if( ExprHasVVAProperty(pExpr, EP_Immutable) ){
|
|
+ sqlite3_str_appendf(&x, " IMMUTABLE");
|
|
+ }
|
|
+ sqlite3StrAccumFinish(&x);
|
|
}else{
|
|
zFlgs[0] = 0;
|
|
}
|
|
@@ -29016,10 +29831,18 @@
|
|
case TK_COLUMN: {
|
|
if( pExpr->iTable<0 ){
|
|
/* This only happens when coding check constraints */
|
|
- sqlite3TreeViewLine(pView, "COLUMN(%d)%s", pExpr->iColumn, zFlgs);
|
|
+ char zOp2[16];
|
|
+ if( pExpr->op2 ){
|
|
+ sqlite3_snprintf(sizeof(zOp2),zOp2," op2=0x%02x",pExpr->op2);
|
|
+ }else{
|
|
+ zOp2[0] = 0;
|
|
+ }
|
|
+ sqlite3TreeViewLine(pView, "COLUMN(%d)%s%s",
|
|
+ pExpr->iColumn, zFlgs, zOp2);
|
|
}else{
|
|
- sqlite3TreeViewLine(pView, "{%d:%d}%s",
|
|
- pExpr->iTable, pExpr->iColumn, zFlgs);
|
|
+ sqlite3TreeViewLine(pView, "{%d:%d} pTab=%p%s",
|
|
+ pExpr->iTable, pExpr->iColumn,
|
|
+ pExpr->y.pTab, zFlgs);
|
|
}
|
|
if( ExprHasProperty(pExpr, EP_FixedCol) ){
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
@@ -29101,6 +29924,7 @@
|
|
case TK_RSHIFT: zBinOp = "RSHIFT"; break;
|
|
case TK_CONCAT: zBinOp = "CONCAT"; break;
|
|
case TK_DOT: zBinOp = "DOT"; break;
|
|
+ case TK_LIMIT: zBinOp = "LIMIT"; break;
|
|
|
|
case TK_UMINUS: zUniOp = "UMINUS"; break;
|
|
case TK_UPLUS: zUniOp = "UPLUS"; break;
|
|
@@ -29129,7 +29953,14 @@
|
|
}
|
|
|
|
case TK_COLLATE: {
|
|
- sqlite3TreeViewLine(pView, "COLLATE %Q", pExpr->u.zToken);
|
|
+ /* COLLATE operators without the EP_Collate flag are intended to
|
|
+ ** emulate collation associated with a table column. These show
|
|
+ ** up in the treeview output as "SOFT-COLLATE". Explicit COLLATE
|
|
+ ** operators that appear in the original SQL always have the
|
|
+ ** EP_Collate bit set and appear in treeview output as just "COLLATE" */
|
|
+ sqlite3TreeViewLine(pView, "%sCOLLATE %Q%s",
|
|
+ !ExprHasProperty(pExpr, EP_Collate) ? "SOFT-" : "",
|
|
+ pExpr->u.zToken, zFlgs);
|
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
break;
|
|
}
|
|
@@ -29144,16 +29975,28 @@
|
|
}else{
|
|
pFarg = pExpr->x.pList;
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- pWin = pExpr->y.pWin;
|
|
+ pWin = ExprHasProperty(pExpr, EP_WinFunc) ? pExpr->y.pWin : 0;
|
|
#else
|
|
pWin = 0;
|
|
#endif
|
|
}
|
|
if( pExpr->op==TK_AGG_FUNCTION ){
|
|
- sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q",
|
|
- pExpr->op2, pExpr->u.zToken);
|
|
+ sqlite3TreeViewLine(pView, "AGG_FUNCTION%d %Q%s iAgg=%d agg=%p",
|
|
+ pExpr->op2, pExpr->u.zToken, zFlgs,
|
|
+ pExpr->iAgg, pExpr->pAggInfo);
|
|
+ }else if( pExpr->op2!=0 ){
|
|
+ const char *zOp2;
|
|
+ char zBuf[8];
|
|
+ sqlite3_snprintf(sizeof(zBuf),zBuf,"0x%02x",pExpr->op2);
|
|
+ zOp2 = zBuf;
|
|
+ if( pExpr->op2==NC_IsCheck ) zOp2 = "NC_IsCheck";
|
|
+ if( pExpr->op2==NC_IdxExpr ) zOp2 = "NC_IdxExpr";
|
|
+ if( pExpr->op2==NC_PartIdx ) zOp2 = "NC_PartIdx";
|
|
+ if( pExpr->op2==NC_GenCol ) zOp2 = "NC_GenCol";
|
|
+ sqlite3TreeViewLine(pView, "FUNCTION %Q%s op2=%s",
|
|
+ pExpr->u.zToken, zFlgs, zOp2);
|
|
}else{
|
|
- sqlite3TreeViewLine(pView, "FUNCTION %Q", pExpr->u.zToken);
|
|
+ sqlite3TreeViewLine(pView, "FUNCTION %Q%s", pExpr->u.zToken, zFlgs);
|
|
}
|
|
if( pFarg ){
|
|
sqlite3TreeViewExprList(pView, pFarg, pWin!=0, 0);
|
|
@@ -29230,7 +30073,7 @@
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
case TK_RAISE: {
|
|
const char *zType = "unk";
|
|
- switch( pExpr->affinity ){
|
|
+ switch( pExpr->affExpr ){
|
|
case OE_Rollback: zType = "rollback"; break;
|
|
case OE_Abort: zType = "abort"; break;
|
|
case OE_Fail: zType = "fail"; break;
|
|
@@ -29247,7 +30090,9 @@
|
|
break;
|
|
}
|
|
case TK_VECTOR: {
|
|
- sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
|
|
+ char *z = sqlite3_mprintf("VECTOR%s",zFlgs);
|
|
+ sqlite3TreeViewBareExprList(pView, pExpr->x.pList, z);
|
|
+ sqlite3_free(z);
|
|
break;
|
|
}
|
|
case TK_SELECT_COLUMN: {
|
|
@@ -29271,7 +30116,7 @@
|
|
sqlite3TreeViewExpr(pView, pExpr->pRight, 0);
|
|
}else if( zUniOp ){
|
|
sqlite3TreeViewLine(pView, "%s%s", zUniOp, zFlgs);
|
|
- sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
+ sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
|
}
|
|
sqlite3TreeViewPop(pView);
|
|
}
|
|
@@ -29293,8 +30138,9 @@
|
|
sqlite3TreeViewLine(pView, "%s", zLabel);
|
|
for(i=0; i<pList->nExpr; i++){
|
|
int j = pList->a[i].u.x.iOrderByCol;
|
|
- char *zName = pList->a[i].zName;
|
|
+ char *zName = pList->a[i].zEName;
|
|
int moreToFollow = i<pList->nExpr - 1;
|
|
+ if( pList->a[i].eEName!=ENAME_NAME ) zName = 0;
|
|
if( j || zName ){
|
|
sqlite3TreeViewPush(pView, moreToFollow);
|
|
moreToFollow = 0;
|
|
@@ -29851,26 +30697,6 @@
|
|
} \
|
|
}
|
|
|
|
-#define READ_UTF16LE(zIn, TERM, c){ \
|
|
- c = (*zIn++); \
|
|
- c += ((*zIn++)<<8); \
|
|
- if( c>=0xD800 && c<0xE000 && TERM ){ \
|
|
- int c2 = (*zIn++); \
|
|
- c2 += ((*zIn++)<<8); \
|
|
- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
|
|
- } \
|
|
-}
|
|
-
|
|
-#define READ_UTF16BE(zIn, TERM, c){ \
|
|
- c = ((*zIn++)<<8); \
|
|
- c += (*zIn++); \
|
|
- if( c>=0xD800 && c<0xE000 && TERM ){ \
|
|
- int c2 = ((*zIn++)<<8); \
|
|
- c2 += (*zIn++); \
|
|
- c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10); \
|
|
- } \
|
|
-}
|
|
-
|
|
/*
|
|
** Translate a single UTF-8 character. Return the unicode value.
|
|
**
|
|
@@ -29961,9 +30787,11 @@
|
|
|
|
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
|
|
{
|
|
- char zBuf[100];
|
|
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
|
|
- fprintf(stderr, "INPUT: %s\n", zBuf);
|
|
+ StrAccum acc;
|
|
+ char zBuf[1000];
|
|
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
+ sqlite3VdbeMemPrettyPrint(pMem, &acc);
|
|
+ fprintf(stderr, "INPUT: %s\n", sqlite3StrAccumFinish(&acc));
|
|
}
|
|
#endif
|
|
|
|
@@ -30045,13 +30873,59 @@
|
|
if( pMem->enc==SQLITE_UTF16LE ){
|
|
/* UTF-16 Little-endian -> UTF-8 */
|
|
while( zIn<zTerm ){
|
|
- READ_UTF16LE(zIn, zIn<zTerm, c);
|
|
+ c = *(zIn++);
|
|
+ c += (*(zIn++))<<8;
|
|
+ if( c>=0xd800 && c<0xe000 ){
|
|
+#ifdef SQLITE_REPLACE_INVALID_UTF
|
|
+ if( c>=0xdc00 || zIn>=zTerm ){
|
|
+ c = 0xfffd;
|
|
+ }else{
|
|
+ int c2 = *(zIn++);
|
|
+ c2 += (*(zIn++))<<8;
|
|
+ if( c2<0xdc00 || c2>=0xe000 ){
|
|
+ zIn -= 2;
|
|
+ c = 0xfffd;
|
|
+ }else{
|
|
+ c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
+ if( zIn<zTerm ){
|
|
+ int c2 = (*zIn++);
|
|
+ c2 += ((*zIn++)<<8);
|
|
+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
WRITE_UTF8(z, c);
|
|
}
|
|
}else{
|
|
/* UTF-16 Big-endian -> UTF-8 */
|
|
while( zIn<zTerm ){
|
|
- READ_UTF16BE(zIn, zIn<zTerm, c);
|
|
+ c = (*(zIn++))<<8;
|
|
+ c += *(zIn++);
|
|
+ if( c>=0xd800 && c<0xe000 ){
|
|
+#ifdef SQLITE_REPLACE_INVALID_UTF
|
|
+ if( c>=0xdc00 || zIn>=zTerm ){
|
|
+ c = 0xfffd;
|
|
+ }else{
|
|
+ int c2 = (*(zIn++))<<8;
|
|
+ c2 += *(zIn++);
|
|
+ if( c2<0xdc00 || c2>=0xe000 ){
|
|
+ zIn -= 2;
|
|
+ c = 0xfffd;
|
|
+ }else{
|
|
+ c = ((c&0x3ff)<<10) + (c2&0x3ff) + 0x10000;
|
|
+ }
|
|
+ }
|
|
+#else
|
|
+ if( zIn<zTerm ){
|
|
+ int c2 = ((*zIn++)<<8);
|
|
+ c2 += (*zIn++);
|
|
+ c = (c2&0x03FF) + ((c&0x003F)<<10) + (((c&0x03C0)+0x0040)<<10);
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
WRITE_UTF8(z, c);
|
|
}
|
|
}
|
|
@@ -30071,9 +30945,11 @@
|
|
translate_out:
|
|
#if defined(TRANSLATE_TRACE) && defined(SQLITE_DEBUG)
|
|
{
|
|
- char zBuf[100];
|
|
- sqlite3VdbeMemPrettyPrint(pMem, zBuf);
|
|
- fprintf(stderr, "OUTPUT: %s\n", zBuf);
|
|
+ StrAccum acc;
|
|
+ char zBuf[1000];
|
|
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
+ sqlite3VdbeMemPrettyPrint(pMem, &acc);
|
|
+ fprintf(stderr, "OUTPUT: %s\n", sqlite3StrAccumFinish(&acc));
|
|
}
|
|
#endif
|
|
return SQLITE_OK;
|
|
@@ -30208,18 +31084,15 @@
|
|
unsigned char const *z = zIn;
|
|
int n = 0;
|
|
|
|
- if( SQLITE_UTF16NATIVE==SQLITE_UTF16BE ){
|
|
- while( n<nChar ){
|
|
- READ_UTF16BE(z, 1, c);
|
|
- n++;
|
|
- }
|
|
- }else{
|
|
- while( n<nChar ){
|
|
- READ_UTF16LE(z, 1, c);
|
|
- n++;
|
|
- }
|
|
+ if( SQLITE_UTF16NATIVE==SQLITE_UTF16LE ) z++;
|
|
+ while( n<nChar ){
|
|
+ c = z[0];
|
|
+ z += 2;
|
|
+ if( c>=0xd8 && c<0xdc && z[0]>=0xdc && z[0]<0xe0 ) z += 2;
|
|
+ n++;
|
|
}
|
|
- return (int)(z-(unsigned char const *)zIn);
|
|
+ return (int)(z-(unsigned char const *)zIn)
|
|
+ - (SQLITE_UTF16NATIVE==SQLITE_UTF16LE);
|
|
}
|
|
|
|
#if defined(SQLITE_TEST)
|
|
@@ -30249,30 +31122,6 @@
|
|
assert( c==t );
|
|
assert( (z-zBuf)==n );
|
|
}
|
|
- for(i=0; i<0x00110000; i++){
|
|
- if( i>=0xD800 && i<0xE000 ) continue;
|
|
- z = zBuf;
|
|
- WRITE_UTF16LE(z, i);
|
|
- n = (int)(z-zBuf);
|
|
- assert( n>0 && n<=4 );
|
|
- z[0] = 0;
|
|
- z = zBuf;
|
|
- READ_UTF16LE(z, 1, c);
|
|
- assert( c==i );
|
|
- assert( (z-zBuf)==n );
|
|
- }
|
|
- for(i=0; i<0x00110000; i++){
|
|
- if( i>=0xD800 && i<0xE000 ) continue;
|
|
- z = zBuf;
|
|
- WRITE_UTF16BE(z, i);
|
|
- n = (int)(z-zBuf);
|
|
- assert( n>0 && n<=4 );
|
|
- z[0] = 0;
|
|
- z = zBuf;
|
|
- READ_UTF16BE(z, 1, c);
|
|
- assert( c==i );
|
|
- assert( (z-zBuf)==n );
|
|
- }
|
|
}
|
|
#endif /* SQLITE_TEST */
|
|
#endif /* SQLITE_OMIT_UTF16 */
|
|
@@ -30298,7 +31147,9 @@
|
|
*/
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <stdarg.h> */
|
|
+#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
#include <math.h>
|
|
+#endif
|
|
|
|
/*
|
|
** Routine needed to support the testcase() macro.
|
|
@@ -30473,6 +31324,7 @@
|
|
sqlite3DbFree(db, pParse->zErrMsg);
|
|
pParse->zErrMsg = zMsg;
|
|
pParse->rc = SQLITE_ERROR;
|
|
+ pParse->pWith = 0;
|
|
}
|
|
}
|
|
|
|
@@ -30595,6 +31447,19 @@
|
|
return N<0 ? 0 : UpperToLower[*a] - UpperToLower[*b];
|
|
}
|
|
|
|
+/*
|
|
+** Compute an 8-bit hash on a string that is insensitive to case differences
|
|
+*/
|
|
+SQLITE_PRIVATE u8 sqlite3StrIHash(const char *z){
|
|
+ u8 h = 0;
|
|
+ if( z==0 ) return 0;
|
|
+ while( z[0] ){
|
|
+ h += UpperToLower[(unsigned char)z[0]];
|
|
+ z++;
|
|
+ }
|
|
+ return h;
|
|
+}
|
|
+
|
|
/*
|
|
** Compute 10 to the E-th power. Examples: E==1 results in 10.
|
|
** E==2 results in 100. E==50 results in 1.0e50.
|
|
@@ -30663,10 +31528,13 @@
|
|
** returns FALSE but it still converts the prefix and writes the result
|
|
** into *pResult.
|
|
*/
|
|
+#if defined(_MSC_VER)
|
|
+#pragma warning(disable : 4756)
|
|
+#endif
|
|
SQLITE_PRIVATE int sqlite3AtoF(const char *z, double *pResult, int length, u8 enc){
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
int incr;
|
|
- const char *zEnd = z + length;
|
|
+ const char *zEnd;
|
|
/* sign * significand * (10 ^ (esign * exponent)) */
|
|
int sign = 1; /* sign of significand */
|
|
i64 s = 0; /* significand */
|
|
@@ -30680,12 +31548,15 @@
|
|
|
|
assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
|
*pResult = 0.0; /* Default return value, in case of an error */
|
|
+ if( length==0 ) return 0;
|
|
|
|
if( enc==SQLITE_UTF8 ){
|
|
incr = 1;
|
|
+ zEnd = z + length;
|
|
}else{
|
|
int i;
|
|
incr = 2;
|
|
+ length &= ~1;
|
|
assert( SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
|
testcase( enc==SQLITE_UTF16LE );
|
|
testcase( enc==SQLITE_UTF16BE );
|
|
@@ -30850,6 +31721,9 @@
|
|
return !sqlite3Atoi64(z, pResult, length, enc);
|
|
#endif /* SQLITE_OMIT_FLOATING_POINT */
|
|
}
|
|
+#if defined(_MSC_VER)
|
|
+#pragma warning(default : 4756)
|
|
+#endif
|
|
|
|
/*
|
|
** Compare the 19-character string zNum against the text representation
|
|
@@ -31525,7 +32399,7 @@
|
|
return (u8)(h & 0xf);
|
|
}
|
|
|
|
-#if !defined(SQLITE_OMIT_BLOB_LITERAL) || defined(SQLITE_HAS_CODEC)
|
|
+#if !defined(SQLITE_OMIT_BLOB_LITERAL)
|
|
/*
|
|
** Convert a BLOB literal of the form "x'hhhhhh'" into its binary
|
|
** value. Return a pointer to its binary value. Space to hold the
|
|
@@ -31546,7 +32420,7 @@
|
|
}
|
|
return zBlob;
|
|
}
|
|
-#endif /* !SQLITE_OMIT_BLOB_LITERAL || SQLITE_HAS_CODEC */
|
|
+#endif /* !SQLITE_OMIT_BLOB_LITERAL */
|
|
|
|
/*
|
|
** Log an error that is an API call on a connection pointer that should
|
|
@@ -31779,7 +32653,7 @@
|
|
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
|
|
|
#if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || \
|
|
- defined(SQLITE_ENABLE_STAT3_OR_STAT4) || \
|
|
+ defined(SQLITE_ENABLE_STAT4) || \
|
|
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
|
|
/*
|
|
** Convert a LogEst into an integer.
|
|
@@ -31797,7 +32671,7 @@
|
|
defined(SQLITE_EXPLAIN_ESTIMATED_ROWS)
|
|
if( x>60 ) return (u64)LARGEST_INT64;
|
|
#else
|
|
- /* If only SQLITE_ENABLE_STAT3_OR_STAT4 is on, then the largest input
|
|
+ /* If only SQLITE_ENABLE_STAT4 is on, then the largest input
|
|
** possible to this routine is 310, resulting in a maximum x of 31 */
|
|
assert( x<=60 );
|
|
#endif
|
|
@@ -32220,30 +33094,30 @@
|
|
/* 23 */ "SeekLE" OpHelp("key=r[P3@P4]"),
|
|
/* 24 */ "SeekGE" OpHelp("key=r[P3@P4]"),
|
|
/* 25 */ "SeekGT" OpHelp("key=r[P3@P4]"),
|
|
- /* 26 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
|
|
- /* 27 */ "NoConflict" OpHelp("key=r[P3@P4]"),
|
|
- /* 28 */ "NotFound" OpHelp("key=r[P3@P4]"),
|
|
- /* 29 */ "Found" OpHelp("key=r[P3@P4]"),
|
|
- /* 30 */ "SeekRowid" OpHelp("intkey=r[P3]"),
|
|
- /* 31 */ "NotExists" OpHelp("intkey=r[P3]"),
|
|
- /* 32 */ "Last" OpHelp(""),
|
|
- /* 33 */ "IfSmaller" OpHelp(""),
|
|
- /* 34 */ "SorterSort" OpHelp(""),
|
|
- /* 35 */ "Sort" OpHelp(""),
|
|
- /* 36 */ "Rewind" OpHelp(""),
|
|
- /* 37 */ "IdxLE" OpHelp("key=r[P3@P4]"),
|
|
- /* 38 */ "IdxGT" OpHelp("key=r[P3@P4]"),
|
|
- /* 39 */ "IdxLT" OpHelp("key=r[P3@P4]"),
|
|
- /* 40 */ "IdxGE" OpHelp("key=r[P3@P4]"),
|
|
- /* 41 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
|
|
- /* 42 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
|
|
+ /* 26 */ "IfNotOpen" OpHelp("if( !csr[P1] ) goto P2"),
|
|
+ /* 27 */ "IfNoHope" OpHelp("key=r[P3@P4]"),
|
|
+ /* 28 */ "NoConflict" OpHelp("key=r[P3@P4]"),
|
|
+ /* 29 */ "NotFound" OpHelp("key=r[P3@P4]"),
|
|
+ /* 30 */ "Found" OpHelp("key=r[P3@P4]"),
|
|
+ /* 31 */ "SeekRowid" OpHelp("intkey=r[P3]"),
|
|
+ /* 32 */ "NotExists" OpHelp("intkey=r[P3]"),
|
|
+ /* 33 */ "Last" OpHelp(""),
|
|
+ /* 34 */ "IfSmaller" OpHelp(""),
|
|
+ /* 35 */ "SorterSort" OpHelp(""),
|
|
+ /* 36 */ "Sort" OpHelp(""),
|
|
+ /* 37 */ "Rewind" OpHelp(""),
|
|
+ /* 38 */ "IdxLE" OpHelp("key=r[P3@P4]"),
|
|
+ /* 39 */ "IdxGT" OpHelp("key=r[P3@P4]"),
|
|
+ /* 40 */ "IdxLT" OpHelp("key=r[P3@P4]"),
|
|
+ /* 41 */ "IdxGE" OpHelp("key=r[P3@P4]"),
|
|
+ /* 42 */ "RowSetRead" OpHelp("r[P3]=rowset(P1)"),
|
|
/* 43 */ "Or" OpHelp("r[P3]=(r[P1] || r[P2])"),
|
|
/* 44 */ "And" OpHelp("r[P3]=(r[P1] && r[P2])"),
|
|
- /* 45 */ "Program" OpHelp(""),
|
|
- /* 46 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
|
|
- /* 47 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
|
|
- /* 48 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
|
|
- /* 49 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
|
|
+ /* 45 */ "RowSetTest" OpHelp("if r[P3] in rowset(P1) goto P2"),
|
|
+ /* 46 */ "Program" OpHelp(""),
|
|
+ /* 47 */ "FkIfZero" OpHelp("if fkctr[P1]==0 goto P2"),
|
|
+ /* 48 */ "IfPos" OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
|
|
+ /* 49 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
|
|
/* 50 */ "IsNull" OpHelp("if r[P1]==NULL goto P2"),
|
|
/* 51 */ "NotNull" OpHelp("if r[P1]!=NULL goto P2"),
|
|
/* 52 */ "Ne" OpHelp("IF r[P3]!=r[P1]"),
|
|
@@ -32253,83 +33127,83 @@
|
|
/* 56 */ "Lt" OpHelp("IF r[P3]<r[P1]"),
|
|
/* 57 */ "Ge" OpHelp("IF r[P3]>=r[P1]"),
|
|
/* 58 */ "ElseNotEq" OpHelp(""),
|
|
- /* 59 */ "IncrVacuum" OpHelp(""),
|
|
- /* 60 */ "VNext" OpHelp(""),
|
|
- /* 61 */ "Init" OpHelp("Start at P2"),
|
|
- /* 62 */ "PureFunc0" OpHelp(""),
|
|
- /* 63 */ "Function0" OpHelp("r[P3]=func(r[P2@P5])"),
|
|
- /* 64 */ "PureFunc" OpHelp(""),
|
|
- /* 65 */ "Function" OpHelp("r[P3]=func(r[P2@P5])"),
|
|
- /* 66 */ "Return" OpHelp(""),
|
|
- /* 67 */ "EndCoroutine" OpHelp(""),
|
|
- /* 68 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
|
|
- /* 69 */ "Halt" OpHelp(""),
|
|
- /* 70 */ "Integer" OpHelp("r[P2]=P1"),
|
|
- /* 71 */ "Int64" OpHelp("r[P2]=P4"),
|
|
- /* 72 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
|
|
- /* 73 */ "Null" OpHelp("r[P2..P3]=NULL"),
|
|
- /* 74 */ "SoftNull" OpHelp("r[P1]=NULL"),
|
|
- /* 75 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
|
|
- /* 76 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
|
|
- /* 77 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
|
|
- /* 78 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
|
|
- /* 79 */ "SCopy" OpHelp("r[P2]=r[P1]"),
|
|
- /* 80 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
|
|
- /* 81 */ "ResultRow" OpHelp("output=r[P1@P2]"),
|
|
- /* 82 */ "CollSeq" OpHelp(""),
|
|
- /* 83 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
|
|
- /* 84 */ "RealAffinity" OpHelp(""),
|
|
- /* 85 */ "Cast" OpHelp("affinity(r[P1])"),
|
|
- /* 86 */ "Permutation" OpHelp(""),
|
|
- /* 87 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
|
|
- /* 88 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
|
|
- /* 89 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
|
|
- /* 90 */ "Column" OpHelp("r[P3]=PX"),
|
|
- /* 91 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
|
|
- /* 92 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
|
|
- /* 93 */ "Count" OpHelp("r[P2]=count()"),
|
|
- /* 94 */ "ReadCookie" OpHelp(""),
|
|
- /* 95 */ "SetCookie" OpHelp(""),
|
|
- /* 96 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
|
|
- /* 97 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
|
|
- /* 98 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
|
|
- /* 99 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
|
|
- /* 100 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
|
|
- /* 101 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
|
|
- /* 102 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
|
|
- /* 103 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
|
|
- /* 104 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
|
|
- /* 105 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
|
|
- /* 106 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
|
|
- /* 107 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
|
|
- /* 108 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
|
|
- /* 109 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
|
|
- /* 110 */ "String8" OpHelp("r[P2]='P4'"),
|
|
- /* 111 */ "OpenDup" OpHelp(""),
|
|
- /* 112 */ "OpenAutoindex" OpHelp("nColumn=P2"),
|
|
- /* 113 */ "OpenEphemeral" OpHelp("nColumn=P2"),
|
|
- /* 114 */ "SorterOpen" OpHelp(""),
|
|
- /* 115 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
|
|
- /* 116 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
|
|
- /* 117 */ "Close" OpHelp(""),
|
|
- /* 118 */ "ColumnsUsed" OpHelp(""),
|
|
- /* 119 */ "SeekHit" OpHelp("seekHit=P2"),
|
|
- /* 120 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
|
|
- /* 121 */ "NewRowid" OpHelp("r[P2]=rowid"),
|
|
- /* 122 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
|
|
- /* 123 */ "Delete" OpHelp(""),
|
|
- /* 124 */ "ResetCount" OpHelp(""),
|
|
- /* 125 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
|
|
- /* 126 */ "SorterData" OpHelp("r[P2]=data"),
|
|
- /* 127 */ "RowData" OpHelp("r[P2]=data"),
|
|
- /* 128 */ "Rowid" OpHelp("r[P2]=rowid"),
|
|
- /* 129 */ "NullRow" OpHelp(""),
|
|
- /* 130 */ "SeekEnd" OpHelp(""),
|
|
+ /* 59 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
|
|
+ /* 60 */ "IncrVacuum" OpHelp(""),
|
|
+ /* 61 */ "VNext" OpHelp(""),
|
|
+ /* 62 */ "Init" OpHelp("Start at P2"),
|
|
+ /* 63 */ "PureFunc" OpHelp("r[P3]=func(r[P2@NP])"),
|
|
+ /* 64 */ "Function" OpHelp("r[P3]=func(r[P2@NP])"),
|
|
+ /* 65 */ "Return" OpHelp(""),
|
|
+ /* 66 */ "EndCoroutine" OpHelp(""),
|
|
+ /* 67 */ "HaltIfNull" OpHelp("if r[P3]=null halt"),
|
|
+ /* 68 */ "Halt" OpHelp(""),
|
|
+ /* 69 */ "Integer" OpHelp("r[P2]=P1"),
|
|
+ /* 70 */ "Int64" OpHelp("r[P2]=P4"),
|
|
+ /* 71 */ "String" OpHelp("r[P2]='P4' (len=P1)"),
|
|
+ /* 72 */ "Null" OpHelp("r[P2..P3]=NULL"),
|
|
+ /* 73 */ "SoftNull" OpHelp("r[P1]=NULL"),
|
|
+ /* 74 */ "Blob" OpHelp("r[P2]=P4 (len=P1)"),
|
|
+ /* 75 */ "Variable" OpHelp("r[P2]=parameter(P1,P4)"),
|
|
+ /* 76 */ "Move" OpHelp("r[P2@P3]=r[P1@P3]"),
|
|
+ /* 77 */ "Copy" OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
|
|
+ /* 78 */ "SCopy" OpHelp("r[P2]=r[P1]"),
|
|
+ /* 79 */ "IntCopy" OpHelp("r[P2]=r[P1]"),
|
|
+ /* 80 */ "ResultRow" OpHelp("output=r[P1@P2]"),
|
|
+ /* 81 */ "CollSeq" OpHelp(""),
|
|
+ /* 82 */ "AddImm" OpHelp("r[P1]=r[P1]+P2"),
|
|
+ /* 83 */ "RealAffinity" OpHelp(""),
|
|
+ /* 84 */ "Cast" OpHelp("affinity(r[P1])"),
|
|
+ /* 85 */ "Permutation" OpHelp(""),
|
|
+ /* 86 */ "Compare" OpHelp("r[P1@P3] <-> r[P2@P3]"),
|
|
+ /* 87 */ "IsTrue" OpHelp("r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4"),
|
|
+ /* 88 */ "Offset" OpHelp("r[P3] = sqlite_offset(P1)"),
|
|
+ /* 89 */ "Column" OpHelp("r[P3]=PX"),
|
|
+ /* 90 */ "Affinity" OpHelp("affinity(r[P1@P2])"),
|
|
+ /* 91 */ "MakeRecord" OpHelp("r[P3]=mkrec(r[P1@P2])"),
|
|
+ /* 92 */ "Count" OpHelp("r[P2]=count()"),
|
|
+ /* 93 */ "ReadCookie" OpHelp(""),
|
|
+ /* 94 */ "SetCookie" OpHelp(""),
|
|
+ /* 95 */ "ReopenIdx" OpHelp("root=P2 iDb=P3"),
|
|
+ /* 96 */ "OpenRead" OpHelp("root=P2 iDb=P3"),
|
|
+ /* 97 */ "OpenWrite" OpHelp("root=P2 iDb=P3"),
|
|
+ /* 98 */ "OpenDup" OpHelp(""),
|
|
+ /* 99 */ "OpenAutoindex" OpHelp("nColumn=P2"),
|
|
+ /* 100 */ "OpenEphemeral" OpHelp("nColumn=P2"),
|
|
+ /* 101 */ "BitAnd" OpHelp("r[P3]=r[P1]&r[P2]"),
|
|
+ /* 102 */ "BitOr" OpHelp("r[P3]=r[P1]|r[P2]"),
|
|
+ /* 103 */ "ShiftLeft" OpHelp("r[P3]=r[P2]<<r[P1]"),
|
|
+ /* 104 */ "ShiftRight" OpHelp("r[P3]=r[P2]>>r[P1]"),
|
|
+ /* 105 */ "Add" OpHelp("r[P3]=r[P1]+r[P2]"),
|
|
+ /* 106 */ "Subtract" OpHelp("r[P3]=r[P2]-r[P1]"),
|
|
+ /* 107 */ "Multiply" OpHelp("r[P3]=r[P1]*r[P2]"),
|
|
+ /* 108 */ "Divide" OpHelp("r[P3]=r[P2]/r[P1]"),
|
|
+ /* 109 */ "Remainder" OpHelp("r[P3]=r[P2]%r[P1]"),
|
|
+ /* 110 */ "Concat" OpHelp("r[P3]=r[P2]+r[P1]"),
|
|
+ /* 111 */ "SorterOpen" OpHelp(""),
|
|
+ /* 112 */ "BitNot" OpHelp("r[P2]= ~r[P1]"),
|
|
+ /* 113 */ "SequenceTest" OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
|
|
+ /* 114 */ "OpenPseudo" OpHelp("P3 columns in r[P2]"),
|
|
+ /* 115 */ "String8" OpHelp("r[P2]='P4'"),
|
|
+ /* 116 */ "Close" OpHelp(""),
|
|
+ /* 117 */ "ColumnsUsed" OpHelp(""),
|
|
+ /* 118 */ "SeekHit" OpHelp("seekHit=P2"),
|
|
+ /* 119 */ "Sequence" OpHelp("r[P2]=cursor[P1].ctr++"),
|
|
+ /* 120 */ "NewRowid" OpHelp("r[P2]=rowid"),
|
|
+ /* 121 */ "Insert" OpHelp("intkey=r[P3] data=r[P2]"),
|
|
+ /* 122 */ "Delete" OpHelp(""),
|
|
+ /* 123 */ "ResetCount" OpHelp(""),
|
|
+ /* 124 */ "SorterCompare" OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
|
|
+ /* 125 */ "SorterData" OpHelp("r[P2]=data"),
|
|
+ /* 126 */ "RowData" OpHelp("r[P2]=data"),
|
|
+ /* 127 */ "Rowid" OpHelp("r[P2]=rowid"),
|
|
+ /* 128 */ "NullRow" OpHelp(""),
|
|
+ /* 129 */ "SeekEnd" OpHelp(""),
|
|
+ /* 130 */ "IdxInsert" OpHelp("key=r[P2]"),
|
|
/* 131 */ "SorterInsert" OpHelp("key=r[P2]"),
|
|
- /* 132 */ "IdxInsert" OpHelp("key=r[P2]"),
|
|
- /* 133 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
|
|
- /* 134 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
|
|
- /* 135 */ "IdxRowid" OpHelp("r[P2]=rowid"),
|
|
+ /* 132 */ "IdxDelete" OpHelp("key=r[P2@P3]"),
|
|
+ /* 133 */ "DeferredSeek" OpHelp("Move P3 to P1.rowid if needed"),
|
|
+ /* 134 */ "IdxRowid" OpHelp("r[P2]=rowid"),
|
|
+ /* 135 */ "FinishSeek" OpHelp(""),
|
|
/* 136 */ "Destroy" OpHelp(""),
|
|
/* 137 */ "Clear" OpHelp(""),
|
|
/* 138 */ "ResetSorter" OpHelp(""),
|
|
@@ -32339,12 +33213,12 @@
|
|
/* 142 */ "LoadAnalysis" OpHelp(""),
|
|
/* 143 */ "DropTable" OpHelp(""),
|
|
/* 144 */ "DropIndex" OpHelp(""),
|
|
- /* 145 */ "Real" OpHelp("r[P2]=P4"),
|
|
- /* 146 */ "DropTrigger" OpHelp(""),
|
|
- /* 147 */ "IntegrityCk" OpHelp(""),
|
|
- /* 148 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
|
|
- /* 149 */ "Param" OpHelp(""),
|
|
- /* 150 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
|
|
+ /* 145 */ "DropTrigger" OpHelp(""),
|
|
+ /* 146 */ "IntegrityCk" OpHelp(""),
|
|
+ /* 147 */ "RowSetAdd" OpHelp("rowset(P1)=r[P2]"),
|
|
+ /* 148 */ "Param" OpHelp(""),
|
|
+ /* 149 */ "FkCounter" OpHelp("fkctr[P1]+=P2"),
|
|
+ /* 150 */ "Real" OpHelp("r[P2]=P4"),
|
|
/* 151 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
|
|
/* 152 */ "OffsetLimit" OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
|
|
/* 153 */ "AggInverse" OpHelp("accum=r[P3] inverse(r[P2@P5])"),
|
|
@@ -32353,20 +33227,23 @@
|
|
/* 156 */ "AggValue" OpHelp("r[P3]=value N=P2"),
|
|
/* 157 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
|
|
/* 158 */ "Expire" OpHelp(""),
|
|
- /* 159 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
|
|
- /* 160 */ "VBegin" OpHelp(""),
|
|
- /* 161 */ "VCreate" OpHelp(""),
|
|
- /* 162 */ "VDestroy" OpHelp(""),
|
|
- /* 163 */ "VOpen" OpHelp(""),
|
|
- /* 164 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
|
|
- /* 165 */ "VRename" OpHelp(""),
|
|
- /* 166 */ "Pagecount" OpHelp(""),
|
|
- /* 167 */ "MaxPgcnt" OpHelp(""),
|
|
- /* 168 */ "Trace" OpHelp(""),
|
|
- /* 169 */ "CursorHint" OpHelp(""),
|
|
- /* 170 */ "Noop" OpHelp(""),
|
|
- /* 171 */ "Explain" OpHelp(""),
|
|
- /* 172 */ "Abortable" OpHelp(""),
|
|
+ /* 159 */ "CursorLock" OpHelp(""),
|
|
+ /* 160 */ "CursorUnlock" OpHelp(""),
|
|
+ /* 161 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
|
|
+ /* 162 */ "VBegin" OpHelp(""),
|
|
+ /* 163 */ "VCreate" OpHelp(""),
|
|
+ /* 164 */ "VDestroy" OpHelp(""),
|
|
+ /* 165 */ "VOpen" OpHelp(""),
|
|
+ /* 166 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
|
|
+ /* 167 */ "VRename" OpHelp(""),
|
|
+ /* 168 */ "Pagecount" OpHelp(""),
|
|
+ /* 169 */ "MaxPgcnt" OpHelp(""),
|
|
+ /* 170 */ "Trace" OpHelp(""),
|
|
+ /* 171 */ "CursorHint" OpHelp(""),
|
|
+ /* 172 */ "ReleaseReg" OpHelp("release r[P1@P2] mask P3"),
|
|
+ /* 173 */ "Noop" OpHelp(""),
|
|
+ /* 174 */ "Explain" OpHelp(""),
|
|
+ /* 175 */ "Abortable" OpHelp(""),
|
|
};
|
|
return azName[i];
|
|
}
|
|
@@ -32481,13 +33358,29 @@
|
|
# include <sys/param.h>
|
|
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
|
|
|
|
-#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
|
|
- (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
|
|
-# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
|
|
- && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
|
|
-# define HAVE_GETHOSTUUID 1
|
|
-# else
|
|
-# warning "gethostuuid() is disabled."
|
|
+/*
|
|
+** Try to determine if gethostuuid() is available based on standard
|
|
+** macros. This might sometimes compute the wrong value for some
|
|
+** obscure platforms. For those cases, simply compile with one of
|
|
+** the following:
|
|
+**
|
|
+** -DHAVE_GETHOSTUUID=0
|
|
+** -DHAVE_GETHOSTUUID=1
|
|
+**
|
|
+** None if this matters except when building on Apple products with
|
|
+** -DSQLITE_ENABLE_LOCKING_STYLE.
|
|
+*/
|
|
+#ifndef HAVE_GETHOSTUUID
|
|
+# define HAVE_GETHOSTUUID 0
|
|
+# if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
|
|
+ (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
|
|
+# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
|
|
+ && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
|
|
+# undef HAVE_GETHOSTUUID
|
|
+# define HAVE_GETHOSTUUID 1
|
|
+# else
|
|
+# warning "gethostuuid() is disabled."
|
|
+# endif
|
|
# endif
|
|
#endif
|
|
|
|
@@ -32714,7 +33607,7 @@
|
|
******************************************************************************
|
|
**
|
|
** This file contains inline asm code for retrieving "high-performance"
|
|
-** counters for x86 class CPUs.
|
|
+** counters for x86 and x86_64 class CPUs.
|
|
*/
|
|
#ifndef SQLITE_HWTIME_H
|
|
#define SQLITE_HWTIME_H
|
|
@@ -32725,8 +33618,9 @@
|
|
** processor and returns that value. This can be used for high-res
|
|
** profiling.
|
|
*/
|
|
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
+#if !defined(__STRICT_ANSI__) && \
|
|
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
@@ -32747,7 +33641,7 @@
|
|
|
|
#endif
|
|
|
|
-#elif (defined(__GNUC__) && defined(__x86_64__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long val;
|
|
@@ -32755,7 +33649,7 @@
|
|
return val;
|
|
}
|
|
|
|
-#elif (defined(__GNUC__) && defined(__ppc__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long long retval;
|
|
@@ -32772,14 +33666,13 @@
|
|
|
|
#else
|
|
|
|
- #error Need implementation of sqlite3Hwtime() for your platform.
|
|
-
|
|
/*
|
|
- ** To compile without implementing sqlite3Hwtime() for your platform,
|
|
- ** you can remove the above #error and use the following
|
|
- ** stub function. You will lose timing support for many
|
|
- ** of the debugging and testing utilities, but it should at
|
|
- ** least compile and run.
|
|
+ ** asm() is needed for hardware timing support. Without asm(),
|
|
+ ** disable the sqlite3Hwtime() routine.
|
|
+ **
|
|
+ ** sqlite3Hwtime() is only used for some obscure debugging
|
|
+ ** and analysis configurations, not in any deliverable, so this
|
|
+ ** should not be a great loss.
|
|
*/
|
|
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
|
|
|
|
@@ -33095,13 +33988,14 @@
|
|
#if defined(__linux__) && defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
# ifdef __ANDROID__
|
|
{ "ioctl", (sqlite3_syscall_ptr)(int(*)(int, int, ...))ioctl, 0 },
|
|
+#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
|
|
# else
|
|
{ "ioctl", (sqlite3_syscall_ptr)ioctl, 0 },
|
|
+#define osIoctl ((int(*)(int,unsigned long,...))aSyscall[28].pCurrent)
|
|
# endif
|
|
#else
|
|
{ "ioctl", (sqlite3_syscall_ptr)0, 0 },
|
|
#endif
|
|
-#define osIoctl ((int(*)(int,int,...))aSyscall[28].pCurrent)
|
|
|
|
}; /* End of the overrideable system calls */
|
|
|
|
@@ -33246,7 +34140,7 @@
|
|
sqlite3_log(SQLITE_WARNING,
|
|
"attempt to open \"%s\" as file descriptor %d", z, fd);
|
|
fd = -1;
|
|
- if( osOpen("/dev/null", f, m)<0 ) break;
|
|
+ if( osOpen("/dev/null", O_RDONLY, m)<0 ) break;
|
|
}
|
|
if( fd>=0 ){
|
|
if( m!=0 ){
|
|
@@ -34122,8 +35016,9 @@
|
|
struct flock *pLock, /* The description of the lock */
|
|
unixFile *pFile /* Structure holding timeout value */
|
|
){
|
|
+ int tm = pFile->iBusyTimeout;
|
|
int rc = osFcntl(h,F_SETLK,pLock);
|
|
- while( rc<0 && pFile->iBusyTimeout>0 ){
|
|
+ while( rc<0 && tm>0 ){
|
|
/* On systems that support some kind of blocking file lock with a timeout,
|
|
** make appropriate changes here to invoke that blocking file lock. On
|
|
** generic posix, however, there is no such API. So we simply try the
|
|
@@ -34131,7 +35026,7 @@
|
|
** the lock is obtained. */
|
|
usleep(1000);
|
|
rc = osFcntl(h,F_SETLK,pLock);
|
|
- pFile->iBusyTimeout--;
|
|
+ tm--;
|
|
}
|
|
return rc;
|
|
}
|
|
@@ -36552,7 +37447,9 @@
|
|
}
|
|
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
case SQLITE_FCNTL_LOCK_TIMEOUT: {
|
|
+ int iOld = pFile->iBusyTimeout;
|
|
pFile->iBusyTimeout = *(int*)pArg;
|
|
+ *(int*)pArg = iOld;
|
|
return SQLITE_OK;
|
|
}
|
|
#endif
|
|
@@ -36871,13 +37768,20 @@
|
|
assert( n>=1 && n<=SQLITE_SHM_NLOCK );
|
|
|
|
if( pShmNode->hShm>=0 ){
|
|
+ int res;
|
|
/* Initialize the locking parameters */
|
|
f.l_type = lockType;
|
|
f.l_whence = SEEK_SET;
|
|
f.l_start = ofst;
|
|
f.l_len = n;
|
|
- rc = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
|
|
- rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
|
|
+ res = osSetPosixAdvisoryLock(pShmNode->hShm, &f, pFile);
|
|
+ if( res==-1 ){
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ rc = (pFile->iBusyTimeout ? SQLITE_BUSY_TIMEOUT : SQLITE_BUSY);
|
|
+#else
|
|
+ rc = SQLITE_BUSY;
|
|
+#endif
|
|
+ }
|
|
}
|
|
|
|
/* Update the global lock state and do debug tracing */
|
|
@@ -37133,10 +38037,12 @@
|
|
|
|
if( pInode->bProcessLock==0 ){
|
|
if( 0==sqlite3_uri_boolean(pDbFd->zPath, "readonly_shm", 0) ){
|
|
- pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT,(sStat.st_mode&0777));
|
|
+ pShmNode->hShm = robust_open(zShm, O_RDWR|O_CREAT|O_NOFOLLOW,
|
|
+ (sStat.st_mode&0777));
|
|
}
|
|
if( pShmNode->hShm<0 ){
|
|
- pShmNode->hShm = robust_open(zShm, O_RDONLY, (sStat.st_mode&0777));
|
|
+ pShmNode->hShm = robust_open(zShm, O_RDONLY|O_NOFOLLOW,
|
|
+ (sStat.st_mode&0777));
|
|
if( pShmNode->hShm<0 ){
|
|
rc = unixLogError(SQLITE_CANTOPEN_BKPT, "open", zShm);
|
|
goto shm_open_err;
|
|
@@ -37372,6 +38278,25 @@
|
|
assert( pShmNode->hShm>=0 || pDbFd->pInode->bProcessLock==1 );
|
|
assert( pShmNode->hShm<0 || pDbFd->pInode->bProcessLock==0 );
|
|
|
|
+ /* Check that, if this to be a blocking lock, no locks that occur later
|
|
+ ** in the following list than the lock being obtained are already held:
|
|
+ **
|
|
+ ** 1. Checkpointer lock (ofst==1).
|
|
+ ** 2. Write lock (ofst==0).
|
|
+ ** 3. Read locks (ofst>=3 && ofst<SQLITE_SHM_NLOCK).
|
|
+ **
|
|
+ ** In other words, if this is a blocking lock, none of the locks that
|
|
+ ** occur later in the above list than the lock being obtained may be
|
|
+ ** held. */
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
|
|
+ (ofst!=2) /* not RECOVER */
|
|
+ && (ofst!=1 || (p->exclMask|p->sharedMask)==0)
|
|
+ && (ofst!=0 || (p->exclMask|p->sharedMask)<3)
|
|
+ && (ofst<3 || (p->exclMask|p->sharedMask)<(1<<ofst))
|
|
+ ));
|
|
+#endif
|
|
+
|
|
mask = (1<<(ofst+n)) - (1<<ofst);
|
|
assert( n>1 || mask==(1<<ofst) );
|
|
sqlite3_mutex_enter(pShmNode->pShmMutex);
|
|
@@ -38343,6 +39268,7 @@
|
|
UnixUnusedFd **pp;
|
|
assert( sqlite3_mutex_notheld(pInode->pLockMutex) );
|
|
sqlite3_mutex_enter(pInode->pLockMutex);
|
|
+ flags &= (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
|
|
for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext));
|
|
pUnused = *pp;
|
|
if( pUnused ){
|
|
@@ -38396,7 +39322,7 @@
|
|
** If the SQLITE_ENABLE_8_3_NAMES option is enabled, then the
|
|
** original filename is unavailable. But 8_3_NAMES is only used for
|
|
** FAT filesystems and permissions do not matter there, so just use
|
|
-** the default permissions.
|
|
+** the default permissions. In 8_3_NAMES mode, leave *pMode set to zero.
|
|
*/
|
|
static int findCreateFileMode(
|
|
const char *zPath, /* Path of file (possibly) being created */
|
|
@@ -38485,7 +39411,7 @@
|
|
unixFile *p = (unixFile *)pFile;
|
|
int fd = -1; /* File descriptor returned by open() */
|
|
int openFlags = 0; /* Flags to pass to open() */
|
|
- int eType = flags&0xFFFFFF00; /* Type of file to open */
|
|
+ int eType = flags&0x0FFF00; /* Type of file to open */
|
|
int noLock; /* True to omit locking primitives */
|
|
int rc = SQLITE_OK; /* Function Return Code */
|
|
int ctrlFlags = 0; /* UNIXFILE_* flags */
|
|
@@ -38595,7 +39521,7 @@
|
|
if( isReadWrite ) openFlags |= O_RDWR;
|
|
if( isCreate ) openFlags |= O_CREAT;
|
|
if( isExclusive ) openFlags |= (O_EXCL|O_NOFOLLOW);
|
|
- openFlags |= (O_LARGEFILE|O_BINARY);
|
|
+ openFlags |= (O_LARGEFILE|O_BINARY|O_NOFOLLOW);
|
|
|
|
if( fd<0 ){
|
|
mode_t openMode; /* Permissions to create file with */
|
|
@@ -38631,11 +39557,19 @@
|
|
goto open_finished;
|
|
}
|
|
|
|
- /* If this process is running as root and if creating a new rollback
|
|
- ** journal or WAL file, set the ownership of the journal or WAL to be
|
|
- ** the same as the original database.
|
|
+ /* The owner of the rollback journal or WAL file should always be the
|
|
+ ** same as the owner of the database file. Try to ensure that this is
|
|
+ ** the case. The chown() system call will be a no-op if the current
|
|
+ ** process lacks root privileges, be we should at least try. Without
|
|
+ ** this step, if a root process opens a database file, it can leave
|
|
+ ** behinds a journal/WAL that is owned by root and hence make the
|
|
+ ** database inaccessible to unprivileged processes.
|
|
+ **
|
|
+ ** If openMode==0, then that means uid and gid are not set correctly
|
|
+ ** (probably because SQLite is configured to use 8+3 filename mode) and
|
|
+ ** in that case we do not want to attempt the chown().
|
|
*/
|
|
- if( flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL) ){
|
|
+ if( openMode && (flags & (SQLITE_OPEN_WAL|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
|
|
robustFchown(fd, uid, gid);
|
|
}
|
|
}
|
|
@@ -38646,7 +39580,8 @@
|
|
|
|
if( p->pPreallocatedUnused ){
|
|
p->pPreallocatedUnused->fd = fd;
|
|
- p->pPreallocatedUnused->flags = flags;
|
|
+ p->pPreallocatedUnused->flags =
|
|
+ flags & (SQLITE_OPEN_READONLY|SQLITE_OPEN_READWRITE);
|
|
}
|
|
|
|
if( isDelete ){
|
|
@@ -38804,7 +39739,8 @@
|
|
|
|
if( flags==SQLITE_ACCESS_EXISTS ){
|
|
struct stat buf;
|
|
- *pResOut = (0==osStat(zPath, &buf) && buf.st_size>0);
|
|
+ *pResOut = 0==osStat(zPath, &buf) &&
|
|
+ (!S_ISREG(buf.st_mode) || buf.st_size>0);
|
|
}else{
|
|
*pResOut = osAccess(zPath, W_OK|R_OK)==0;
|
|
}
|
|
@@ -38858,7 +39794,7 @@
|
|
#else
|
|
int rc = SQLITE_OK;
|
|
int nByte;
|
|
- int nLink = 1; /* Number of symbolic links followed so far */
|
|
+ int nLink = 0; /* Number of symbolic links followed so far */
|
|
const char *zIn = zPath; /* Input path for each iteration of loop */
|
|
char *zDel = 0;
|
|
|
|
@@ -38887,10 +39823,11 @@
|
|
}
|
|
|
|
if( bLink ){
|
|
+ nLink++;
|
|
if( zDel==0 ){
|
|
zDel = sqlite3_malloc(nOut);
|
|
if( zDel==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
- }else if( ++nLink>SQLITE_MAX_SYMLINKS ){
|
|
+ }else if( nLink>=SQLITE_MAX_SYMLINKS ){
|
|
rc = SQLITE_CANTOPEN_BKPT;
|
|
}
|
|
|
|
@@ -38926,6 +39863,7 @@
|
|
}while( rc==SQLITE_OK );
|
|
|
|
sqlite3_free(zDel);
|
|
+ if( rc==SQLITE_OK && nLink ) rc = SQLITE_OK_SYMLINK;
|
|
return rc;
|
|
#endif /* HAVE_READLINK && HAVE_LSTAT */
|
|
}
|
|
@@ -39411,7 +40349,7 @@
|
|
int fd = -1;
|
|
unixFile *pNew;
|
|
int rc = SQLITE_OK;
|
|
- int openFlags = O_RDWR | O_CREAT;
|
|
+ int openFlags = O_RDWR | O_CREAT | O_NOFOLLOW;
|
|
sqlite3_vfs dummyVfs;
|
|
int terrno = 0;
|
|
UnixUnusedFd *pUnused = NULL;
|
|
@@ -39441,7 +40379,7 @@
|
|
}
|
|
}
|
|
if( fd<0 ){
|
|
- openFlags = O_RDONLY;
|
|
+ openFlags = O_RDONLY | O_NOFOLLOW;
|
|
fd = robust_open(path, openFlags, 0);
|
|
terrno = errno;
|
|
}
|
|
@@ -39492,7 +40430,7 @@
|
|
|
|
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
|
|
|
|
-#ifdef HAVE_GETHOSTUUID
|
|
+#if HAVE_GETHOSTUUID
|
|
/* Not always defined in the headers as it ought to be */
|
|
extern int gethostuuid(uuid_t id, const struct timespec *wait);
|
|
#endif
|
|
@@ -39503,7 +40441,7 @@
|
|
static int proxyGetHostID(unsigned char *pHostID, int *pError){
|
|
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
|
|
memset(pHostID, 0, PROXY_HOSTIDLEN);
|
|
-#ifdef HAVE_GETHOSTUUID
|
|
+#if HAVE_GETHOSTUUID
|
|
{
|
|
struct timespec timeout = {1, 0}; /* 1 sec timeout */
|
|
if( gethostuuid(pHostID, &timeout) ){
|
|
@@ -39567,7 +40505,7 @@
|
|
goto end_breaklock;
|
|
}
|
|
/* write it out to the temporary break file */
|
|
- fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL), 0);
|
|
+ fd = robust_open(tPath, (O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW), 0);
|
|
if( fd<0 ){
|
|
sqlite3_snprintf(sizeof(errmsg), errmsg, "create failed (%d)", errno);
|
|
goto end_breaklock;
|
|
@@ -40177,7 +41115,7 @@
|
|
assert( 0 ); /* The call assures that only valid opcodes are sent */
|
|
}
|
|
}
|
|
- /*NOTREACHED*/
|
|
+ /*NOTREACHED*/ assert(0);
|
|
return SQLITE_ERROR;
|
|
}
|
|
|
|
@@ -40525,7 +41463,7 @@
|
|
******************************************************************************
|
|
**
|
|
** This file contains inline asm code for retrieving "high-performance"
|
|
-** counters for x86 class CPUs.
|
|
+** counters for x86 and x86_64 class CPUs.
|
|
*/
|
|
#ifndef SQLITE_HWTIME_H
|
|
#define SQLITE_HWTIME_H
|
|
@@ -40536,8 +41474,9 @@
|
|
** processor and returns that value. This can be used for high-res
|
|
** profiling.
|
|
*/
|
|
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
+#if !defined(__STRICT_ANSI__) && \
|
|
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
@@ -40558,7 +41497,7 @@
|
|
|
|
#endif
|
|
|
|
-#elif (defined(__GNUC__) && defined(__x86_64__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long val;
|
|
@@ -40566,7 +41505,7 @@
|
|
return val;
|
|
}
|
|
|
|
-#elif (defined(__GNUC__) && defined(__ppc__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long long retval;
|
|
@@ -40583,14 +41522,13 @@
|
|
|
|
#else
|
|
|
|
- #error Need implementation of sqlite3Hwtime() for your platform.
|
|
-
|
|
/*
|
|
- ** To compile without implementing sqlite3Hwtime() for your platform,
|
|
- ** you can remove the above #error and use the following
|
|
- ** stub function. You will lose timing support for many
|
|
- ** of the debugging and testing utilities, but it should at
|
|
- ** least compile and run.
|
|
+ ** asm() is needed for hardware timing support. Without asm(),
|
|
+ ** disable the sqlite3Hwtime() routine.
|
|
+ **
|
|
+ ** sqlite3Hwtime() is only used for some obscure debugging
|
|
+ ** and analysis configurations, not in any deliverable, so this
|
|
+ ** should not be a great loss.
|
|
*/
|
|
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
|
|
|
|
@@ -44149,6 +45087,7 @@
|
|
/* Forward references to VFS helper methods used for temporary files */
|
|
static int winGetTempname(sqlite3_vfs *, char **);
|
|
static int winIsDir(const void *);
|
|
+static BOOL winIsLongPathPrefix(const char *);
|
|
static BOOL winIsDriveLetterAndColon(const char *);
|
|
|
|
/*
|
|
@@ -44862,6 +45801,7 @@
|
|
rc = winOpenSharedMemory(pDbFd);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
pShm = pDbFd->pShm;
|
|
+ assert( pShm!=0 );
|
|
}
|
|
pShmNode = pShm->pShmNode;
|
|
|
|
@@ -45164,6 +46104,7 @@
|
|
}
|
|
}
|
|
if( pFd->mmapSize >= iOff+nAmt ){
|
|
+ assert( pFd->pMapRegion!=0 );
|
|
*pp = &((u8 *)pFd->pMapRegion)[iOff];
|
|
pFd->nFetchOut++;
|
|
}
|
|
@@ -45916,7 +46857,9 @@
|
|
if( isReadonly ){
|
|
pFile->ctrlFlags |= WINFILE_RDONLY;
|
|
}
|
|
- if( sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE) ){
|
|
+ if( (flags & SQLITE_OPEN_MAIN_DB)
|
|
+ && sqlite3_uri_boolean(zName, "psow", SQLITE_POWERSAFE_OVERWRITE)
|
|
+ ){
|
|
pFile->ctrlFlags |= WINFILE_PSOW;
|
|
}
|
|
pFile->lastErrno = NO_ERROR;
|
|
@@ -46126,6 +47069,17 @@
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
+/*
|
|
+** Returns non-zero if the specified path name starts with the "long path"
|
|
+** prefix.
|
|
+*/
|
|
+static BOOL winIsLongPathPrefix(
|
|
+ const char *zPathname
|
|
+){
|
|
+ return ( zPathname[0]=='\\' && zPathname[1]=='\\'
|
|
+ && zPathname[2]=='?' && zPathname[3]=='\\' );
|
|
+}
|
|
+
|
|
/*
|
|
** Returns non-zero if the specified path name starts with a drive letter
|
|
** followed by a colon character.
|
|
@@ -46190,10 +47144,11 @@
|
|
char *zOut;
|
|
#endif
|
|
|
|
- /* If this path name begins with "/X:", where "X" is any alphabetic
|
|
- ** character, discard the initial "/" from the pathname.
|
|
+ /* If this path name begins with "/X:" or "\\?\", where "X" is any
|
|
+ ** alphabetic character, discard the initial "/" from the pathname.
|
|
*/
|
|
- if( zRelative[0]=='/' && winIsDriveLetterAndColon(zRelative+1) ){
|
|
+ if( zRelative[0]=='/' && (winIsDriveLetterAndColon(zRelative+1)
|
|
+ || winIsLongPathPrefix(zRelative+1)) ){
|
|
zRelative++;
|
|
}
|
|
|
|
@@ -46949,7 +47904,7 @@
|
|
}
|
|
newSz *= 2;
|
|
if( newSz>p->szMax ) newSz = p->szMax;
|
|
- pNew = sqlite3_realloc64(p->aData, newSz);
|
|
+ pNew = sqlite3Realloc(p->aData, newSz);
|
|
if( pNew==0 ) return SQLITE_NOMEM;
|
|
p->aData = pNew;
|
|
p->szAlloc = newSz;
|
|
@@ -47396,10 +48351,11 @@
|
|
sqlite3_vfs *pLower = sqlite3_vfs_find(0);
|
|
int sz = pLower->szOsFile;
|
|
memdb_vfs.pAppData = pLower;
|
|
- /* In all known configurations of SQLite, the size of a default
|
|
- ** sqlite3_file is greater than the size of a memdb sqlite3_file.
|
|
- ** Should that ever change, remove the following NEVER() */
|
|
- if( NEVER(sz<sizeof(MemFile)) ) sz = sizeof(MemFile);
|
|
+ /* The following conditional can only be true when compiled for
|
|
+ ** Windows x86 and SQLITE_MAX_MMAP_SIZE=0. We always leave
|
|
+ ** it in, to be safe, but it is marked as NO_TEST since there
|
|
+ ** is no way to reach it under most builds. */
|
|
+ if( sz<sizeof(MemFile) ) sz = sizeof(MemFile); /*NO_TEST*/
|
|
memdb_vfs.szOsFile = sz;
|
|
return sqlite3_vfs_register(&memdb_vfs, 0);
|
|
}
|
|
@@ -48085,6 +49041,7 @@
|
|
** built-in default page cache is used instead of the application defined
|
|
** page cache. */
|
|
sqlite3PCacheSetDefault();
|
|
+ assert( sqlite3GlobalConfig.pcache2.xInit!=0 );
|
|
}
|
|
return sqlite3GlobalConfig.pcache2.xInit(sqlite3GlobalConfig.pcache2.pArg);
|
|
}
|
|
@@ -49131,6 +50088,7 @@
|
|
|
|
assert( sqlite3_mutex_held(pCache->pGroup->mutex) );
|
|
if( pCache->pFree || (pCache->nPage==0 && pcache1InitBulk(pCache)) ){
|
|
+ assert( pCache->pFree!=0 );
|
|
p = pCache->pFree;
|
|
pCache->pFree = p->pNext;
|
|
p->pNext = 0;
|
|
@@ -49154,13 +50112,15 @@
|
|
}
|
|
#else
|
|
pPg = pcache1Alloc(pCache->szAlloc);
|
|
- p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
|
#endif
|
|
if( benignMalloc ){ sqlite3EndBenignMalloc(); }
|
|
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
|
|
pcache1EnterMutex(pCache->pGroup);
|
|
#endif
|
|
if( pPg==0 ) return 0;
|
|
+#ifndef SQLITE_PCACHE_SEPARATE_HEADER
|
|
+ p = (PgHdr1 *)&((u8 *)pPg)[pCache->szPage];
|
|
+#endif
|
|
p->page.pBuf = pPg;
|
|
p->page.pExtra = &p[1];
|
|
p->isBulkLocal = 0;
|
|
@@ -50161,7 +51121,7 @@
|
|
/*
|
|
** Allocate a new RowSetEntry object that is associated with the
|
|
** given RowSet. Return a pointer to the new and completely uninitialized
|
|
-** objected.
|
|
+** object.
|
|
**
|
|
** In an OOM situation, the RowSet.db->mallocFailed flag is set and this
|
|
** routine returns NULL.
|
|
@@ -50437,7 +51397,7 @@
|
|
if( p ){
|
|
struct RowSetEntry **ppPrevTree = &pRowSet->pForest;
|
|
if( (pRowSet->rsFlags & ROWSET_SORTED)==0 ){ /*OPTIMIZATION-IF-FALSE*/
|
|
- /* Only sort the current set of entiries if they need it */
|
|
+ /* Only sort the current set of entries if they need it */
|
|
p = rowSetEntrySort(p);
|
|
}
|
|
for(pTree = pRowSet->pForest; pTree; pTree=pTree->pRight){
|
|
@@ -50659,6 +51619,11 @@
|
|
/* Return the sqlite3_file object for the WAL file */
|
|
SQLITE_PRIVATE sqlite3_file *sqlite3WalFile(Wal *pWal);
|
|
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock);
|
|
+SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db);
|
|
+#endif
|
|
+
|
|
#endif /* ifndef SQLITE_OMIT_WAL */
|
|
#endif /* SQLITE_WAL_H */
|
|
|
|
@@ -51049,20 +52014,6 @@
|
|
*/
|
|
#define UNKNOWN_LOCK (EXCLUSIVE_LOCK+1)
|
|
|
|
-/*
|
|
-** A macro used for invoking the codec if there is one
|
|
-*/
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-# define CODEC1(P,D,N,X,E) \
|
|
- if( P->xCodec && P->xCodec(P->pCodec,D,N,X)==0 ){ E; }
|
|
-# define CODEC2(P,D,N,X,E,O) \
|
|
- if( P->xCodec==0 ){ O=(char*)D; }else \
|
|
- if( (O=(char*)(P->xCodec(P->pCodec,D,N,X)))==0 ){ E; }
|
|
-#else
|
|
-# define CODEC1(P,D,N,X,E) /* NO-OP */
|
|
-# define CODEC2(P,D,N,X,E,O) O=(char*)D
|
|
-#endif
|
|
-
|
|
/*
|
|
** The maximum allowed sector size. 64KiB. If the xSectorsize() method
|
|
** returns a value larger than this, then MAX_SECTOR_SIZE is used instead.
|
|
@@ -51348,12 +52299,6 @@
|
|
#endif
|
|
void (*xReiniter)(DbPage*); /* Call this routine when reloading pages */
|
|
int (*xGet)(Pager*,Pgno,DbPage**,int); /* Routine to fetch a patch */
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- void *(*xCodec)(void*,void*,Pgno,int); /* Routine for en/decoding data */
|
|
- void (*xCodecSizeChng)(void*,int,int); /* Notify of page size changes */
|
|
- void (*xCodecFree)(void*); /* Destructor for the codec */
|
|
- void *pCodec; /* First argument to xCodec... methods */
|
|
-#endif
|
|
char *pTmpSpace; /* Pager.pageSize bytes of space for tmp use */
|
|
PCache *pPCache; /* Pointer to page cache object */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
@@ -51480,9 +52425,6 @@
|
|
SQLITE_PRIVATE int sqlite3PagerDirectReadOk(Pager *pPager, Pgno pgno){
|
|
if( pPager->fd->pMethods==0 ) return 0;
|
|
if( sqlite3PCacheIsDirty(pPager->pPCache) ) return 0;
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( pPager->xCodec!=0 ) return 0;
|
|
-#endif
|
|
#ifndef SQLITE_OMIT_WAL
|
|
if( pPager->pWal ){
|
|
u32 iRead = 0;
|
|
@@ -51716,11 +52658,7 @@
|
|
if( pPager->errCode ){
|
|
pPager->xGet = getPageError;
|
|
#if SQLITE_MAX_MMAP_SIZE>0
|
|
- }else if( USEFETCH(pPager)
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- && pPager->xCodec==0
|
|
-#endif
|
|
- ){
|
|
+ }else if( USEFETCH(pPager) ){
|
|
pPager->xGet = getPageMMap;
|
|
#endif /* SQLITE_MAX_MMAP_SIZE>0 */
|
|
}else{
|
|
@@ -51815,6 +52753,7 @@
|
|
}
|
|
IOTRACE(("UNLOCK %p %d\n", pPager, eLock))
|
|
}
|
|
+ pPager->changeCountDone = pPager->tempFile; /* ticket fb3b3024ea238d5c */
|
|
return rc;
|
|
}
|
|
|
|
@@ -52002,6 +52941,7 @@
|
|
len = 0;
|
|
}
|
|
zMaster[len] = '\0';
|
|
+ zMaster[len+1] = '\0';
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -52535,7 +53475,6 @@
|
|
** code is cleared and the cache reset in the block below.
|
|
*/
|
|
assert( pPager->errCode || pPager->eState!=PAGER_ERROR );
|
|
- pPager->changeCountDone = 0;
|
|
pPager->eState = PAGER_OPEN;
|
|
}
|
|
|
|
@@ -52799,7 +53738,6 @@
|
|
&& (!pagerUseWal(pPager) || sqlite3WalExclusiveMode(pPager->pWal, 0))
|
|
){
|
|
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
|
|
- pPager->changeCountDone = 0;
|
|
}
|
|
pPager->eState = PAGER_READER;
|
|
pPager->setMaster = 0;
|
|
@@ -52868,35 +53806,6 @@
|
|
return cksum;
|
|
}
|
|
|
|
-/*
|
|
-** Report the current page size and number of reserved bytes back
|
|
-** to the codec.
|
|
-*/
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-static void pagerReportSize(Pager *pPager){
|
|
- if( pPager->xCodecSizeChng ){
|
|
- pPager->xCodecSizeChng(pPager->pCodec, pPager->pageSize,
|
|
- (int)pPager->nReserve);
|
|
- }
|
|
-}
|
|
-#else
|
|
-# define pagerReportSize(X) /* No-op if we do not support a codec */
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-/*
|
|
-** Make sure the number of reserved bits is the same in the destination
|
|
-** pager as it is in the source. This comes up when a VACUUM changes the
|
|
-** number of reserved bits to the "optimal" amount.
|
|
-*/
|
|
-SQLITE_PRIVATE void sqlite3PagerAlignReserve(Pager *pDest, Pager *pSrc){
|
|
- if( pDest->nReserve!=pSrc->nReserve ){
|
|
- pDest->nReserve = pSrc->nReserve;
|
|
- pagerReportSize(pDest);
|
|
- }
|
|
-}
|
|
-#endif
|
|
-
|
|
/*
|
|
** Read a single page from either the journal file (if isMainJrnl==1) or
|
|
** from the sub-journal (if isMainJrnl==0) and playback that page.
|
|
@@ -52948,11 +53857,6 @@
|
|
char *aData; /* Temporary storage for the page */
|
|
sqlite3_file *jfd; /* The file descriptor for the journal file */
|
|
int isSynced; /* True if journal page is synced */
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- /* The jrnlEnc flag is true if Journal pages should be passed through
|
|
- ** the codec. It is false for pure in-memory journals. */
|
|
- const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
|
|
-#endif
|
|
|
|
assert( (isMainJrnl&~1)==0 ); /* isMainJrnl is 0 or 1 */
|
|
assert( (isSavepnt&~1)==0 ); /* isSavepnt is 0 or 1 */
|
|
@@ -53015,7 +53919,6 @@
|
|
*/
|
|
if( pgno==1 && pPager->nReserve!=((u8*)aData)[20] ){
|
|
pPager->nReserve = ((u8*)aData)[20];
|
|
- pagerReportSize(pPager);
|
|
}
|
|
|
|
/* If the pager is in CACHEMOD state, then there must be a copy of this
|
|
@@ -53083,26 +53986,12 @@
|
|
** is if the data was just read from an in-memory sub-journal. In that
|
|
** case it must be encrypted here before it is copied into the database
|
|
** file. */
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( !jrnlEnc ){
|
|
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
|
|
- rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
|
|
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
|
|
- }else
|
|
-#endif
|
|
rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
|
|
|
|
if( pgno>pPager->dbFileSize ){
|
|
pPager->dbFileSize = pgno;
|
|
}
|
|
if( pPager->pBackup ){
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( jrnlEnc ){
|
|
- CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
|
|
- sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
|
|
- CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
|
|
- }else
|
|
-#endif
|
|
sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
|
|
}
|
|
}else if( !isMainJrnl && pPg==0 ){
|
|
@@ -53153,11 +54042,6 @@
|
|
if( pgno==1 ){
|
|
memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
|
|
}
|
|
-
|
|
- /* Decode the page just read from disk */
|
|
-#if SQLITE_HAS_CODEC
|
|
- if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
|
|
-#endif
|
|
sqlite3PcacheRelease(pPg);
|
|
}
|
|
return rc;
|
|
@@ -53238,15 +54122,16 @@
|
|
rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
|
|
if( rc!=SQLITE_OK ) goto delmaster_out;
|
|
nMasterPtr = pVfs->mxPathname+1;
|
|
- zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 1);
|
|
+ zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 2);
|
|
if( !zMasterJournal ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
goto delmaster_out;
|
|
}
|
|
- zMasterPtr = &zMasterJournal[nMasterJournal+1];
|
|
+ zMasterPtr = &zMasterJournal[nMasterJournal+2];
|
|
rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
|
|
if( rc!=SQLITE_OK ) goto delmaster_out;
|
|
zMasterJournal[nMasterJournal] = 0;
|
|
+ zMasterJournal[nMasterJournal+1] = 0;
|
|
|
|
zJournal = zMasterJournal;
|
|
while( (zJournal-zMasterJournal)<nMasterJournal ){
|
|
@@ -53259,9 +54144,12 @@
|
|
/* One of the journals pointed to by the master journal exists.
|
|
** Open it and check if it points at the master journal. If
|
|
** so, return without deleting the master journal file.
|
|
+ ** NB: zJournal is really a MAIN_JOURNAL. But call it a
|
|
+ ** MASTER_JOURNAL here so that the VFS will not send the zJournal
|
|
+ ** name into sqlite3_database_file_object().
|
|
*/
|
|
int c;
|
|
- int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MAIN_JOURNAL);
|
|
+ int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
|
|
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
|
|
if( rc!=SQLITE_OK ){
|
|
goto delmaster_out;
|
|
@@ -53716,8 +54604,6 @@
|
|
memcpy(&pPager->dbFileVers, dbFileVers, sizeof(pPager->dbFileVers));
|
|
}
|
|
}
|
|
- CODEC1(pPager, pPg->pData, pPg->pgno, 3, rc = SQLITE_NOMEM_BKPT);
|
|
-
|
|
PAGER_INCR(sqlite3_pager_readdb_count);
|
|
PAGER_INCR(pPager->nRead);
|
|
IOTRACE(("PGIN %p %d\n", pPager, pPg->pgno));
|
|
@@ -54461,7 +55347,6 @@
|
|
if( nReserve<0 ) nReserve = pPager->nReserve;
|
|
assert( nReserve>=0 && nReserve<1000 );
|
|
pPager->nReserve = (i16)nReserve;
|
|
- pagerReportSize(pPager);
|
|
pagerFixMaplimit(pPager);
|
|
}
|
|
return rc;
|
|
@@ -54857,11 +55742,6 @@
|
|
sqlite3OsClose(pPager->fd);
|
|
sqlite3PageFree(pTmp);
|
|
sqlite3PcacheClose(pPager->pPCache);
|
|
-
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( pPager->xCodecFree ) pPager->xCodecFree(pPager->pCodec);
|
|
-#endif
|
|
-
|
|
assert( !pPager->aSavepoint && !pPager->pInJournal );
|
|
assert( !isOpen(pPager->jfd) && !isOpen(pPager->sjfd) );
|
|
|
|
@@ -55112,8 +55992,7 @@
|
|
assert( (pList->flags&PGHDR_NEED_SYNC)==0 );
|
|
if( pList->pgno==1 ) pager_write_changecounter(pList);
|
|
|
|
- /* Encode the database */
|
|
- CODEC2(pPager, pList->pData, pgno, 6, return SQLITE_NOMEM_BKPT, pData);
|
|
+ pData = pList->pData;
|
|
|
|
/* Write out the page data. */
|
|
rc = sqlite3OsWrite(pPager->fd, pData, pPager->pageSize, offset);
|
|
@@ -55202,12 +56081,6 @@
|
|
void *pData = pPg->pData;
|
|
i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
|
|
char *pData2;
|
|
-
|
|
-#if SQLITE_HAS_CODEC
|
|
- if( !pPager->subjInMemory ){
|
|
- CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
|
|
- }else
|
|
-#endif
|
|
pData2 = pData;
|
|
PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
|
|
rc = write32bits(pPager->sjfd, offset, pPg->pgno);
|
|
@@ -55403,7 +56276,8 @@
|
|
int pcacheSize = sqlite3PcacheSize(); /* Bytes to allocate for PCache */
|
|
u32 szPageDflt = SQLITE_DEFAULT_PAGE_SIZE; /* Default page size */
|
|
const char *zUri = 0; /* URI args to copy */
|
|
- int nUri = 0; /* Number of bytes of URI args at *zUri */
|
|
+ int nUriByte = 1; /* Number of bytes of URI args at *zUri */
|
|
+ int nUri = 0; /* Number of URI parameters */
|
|
|
|
/* Figure out how much space is required for each journal file-handle
|
|
** (there are two of them, the main journal and the sub-journal). */
|
|
@@ -55437,14 +56311,24 @@
|
|
}
|
|
zPathname[0] = 0; /* Make sure initialized even if FullPathname() fails */
|
|
rc = sqlite3OsFullPathname(pVfs, zFilename, nPathname, zPathname);
|
|
+ if( rc!=SQLITE_OK ){
|
|
+ if( rc==SQLITE_OK_SYMLINK ){
|
|
+ if( vfsFlags & SQLITE_OPEN_NOFOLLOW ){
|
|
+ rc = SQLITE_CANTOPEN_SYMLINK;
|
|
+ }else{
|
|
+ rc = SQLITE_OK;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
nPathname = sqlite3Strlen30(zPathname);
|
|
z = zUri = &zFilename[sqlite3Strlen30(zFilename)+1];
|
|
while( *z ){
|
|
- z += sqlite3Strlen30(z)+1;
|
|
- z += sqlite3Strlen30(z)+1;
|
|
+ z += strlen(z)+1;
|
|
+ z += strlen(z)+1;
|
|
+ nUri++;
|
|
}
|
|
- nUri = (int)(&z[1] - zUri);
|
|
- assert( nUri>=0 );
|
|
+ nUriByte = (int)(&z[1] - zUri);
|
|
+ assert( nUriByte>=1 );
|
|
if( rc==SQLITE_OK && nPathname+8>pVfs->mxPathname ){
|
|
/* This branch is taken when the journal path required by
|
|
** the database being opened will be more than pVfs->mxPathname
|
|
@@ -55469,50 +56353,111 @@
|
|
** Database file handle (pVfs->szOsFile bytes)
|
|
** Sub-journal file handle (journalFileSize bytes)
|
|
** Main journal file handle (journalFileSize bytes)
|
|
+ ** Ptr back to the Pager (sizeof(Pager*) bytes)
|
|
+ ** \0\0\0\0 database prefix (4 bytes)
|
|
** Database file name (nPathname+1 bytes)
|
|
- ** Journal file name (nPathname+8+1 bytes)
|
|
+ ** URI query parameters (nUriByte bytes)
|
|
+ ** Journal filename (nPathname+8+1 bytes)
|
|
+ ** WAL filename (nPathname+4+1 bytes)
|
|
+ ** \0\0\0 terminator (3 bytes)
|
|
+ **
|
|
+ ** Some 3rd-party software, over which we have no control, depends on
|
|
+ ** the specific order of the filenames and the \0 separators between them
|
|
+ ** so that it can (for example) find the database filename given the WAL
|
|
+ ** filename without using the sqlite3_filename_database() API. This is a
|
|
+ ** misuse of SQLite and a bug in the 3rd-party software, but the 3rd-party
|
|
+ ** software is in widespread use, so we try to avoid changing the filename
|
|
+ ** order and formatting if possible. In particular, the details of the
|
|
+ ** filename format expected by 3rd-party software should be as follows:
|
|
+ **
|
|
+ ** - Main Database Path
|
|
+ ** - \0
|
|
+ ** - Multiple URI components consisting of:
|
|
+ ** - Key
|
|
+ ** - \0
|
|
+ ** - Value
|
|
+ ** - \0
|
|
+ ** - \0
|
|
+ ** - Journal Path
|
|
+ ** - \0
|
|
+ ** - WAL Path (zWALName)
|
|
+ ** - \0
|
|
+ **
|
|
+ ** The sqlite3_create_filename() interface and the databaseFilename() utility
|
|
+ ** that is used by sqlite3_filename_database() and kin also depend on the
|
|
+ ** specific formatting and order of the various filenames, so if the format
|
|
+ ** changes here, be sure to change it there as well.
|
|
*/
|
|
pPtr = (u8 *)sqlite3MallocZero(
|
|
- ROUND8(sizeof(*pPager)) + /* Pager structure */
|
|
- ROUND8(pcacheSize) + /* PCache object */
|
|
- ROUND8(pVfs->szOsFile) + /* The main db file */
|
|
- journalFileSize * 2 + /* The two journal files */
|
|
- nPathname + 1 + nUri + /* zFilename */
|
|
- nPathname + 8 + 2 /* zJournal */
|
|
+ ROUND8(sizeof(*pPager)) + /* Pager structure */
|
|
+ ROUND8(pcacheSize) + /* PCache object */
|
|
+ ROUND8(pVfs->szOsFile) + /* The main db file */
|
|
+ journalFileSize * 2 + /* The two journal files */
|
|
+ sizeof(pPager) + /* Space to hold a pointer */
|
|
+ 4 + /* Database prefix */
|
|
+ nPathname + 1 + /* database filename */
|
|
+ nUriByte + /* query parameters */
|
|
+ nPathname + 8 + 1 + /* Journal filename */
|
|
#ifndef SQLITE_OMIT_WAL
|
|
- + nPathname + 4 + 2 /* zWal */
|
|
+ nPathname + 4 + 1 + /* WAL filename */
|
|
#endif
|
|
+ 3 /* Terminator */
|
|
);
|
|
assert( EIGHT_BYTE_ALIGNMENT(SQLITE_INT_TO_PTR(journalFileSize)) );
|
|
if( !pPtr ){
|
|
sqlite3DbFree(0, zPathname);
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
- pPager = (Pager*)(pPtr);
|
|
- pPager->pPCache = (PCache*)(pPtr += ROUND8(sizeof(*pPager)));
|
|
- pPager->fd = (sqlite3_file*)(pPtr += ROUND8(pcacheSize));
|
|
- pPager->sjfd = (sqlite3_file*)(pPtr += ROUND8(pVfs->szOsFile));
|
|
- pPager->jfd = (sqlite3_file*)(pPtr += journalFileSize);
|
|
- pPager->zFilename = (char*)(pPtr += journalFileSize);
|
|
+ pPager = (Pager*)pPtr; pPtr += ROUND8(sizeof(*pPager));
|
|
+ pPager->pPCache = (PCache*)pPtr; pPtr += ROUND8(pcacheSize);
|
|
+ pPager->fd = (sqlite3_file*)pPtr; pPtr += ROUND8(pVfs->szOsFile);
|
|
+ pPager->sjfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
|
|
+ pPager->jfd = (sqlite3_file*)pPtr; pPtr += journalFileSize;
|
|
assert( EIGHT_BYTE_ALIGNMENT(pPager->jfd) );
|
|
+ memcpy(pPtr, &pPager, sizeof(pPager)); pPtr += sizeof(pPager);
|
|
+
|
|
+ /* Fill in the Pager.zFilename and pPager.zQueryParam fields */
|
|
+ pPtr += 4; /* Skip zero prefix */
|
|
+ pPager->zFilename = (char*)pPtr;
|
|
+ if( nPathname>0 ){
|
|
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname + 1;
|
|
+ if( zUri ){
|
|
+ memcpy(pPtr, zUri, nUriByte); pPtr += nUriByte;
|
|
+ }else{
|
|
+ pPtr++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
+ /* Fill in Pager.zJournal */
|
|
+ if( nPathname>0 ){
|
|
+ pPager->zJournal = (char*)pPtr;
|
|
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
|
|
+ memcpy(pPtr, "-journal",8); pPtr += 8 + 1;
|
|
+#ifdef SQLITE_ENABLE_8_3_NAMES
|
|
+ sqlite3FileSuffix3(zFilename,pPager->zJournal);
|
|
+ pPtr = (u8*)(pPager->zJournal + sqlite3Strlen30(pPager->zJournal)+1);
|
|
+#endif
|
|
+ }else{
|
|
+ pPager->zJournal = 0;
|
|
+ }
|
|
|
|
- /* Fill in the Pager.zFilename and Pager.zJournal buffers, if required. */
|
|
- if( zPathname ){
|
|
- assert( nPathname>0 );
|
|
- pPager->zJournal = (char*)(pPtr += nPathname + 1 + nUri);
|
|
- memcpy(pPager->zFilename, zPathname, nPathname);
|
|
- if( nUri ) memcpy(&pPager->zFilename[nPathname+1], zUri, nUri);
|
|
- memcpy(pPager->zJournal, zPathname, nPathname);
|
|
- memcpy(&pPager->zJournal[nPathname], "-journal\000", 8+2);
|
|
- sqlite3FileSuffix3(pPager->zFilename, pPager->zJournal);
|
|
#ifndef SQLITE_OMIT_WAL
|
|
- pPager->zWal = &pPager->zJournal[nPathname+8+1];
|
|
- memcpy(pPager->zWal, zPathname, nPathname);
|
|
- memcpy(&pPager->zWal[nPathname], "-wal\000", 4+1);
|
|
- sqlite3FileSuffix3(pPager->zFilename, pPager->zWal);
|
|
+ /* Fill in Pager.zWal */
|
|
+ if( nPathname>0 ){
|
|
+ pPager->zWal = (char*)pPtr;
|
|
+ memcpy(pPtr, zPathname, nPathname); pPtr += nPathname;
|
|
+ memcpy(pPtr, "-wal", 4); pPtr += 4 + 1;
|
|
+#ifdef SQLITE_ENABLE_8_3_NAMES
|
|
+ sqlite3FileSuffix3(zFilename, pPager->zWal);
|
|
+ pPtr = (u8*)(pPager->zWal + sqlite3Strlen30(pPager->zWal)+1);
|
|
#endif
|
|
- sqlite3DbFree(0, zPathname);
|
|
+ }else{
|
|
+ pPager->zWal = 0;
|
|
}
|
|
+#endif
|
|
+
|
|
+ if( nPathname ) sqlite3DbFree(0, zPathname);
|
|
pPager->pVfs = pVfs;
|
|
pPager->vfsFlags = vfsFlags;
|
|
|
|
@@ -55561,9 +56506,9 @@
|
|
}
|
|
#endif
|
|
}
|
|
- pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
|
|
+ pPager->noLock = sqlite3_uri_boolean(pPager->zFilename, "nolock", 0);
|
|
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
|
|
- || sqlite3_uri_boolean(zFilename, "immutable", 0) ){
|
|
+ || sqlite3_uri_boolean(pPager->zFilename, "immutable", 0) ){
|
|
vfsFlags |= SQLITE_OPEN_READONLY;
|
|
goto act_like_temp_file;
|
|
}
|
|
@@ -55670,6 +56615,19 @@
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
+/*
|
|
+** Return the sqlite3_file for the main database given the name
|
|
+** of the corresonding WAL or Journal name as passed into
|
|
+** xOpen.
|
|
+*/
|
|
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char *zName){
|
|
+ Pager *pPager;
|
|
+ while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
|
|
+ zName--;
|
|
+ }
|
|
+ pPager = *(Pager**)(zName - 4 - sizeof(Pager*));
|
|
+ return pPager->fd;
|
|
+}
|
|
|
|
|
|
/*
|
|
@@ -56225,9 +57183,6 @@
|
|
);
|
|
|
|
assert( USEFETCH(pPager) );
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- assert( pPager->xCodec==0 );
|
|
-#endif
|
|
|
|
/* Optimization note: Adding the "pgno<=1" term before "pgno==0" here
|
|
** allows the compiler optimizer to reuse the results of the "pgno>1"
|
|
@@ -56358,7 +57313,6 @@
|
|
assert( pPg->pgno==1 );
|
|
assert( (pPg->flags & PGHDR_MMAP)==0 ); /* Page1 is never memory mapped */
|
|
pPager = pPg->pPager;
|
|
- sqlite3PagerResetLockTimeout(pPager);
|
|
sqlite3PcacheRelease(pPg);
|
|
pagerUnlockIfUnused(pPager);
|
|
}
|
|
@@ -56556,7 +57510,7 @@
|
|
assert( pPg->pgno!=PAGER_MJ_PGNO(pPager) );
|
|
|
|
assert( pPager->journalHdr<=pPager->journalOff );
|
|
- CODEC2(pPager, pPg->pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
|
|
+ pData2 = pPg->pData;
|
|
cksum = pager_cksum(pPager, (u8*)pData2);
|
|
|
|
/* Even if an IO or diskfull error occurs while journalling the
|
|
@@ -56921,7 +57875,7 @@
|
|
if( DIRECT_MODE ){
|
|
const void *zBuf;
|
|
assert( pPager->dbFileSize>0 );
|
|
- CODEC2(pPager, pPgHdr->pData, 1, 6, rc=SQLITE_NOMEM_BKPT, zBuf);
|
|
+ zBuf = pPgHdr->pData;
|
|
if( rc==SQLITE_OK ){
|
|
rc = sqlite3OsWrite(pPager->fd, zBuf, pPager->pageSize, 0);
|
|
pPager->aStat[PAGER_STAT_WRITE]++;
|
|
@@ -57254,6 +58208,7 @@
|
|
** But if (due to a coding error elsewhere in the system) it does get
|
|
** called, just return the same error code without doing anything. */
|
|
if( NEVER(pPager->errCode) ) return pPager->errCode;
|
|
+ pPager->iDataVersion++;
|
|
|
|
assert( pPager->eState==PAGER_WRITER_LOCKED
|
|
|| pPager->eState==PAGER_WRITER_FINISHED
|
|
@@ -57282,7 +58237,6 @@
|
|
}
|
|
|
|
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
|
|
- pPager->iDataVersion++;
|
|
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
|
|
return pager_error(pPager, rc);
|
|
}
|
|
@@ -57626,9 +58580,13 @@
|
|
** behavior. But when the Btree needs to know the filename for matching to
|
|
** shared cache, it uses nullIfMemDb==0 so that in-memory databases can
|
|
** participate in shared-cache.
|
|
+**
|
|
+** The return value to this routine is always safe to use with
|
|
+** sqlite3_uri_parameter() and sqlite3_filename_database() and friends.
|
|
*/
|
|
-SQLITE_PRIVATE const char *sqlite3PagerFilename(Pager *pPager, int nullIfMemDb){
|
|
- return (nullIfMemDb && pPager->memDb) ? "" : pPager->zFilename;
|
|
+SQLITE_PRIVATE const char *sqlite3PagerFilename(const Pager *pPager, int nullIfMemDb){
|
|
+ static const char zFake[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
|
|
+ return (nullIfMemDb && pPager->memDb) ? &zFake[4] : pPager->zFilename;
|
|
}
|
|
|
|
/*
|
|
@@ -57647,16 +58605,6 @@
|
|
return pPager->fd;
|
|
}
|
|
|
|
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
-/*
|
|
-** Reset the lock timeout for pager.
|
|
-*/
|
|
-SQLITE_PRIVATE void sqlite3PagerResetLockTimeout(Pager *pPager){
|
|
- int x = 0;
|
|
- sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_LOCK_TIMEOUT, &x);
|
|
-}
|
|
-#endif
|
|
-
|
|
/*
|
|
** Return the file handle for the journal file (if it exists).
|
|
** This will be either the rollback journal or the WAL file.
|
|
@@ -57676,54 +58624,6 @@
|
|
return pPager->zJournal;
|
|
}
|
|
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-/*
|
|
-** Set or retrieve the codec for this pager
|
|
-*/
|
|
-SQLITE_PRIVATE void sqlite3PagerSetCodec(
|
|
- Pager *pPager,
|
|
- void *(*xCodec)(void*,void*,Pgno,int),
|
|
- void (*xCodecSizeChng)(void*,int,int),
|
|
- void (*xCodecFree)(void*),
|
|
- void *pCodec
|
|
-){
|
|
- if( pPager->xCodecFree ){
|
|
- pPager->xCodecFree(pPager->pCodec);
|
|
- }else{
|
|
- pager_reset(pPager);
|
|
- }
|
|
- pPager->xCodec = pPager->memDb ? 0 : xCodec;
|
|
- pPager->xCodecSizeChng = xCodecSizeChng;
|
|
- pPager->xCodecFree = xCodecFree;
|
|
- pPager->pCodec = pCodec;
|
|
- setGetterMethod(pPager);
|
|
- pagerReportSize(pPager);
|
|
-}
|
|
-SQLITE_PRIVATE void *sqlite3PagerGetCodec(Pager *pPager){
|
|
- return pPager->pCodec;
|
|
-}
|
|
-
|
|
-/*
|
|
-** This function is called by the wal module when writing page content
|
|
-** into the log file.
|
|
-**
|
|
-** This function returns a pointer to a buffer containing the encrypted
|
|
-** page content. If a malloc fails, this function may return NULL.
|
|
-*/
|
|
-SQLITE_PRIVATE void *sqlite3PagerCodec(PgHdr *pPg){
|
|
- void *aData = 0;
|
|
- CODEC2(pPg->pPager, pPg->pData, pPg->pgno, 6, return 0, aData);
|
|
- return aData;
|
|
-}
|
|
-
|
|
-/*
|
|
-** Return the current pager state
|
|
-*/
|
|
-SQLITE_PRIVATE int sqlite3PagerState(Pager *pPager){
|
|
- return pPager->eState;
|
|
-}
|
|
-#endif /* SQLITE_HAS_CODEC */
|
|
-
|
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
|
/*
|
|
** Move the page pPg to location pgno in the file.
|
|
@@ -58118,7 +59018,6 @@
|
|
pPager->walSyncFlags, pPager->pageSize, (u8 *)pPager->pTmpSpace,
|
|
pnLog, pnCkpt
|
|
);
|
|
- sqlite3PagerResetLockTimeout(pPager);
|
|
}
|
|
return rc;
|
|
}
|
|
@@ -58283,6 +59182,32 @@
|
|
return rc;
|
|
}
|
|
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+/*
|
|
+** If pager pPager is a wal-mode database not in exclusive locking mode,
|
|
+** invoke the sqlite3WalWriteLock() function on the associated Wal object
|
|
+** with the same db and bLock parameters as were passed to this function.
|
|
+** Return an SQLite error code if an error occurs, or SQLITE_OK otherwise.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3PagerWalWriteLock(Pager *pPager, int bLock){
|
|
+ int rc = SQLITE_OK;
|
|
+ if( pagerUseWal(pPager) && pPager->exclusiveMode==0 ){
|
|
+ rc = sqlite3WalWriteLock(pPager->pWal, bLock);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Set the database handle used by the wal layer to determine if
|
|
+** blocking locks are required.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3PagerWalDb(Pager *pPager, sqlite3 *db){
|
|
+ if( pagerUseWal(pPager) ){
|
|
+ sqlite3WalDb(pPager->pWal, db);
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
/*
|
|
** If this is a WAL database, obtain a snapshot handle for the snapshot
|
|
@@ -58301,7 +59226,10 @@
|
|
** read transaction is opened, attempt to read from the snapshot it
|
|
** identifies. If this is not a WAL database, return an error.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(Pager *pPager, sqlite3_snapshot *pSnapshot){
|
|
+SQLITE_PRIVATE int sqlite3PagerSnapshotOpen(
|
|
+ Pager *pPager,
|
|
+ sqlite3_snapshot *pSnapshot
|
|
+){
|
|
int rc = SQLITE_OK;
|
|
if( pPager->pWal ){
|
|
sqlite3WalSnapshotOpen(pPager->pWal, pSnapshot);
|
|
@@ -58637,18 +59565,6 @@
|
|
# define WALTRACE(X)
|
|
#endif
|
|
|
|
-/*
|
|
-** WAL mode depends on atomic aligned 32-bit loads and stores in a few
|
|
-** places. The following macros try to make this explicit.
|
|
-*/
|
|
-#if GCC_VESRION>=5004000
|
|
-# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
|
|
-# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
|
|
-#else
|
|
-# define AtomicLoad(PTR) (*(PTR))
|
|
-# define AtomicStore(PTR,VAL) (*(PTR) = (VAL))
|
|
-#endif
|
|
-
|
|
/*
|
|
** The maximum (and only) versions of the wal and wal-index formats
|
|
** that may be interpreted by this version of SQLite.
|
|
@@ -58858,6 +59774,9 @@
|
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
WalIndexHdr *pSnapshot; /* Start transaction here if not NULL */
|
|
#endif
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ sqlite3 *db;
|
|
+#endif
|
|
};
|
|
|
|
/*
|
|
@@ -58956,7 +59875,7 @@
|
|
if( pWal->nWiData<=iPage ){
|
|
sqlite3_int64 nByte = sizeof(u32*)*(iPage+1);
|
|
volatile u32 **apNew;
|
|
- apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
|
|
+ apNew = (volatile u32 **)sqlite3Realloc((void *)pWal->apWiData, nByte);
|
|
if( !apNew ){
|
|
*ppPage = 0;
|
|
return SQLITE_NOMEM_BKPT;
|
|
@@ -59077,18 +59996,35 @@
|
|
aOut[1] = s2;
|
|
}
|
|
|
|
+/*
|
|
+** If there is the possibility of concurrent access to the SHM file
|
|
+** from multiple threads and/or processes, then do a memory barrier.
|
|
+*/
|
|
static void walShmBarrier(Wal *pWal){
|
|
if( pWal->exclusiveMode!=WAL_HEAPMEMORY_MODE ){
|
|
sqlite3OsShmBarrier(pWal->pDbFd);
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+** Add the SQLITE_NO_TSAN as part of the return-type of a function
|
|
+** definition as a hint that the function contains constructs that
|
|
+** might give false-positive TSAN warnings.
|
|
+**
|
|
+** See tag-20200519-1.
|
|
+*/
|
|
+#if defined(__clang__) && !defined(SQLITE_NO_TSAN)
|
|
+# define SQLITE_NO_TSAN __attribute__((no_sanitize_thread))
|
|
+#else
|
|
+# define SQLITE_NO_TSAN
|
|
+#endif
|
|
+
|
|
/*
|
|
** Write the header information in pWal->hdr into the wal-index.
|
|
**
|
|
** The checksum on pWal->hdr is updated before it is written.
|
|
*/
|
|
-static void walIndexWriteHdr(Wal *pWal){
|
|
+static SQLITE_NO_TSAN void walIndexWriteHdr(Wal *pWal){
|
|
volatile WalIndexHdr *aHdr = walIndexHdr(pWal);
|
|
const int nCksum = offsetof(WalIndexHdr, aCksum);
|
|
|
|
@@ -59096,6 +60032,7 @@
|
|
pWal->hdr.isInit = 1;
|
|
pWal->hdr.iVersion = WALINDEX_MAX_VERSION;
|
|
walChecksumBytes(1, (u8*)&pWal->hdr, nCksum, 0, pWal->hdr.aCksum);
|
|
+ /* Possible TSAN false-positive. See tag-20200519-1 */
|
|
memcpy((void*)&aHdr[1], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
|
|
walShmBarrier(pWal);
|
|
memcpy((void*)&aHdr[0], (const void*)&pWal->hdr, sizeof(WalIndexHdr));
|
|
@@ -59231,7 +60168,7 @@
|
|
SQLITE_SHM_LOCK | SQLITE_SHM_SHARED);
|
|
WALTRACE(("WAL%p: acquire SHARED-%s %s\n", pWal,
|
|
walLockName(lockIdx), rc ? "failed" : "ok"));
|
|
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
|
|
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
|
|
return rc;
|
|
}
|
|
static void walUnlockShared(Wal *pWal, int lockIdx){
|
|
@@ -59247,7 +60184,7 @@
|
|
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
|
|
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
|
|
walLockName(lockIdx), n, rc ? "failed" : "ok"));
|
|
- VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && rc!=SQLITE_BUSY); )
|
|
+ VVA_ONLY( pWal->lockError = (u8)(rc!=SQLITE_OK && (rc&0xFF)!=SQLITE_BUSY); )
|
|
return rc;
|
|
}
|
|
static void walUnlockExclusive(Wal *pWal, int lockIdx, int n){
|
|
@@ -60067,6 +61004,89 @@
|
|
return rc;
|
|
}
|
|
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+/*
|
|
+** Attempt to enable blocking locks. Blocking locks are enabled only if (a)
|
|
+** they are supported by the VFS, and (b) the database handle is configured
|
|
+** with a busy-timeout. Return 1 if blocking locks are successfully enabled,
|
|
+** or 0 otherwise.
|
|
+*/
|
|
+static int walEnableBlocking(Wal *pWal){
|
|
+ int res = 0;
|
|
+ if( pWal->db ){
|
|
+ int tmout = pWal->db->busyTimeout;
|
|
+ if( tmout ){
|
|
+ int rc;
|
|
+ rc = sqlite3OsFileControl(
|
|
+ pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout
|
|
+ );
|
|
+ res = (rc==SQLITE_OK);
|
|
+ }
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Disable blocking locks.
|
|
+*/
|
|
+static void walDisableBlocking(Wal *pWal){
|
|
+ int tmout = 0;
|
|
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_LOCK_TIMEOUT, (void*)&tmout);
|
|
+}
|
|
+
|
|
+/*
|
|
+** If parameter bLock is true, attempt to enable blocking locks, take
|
|
+** the WRITER lock, and then disable blocking locks. If blocking locks
|
|
+** cannot be enabled, no attempt to obtain the WRITER lock is made. Return
|
|
+** an SQLite error code if an error occurs, or SQLITE_OK otherwise. It is not
|
|
+** an error if blocking locks can not be enabled.
|
|
+**
|
|
+** If the bLock parameter is false and the WRITER lock is held, release it.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3WalWriteLock(Wal *pWal, int bLock){
|
|
+ int rc = SQLITE_OK;
|
|
+ assert( pWal->readLock<0 || bLock==0 );
|
|
+ if( bLock ){
|
|
+ assert( pWal->db );
|
|
+ if( walEnableBlocking(pWal) ){
|
|
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ pWal->writeLock = 1;
|
|
+ }
|
|
+ walDisableBlocking(pWal);
|
|
+ }
|
|
+ }else if( pWal->writeLock ){
|
|
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
|
+ pWal->writeLock = 0;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Set the database handle used to determine if blocking locks are required.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3WalDb(Wal *pWal, sqlite3 *db){
|
|
+ pWal->db = db;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Take an exclusive WRITE lock. Blocking if so configured.
|
|
+*/
|
|
+static int walLockWriter(Wal *pWal){
|
|
+ int rc;
|
|
+ walEnableBlocking(pWal);
|
|
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
|
+ walDisableBlocking(pWal);
|
|
+ return rc;
|
|
+}
|
|
+#else
|
|
+# define walEnableBlocking(x) 0
|
|
+# define walDisableBlocking(x)
|
|
+# define walLockWriter(pWal) walLockExclusive((pWal), WAL_WRITE_LOCK, 1)
|
|
+# define sqlite3WalDb(pWal, db)
|
|
+#endif /* ifdef SQLITE_ENABLE_SETLK_TIMEOUT */
|
|
+
|
|
+
|
|
/*
|
|
** Attempt to obtain the exclusive WAL lock defined by parameters lockIdx and
|
|
** n. If the attempt fails and parameter xBusy is not NULL, then it is a
|
|
@@ -60084,6 +61104,12 @@
|
|
do {
|
|
rc = walLockExclusive(pWal, lockIdx, n);
|
|
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ if( rc==SQLITE_BUSY_TIMEOUT ){
|
|
+ walDisableBlocking(pWal);
|
|
+ rc = SQLITE_BUSY;
|
|
+ }
|
|
+#endif
|
|
return rc;
|
|
}
|
|
|
|
@@ -60121,7 +61147,7 @@
|
|
sqlite3Put4byte((u8*)&aSalt[0], 1 + sqlite3Get4byte((u8*)&aSalt[0]));
|
|
memcpy(&pWal->hdr.aSalt[1], &salt1, 4);
|
|
walIndexWriteHdr(pWal);
|
|
- pInfo->nBackfill = 0;
|
|
+ AtomicStore(&pInfo->nBackfill, 0);
|
|
pInfo->nBackfillAttempted = 0;
|
|
pInfo->aReadMark[1] = 0;
|
|
for(i=2; i<WAL_NREADER; i++) pInfo->aReadMark[i] = READMARK_NOT_USED;
|
|
@@ -60196,20 +61222,13 @@
|
|
mxSafeFrame = pWal->hdr.mxFrame;
|
|
mxPage = pWal->hdr.nPage;
|
|
for(i=1; i<WAL_NREADER; i++){
|
|
- /* Thread-sanitizer reports that the following is an unsafe read,
|
|
- ** as some other thread may be in the process of updating the value
|
|
- ** of the aReadMark[] slot. The assumption here is that if that is
|
|
- ** happening, the other client may only be increasing the value,
|
|
- ** not decreasing it. So assuming either that either the "old" or
|
|
- ** "new" version of the value is read, and not some arbitrary value
|
|
- ** that would never be written by a real client, things are still
|
|
- ** safe. */
|
|
- u32 y = pInfo->aReadMark[i];
|
|
+ u32 y = AtomicLoad(pInfo->aReadMark+i);
|
|
if( mxSafeFrame>y ){
|
|
assert( y<=pWal->hdr.mxFrame );
|
|
rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(i), 1);
|
|
if( rc==SQLITE_OK ){
|
|
- pInfo->aReadMark[i] = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
|
|
+ u32 iMark = (i==1 ? mxSafeFrame : READMARK_NOT_USED);
|
|
+ AtomicStore(pInfo->aReadMark+i, iMark);
|
|
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
|
}else if( rc==SQLITE_BUSY ){
|
|
mxSafeFrame = y;
|
|
@@ -60227,7 +61246,7 @@
|
|
}
|
|
|
|
if( pIter
|
|
- && (rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_READ_LOCK(0),1))==SQLITE_OK
|
|
+ && (rc = walBusyLock(pWal,xBusy,pBusyArg,WAL_READ_LOCK(0),1))==SQLITE_OK
|
|
){
|
|
u32 nBackfill = pInfo->nBackfill;
|
|
|
|
@@ -60242,6 +61261,7 @@
|
|
if( rc==SQLITE_OK ){
|
|
i64 nReq = ((i64)mxPage * szPage);
|
|
i64 nSize; /* Current size of database file */
|
|
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_START, 0);
|
|
rc = sqlite3OsFileSize(pWal->pDbFd, &nSize);
|
|
if( rc==SQLITE_OK && nSize<nReq ){
|
|
sqlite3OsFileControlHint(pWal->pDbFd, SQLITE_FCNTL_SIZE_HINT, &nReq);
|
|
@@ -60253,7 +61273,7 @@
|
|
while( rc==SQLITE_OK && 0==walIteratorNext(pIter, &iDbpage, &iFrame) ){
|
|
i64 iOffset;
|
|
assert( walFramePgno(pWal, iFrame)==iDbpage );
|
|
- if( db->u1.isInterrupted ){
|
|
+ if( AtomicLoad(&db->u1.isInterrupted) ){
|
|
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
|
break;
|
|
}
|
|
@@ -60269,6 +61289,7 @@
|
|
rc = sqlite3OsWrite(pWal->pDbFd, zBuf, szPage, iOffset);
|
|
if( rc!=SQLITE_OK ) break;
|
|
}
|
|
+ sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_CKPT_DONE, 0);
|
|
|
|
/* If work was actually accomplished... */
|
|
if( rc==SQLITE_OK ){
|
|
@@ -60281,7 +61302,7 @@
|
|
}
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
- pInfo->nBackfill = mxSafeFrame;
|
|
+ AtomicStore(&pInfo->nBackfill, mxSafeFrame);
|
|
}
|
|
}
|
|
|
|
@@ -60440,7 +61461,7 @@
|
|
** If the checksum cannot be verified return non-zero. If the header
|
|
** is read successfully and the checksum verified, return zero.
|
|
*/
|
|
-static int walIndexTryHdr(Wal *pWal, int *pChanged){
|
|
+static SQLITE_NO_TSAN int walIndexTryHdr(Wal *pWal, int *pChanged){
|
|
u32 aCksum[2]; /* Checksum on the header content */
|
|
WalIndexHdr h1, h2; /* Two copies of the header content */
|
|
WalIndexHdr volatile *aHdr; /* Header in shared memory */
|
|
@@ -60453,13 +61474,19 @@
|
|
** meaning it is possible that an inconsistent snapshot is read
|
|
** from the file. If this happens, return non-zero.
|
|
**
|
|
+ ** tag-20200519-1:
|
|
** There are two copies of the header at the beginning of the wal-index.
|
|
** When reading, read [0] first then [1]. Writes are in the reverse order.
|
|
** Memory barriers are used to prevent the compiler or the hardware from
|
|
- ** reordering the reads and writes.
|
|
+ ** reordering the reads and writes. TSAN and similar tools can sometimes
|
|
+ ** give false-positive warnings about these accesses because the tools do not
|
|
+ ** account for the double-read and the memory barrier. The use of mutexes
|
|
+ ** here would be problematic as the memory being accessed is potentially
|
|
+ ** shared among multiple processes and not all mutex implementions work
|
|
+ ** reliably in that environment.
|
|
*/
|
|
aHdr = walIndexHdr(pWal);
|
|
- memcpy(&h1, (void *)&aHdr[0], sizeof(h1));
|
|
+ memcpy(&h1, (void *)&aHdr[0], sizeof(h1)); /* Possible TSAN false-positive */
|
|
walShmBarrier(pWal);
|
|
memcpy(&h2, (void *)&aHdr[1], sizeof(h2));
|
|
|
|
@@ -60549,28 +61576,32 @@
|
|
/* If the first attempt failed, it might have been due to a race
|
|
** with a writer. So get a WRITE lock and try again.
|
|
*/
|
|
- assert( badHdr==0 || pWal->writeLock==0 );
|
|
if( badHdr ){
|
|
if( pWal->bShmUnreliable==0 && (pWal->readOnly & WAL_SHM_RDONLY) ){
|
|
if( SQLITE_OK==(rc = walLockShared(pWal, WAL_WRITE_LOCK)) ){
|
|
walUnlockShared(pWal, WAL_WRITE_LOCK);
|
|
rc = SQLITE_READONLY_RECOVERY;
|
|
}
|
|
- }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
|
|
- pWal->writeLock = 1;
|
|
- if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
|
|
- badHdr = walIndexTryHdr(pWal, pChanged);
|
|
- if( badHdr ){
|
|
- /* If the wal-index header is still malformed even while holding
|
|
- ** a WRITE lock, it can only mean that the header is corrupted and
|
|
- ** needs to be reconstructed. So run recovery to do exactly that.
|
|
- */
|
|
- rc = walIndexRecover(pWal);
|
|
- *pChanged = 1;
|
|
+ }else{
|
|
+ int bWriteLock = pWal->writeLock;
|
|
+ if( bWriteLock || SQLITE_OK==(rc = walLockWriter(pWal)) ){
|
|
+ pWal->writeLock = 1;
|
|
+ if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
|
|
+ badHdr = walIndexTryHdr(pWal, pChanged);
|
|
+ if( badHdr ){
|
|
+ /* If the wal-index header is still malformed even while holding
|
|
+ ** a WRITE lock, it can only mean that the header is corrupted and
|
|
+ ** needs to be reconstructed. So run recovery to do exactly that.
|
|
+ */
|
|
+ rc = walIndexRecover(pWal);
|
|
+ *pChanged = 1;
|
|
+ }
|
|
+ }
|
|
+ if( bWriteLock==0 ){
|
|
+ pWal->writeLock = 0;
|
|
+ walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
|
}
|
|
}
|
|
- pWal->writeLock = 0;
|
|
- walUnlockExclusive(pWal, WAL_WRITE_LOCK, 1);
|
|
}
|
|
}
|
|
|
|
@@ -60900,7 +61931,7 @@
|
|
assert( pWal->nWiData>0 );
|
|
assert( pWal->apWiData[0]!=0 );
|
|
pInfo = walCkptInfo(pWal);
|
|
- if( !useWal && pInfo->nBackfill==pWal->hdr.mxFrame
|
|
+ if( !useWal && AtomicLoad(&pInfo->nBackfill)==pWal->hdr.mxFrame
|
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
&& (pWal->pSnapshot==0 || pWal->hdr.mxFrame==0)
|
|
#endif
|
|
@@ -60962,7 +61993,8 @@
|
|
for(i=1; i<WAL_NREADER; i++){
|
|
rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
|
if( rc==SQLITE_OK ){
|
|
- mxReadMark = AtomicStore(pInfo->aReadMark+i,mxFrame);
|
|
+ AtomicStore(pInfo->aReadMark+i,mxFrame);
|
|
+ mxReadMark = mxFrame;
|
|
mxI = i;
|
|
walUnlockExclusive(pWal, WAL_READ_LOCK(i), 1);
|
|
break;
|
|
@@ -61066,7 +62098,7 @@
|
|
rc = SQLITE_NOMEM;
|
|
}else{
|
|
u32 i = pInfo->nBackfillAttempted;
|
|
- for(i=pInfo->nBackfillAttempted; i>pInfo->nBackfill; i--){
|
|
+ for(i=pInfo->nBackfillAttempted; i>AtomicLoad(&pInfo->nBackfill); i--){
|
|
WalHashLoc sLoc; /* Hash table location */
|
|
u32 pgno; /* Page number in db file */
|
|
i64 iDbOff; /* Offset of db file entry */
|
|
@@ -61121,12 +62153,35 @@
|
|
SQLITE_PRIVATE int sqlite3WalBeginReadTransaction(Wal *pWal, int *pChanged){
|
|
int rc; /* Return code */
|
|
int cnt = 0; /* Number of TryBeginRead attempts */
|
|
-
|
|
#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
int bChanged = 0;
|
|
WalIndexHdr *pSnapshot = pWal->pSnapshot;
|
|
- if( pSnapshot && memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
|
|
- bChanged = 1;
|
|
+#endif
|
|
+
|
|
+ assert( pWal->ckptLock==0 );
|
|
+
|
|
+#ifdef SQLITE_ENABLE_SNAPSHOT
|
|
+ if( pSnapshot ){
|
|
+ if( memcmp(pSnapshot, &pWal->hdr, sizeof(WalIndexHdr))!=0 ){
|
|
+ bChanged = 1;
|
|
+ }
|
|
+
|
|
+ /* It is possible that there is a checkpointer thread running
|
|
+ ** concurrent with this code. If this is the case, it may be that the
|
|
+ ** checkpointer has already determined that it will checkpoint
|
|
+ ** snapshot X, where X is later in the wal file than pSnapshot, but
|
|
+ ** has not yet set the pInfo->nBackfillAttempted variable to indicate
|
|
+ ** its intent. To avoid the race condition this leads to, ensure that
|
|
+ ** there is no checkpointer process by taking a shared CKPT lock
|
|
+ ** before checking pInfo->nBackfillAttempted. */
|
|
+ (void)walEnableBlocking(pWal);
|
|
+ rc = walLockShared(pWal, WAL_CKPT_LOCK);
|
|
+ walDisableBlocking(pWal);
|
|
+
|
|
+ if( rc!=SQLITE_OK ){
|
|
+ return rc;
|
|
+ }
|
|
+ pWal->ckptLock = 1;
|
|
}
|
|
#endif
|
|
|
|
@@ -61159,48 +62214,42 @@
|
|
assert( pWal->readLock>0 || pWal->hdr.mxFrame==0 );
|
|
assert( pInfo->aReadMark[pWal->readLock]<=pSnapshot->mxFrame );
|
|
|
|
- /* It is possible that there is a checkpointer thread running
|
|
- ** concurrent with this code. If this is the case, it may be that the
|
|
- ** checkpointer has already determined that it will checkpoint
|
|
- ** snapshot X, where X is later in the wal file than pSnapshot, but
|
|
- ** has not yet set the pInfo->nBackfillAttempted variable to indicate
|
|
- ** its intent. To avoid the race condition this leads to, ensure that
|
|
- ** there is no checkpointer process by taking a shared CKPT lock
|
|
- ** before checking pInfo->nBackfillAttempted.
|
|
- **
|
|
- ** TODO: Does the aReadMark[] lock prevent a checkpointer from doing
|
|
- ** this already?
|
|
- */
|
|
- rc = walLockShared(pWal, WAL_CKPT_LOCK);
|
|
-
|
|
- if( rc==SQLITE_OK ){
|
|
- /* Check that the wal file has not been wrapped. Assuming that it has
|
|
- ** not, also check that no checkpointer has attempted to checkpoint any
|
|
- ** frames beyond pSnapshot->mxFrame. If either of these conditions are
|
|
- ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
|
|
- ** with *pSnapshot and set *pChanged as appropriate for opening the
|
|
- ** snapshot. */
|
|
- if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
|
|
- && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
|
|
- ){
|
|
- assert( pWal->readLock>0 );
|
|
- memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
|
|
- *pChanged = bChanged;
|
|
- }else{
|
|
- rc = SQLITE_ERROR_SNAPSHOT;
|
|
- }
|
|
-
|
|
- /* Release the shared CKPT lock obtained above. */
|
|
- walUnlockShared(pWal, WAL_CKPT_LOCK);
|
|
- pWal->minFrame = 1;
|
|
+ /* Check that the wal file has not been wrapped. Assuming that it has
|
|
+ ** not, also check that no checkpointer has attempted to checkpoint any
|
|
+ ** frames beyond pSnapshot->mxFrame. If either of these conditions are
|
|
+ ** true, return SQLITE_ERROR_SNAPSHOT. Otherwise, overwrite pWal->hdr
|
|
+ ** with *pSnapshot and set *pChanged as appropriate for opening the
|
|
+ ** snapshot. */
|
|
+ if( !memcmp(pSnapshot->aSalt, pWal->hdr.aSalt, sizeof(pWal->hdr.aSalt))
|
|
+ && pSnapshot->mxFrame>=pInfo->nBackfillAttempted
|
|
+ ){
|
|
+ assert( pWal->readLock>0 );
|
|
+ memcpy(&pWal->hdr, pSnapshot, sizeof(WalIndexHdr));
|
|
+ *pChanged = bChanged;
|
|
+ }else{
|
|
+ rc = SQLITE_ERROR_SNAPSHOT;
|
|
}
|
|
|
|
+ /* A client using a non-current snapshot may not ignore any frames
|
|
+ ** from the start of the wal file. This is because, for a system
|
|
+ ** where (minFrame < iSnapshot < maxFrame), a checkpointer may
|
|
+ ** have omitted to checkpoint a frame earlier than minFrame in
|
|
+ ** the file because there exists a frame after iSnapshot that
|
|
+ ** is the same database page. */
|
|
+ pWal->minFrame = 1;
|
|
|
|
if( rc!=SQLITE_OK ){
|
|
sqlite3WalEndReadTransaction(pWal);
|
|
}
|
|
}
|
|
}
|
|
+
|
|
+ /* Release the shared CKPT lock obtained above. */
|
|
+ if( pWal->ckptLock ){
|
|
+ assert( pSnapshot );
|
|
+ walUnlockShared(pWal, WAL_CKPT_LOCK);
|
|
+ pWal->ckptLock = 0;
|
|
+ }
|
|
#endif
|
|
return rc;
|
|
}
|
|
@@ -61280,14 +62329,15 @@
|
|
int iKey; /* Hash slot index */
|
|
int nCollide; /* Number of hash collisions remaining */
|
|
int rc; /* Error code */
|
|
+ u32 iH;
|
|
|
|
rc = walHashGet(pWal, iHash, &sLoc);
|
|
if( rc!=SQLITE_OK ){
|
|
return rc;
|
|
}
|
|
nCollide = HASHTABLE_NSLOT;
|
|
- for(iKey=walHash(pgno); sLoc.aHash[iKey]; iKey=walNextHash(iKey)){
|
|
- u32 iH = sLoc.aHash[iKey];
|
|
+ iKey = walHash(pgno);
|
|
+ while( (iH = AtomicLoad(&sLoc.aHash[iKey]))!=0 ){
|
|
u32 iFrame = iH + sLoc.iZero;
|
|
if( iFrame<=iLast && iFrame>=pWal->minFrame && sLoc.aPgno[iH]==pgno ){
|
|
assert( iFrame>iRead || CORRUPT_DB );
|
|
@@ -61296,6 +62346,7 @@
|
|
if( (nCollide--)==0 ){
|
|
return SQLITE_CORRUPT_BKPT;
|
|
}
|
|
+ iKey = walNextHash(iKey);
|
|
}
|
|
if( iRead ) break;
|
|
}
|
|
@@ -61371,6 +62422,16 @@
|
|
SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
|
|
int rc;
|
|
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ /* If the write-lock is already held, then it was obtained before the
|
|
+ ** read-transaction was even opened, making this call a no-op.
|
|
+ ** Return early. */
|
|
+ if( pWal->writeLock ){
|
|
+ assert( !memcmp(&pWal->hdr,(void *)walIndexHdr(pWal),sizeof(WalIndexHdr)) );
|
|
+ return SQLITE_OK;
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Cannot start a write transaction without first holding a read
|
|
** transaction. */
|
|
assert( pWal->readLock>=0 );
|
|
@@ -61616,11 +62677,7 @@
|
|
int rc; /* Result code from subfunctions */
|
|
void *pData; /* Data actually written */
|
|
u8 aFrame[WAL_FRAME_HDRSIZE]; /* Buffer to assemble frame-header in */
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- if( (pData = sqlite3PagerCodec(pPage))==0 ) return SQLITE_NOMEM_BKPT;
|
|
-#else
|
|
pData = pPage->pData;
|
|
-#endif
|
|
walEncodeFrame(p->pWal, pPage->pgno, nTruncate, pData, aFrame);
|
|
rc = walWriteToLog(p, aFrame, sizeof(aFrame), iOffset);
|
|
if( rc ) return rc;
|
|
@@ -61803,11 +62860,7 @@
|
|
if( pWal->iReCksum==0 || iWrite<pWal->iReCksum ){
|
|
pWal->iReCksum = iWrite;
|
|
}
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- if( (pData = sqlite3PagerCodec(p))==0 ) return SQLITE_NOMEM;
|
|
-#else
|
|
pData = p->pData;
|
|
-#endif
|
|
rc = sqlite3OsWrite(pWal->pWalFd, pData, szPage, iOff);
|
|
if( rc ) return rc;
|
|
p->flags &= ~PGHDR_WAL_APPEND;
|
|
@@ -61857,6 +62910,7 @@
|
|
if( rc ) return rc;
|
|
iOffset += szFrame;
|
|
nExtra++;
|
|
+ assert( pLast!=0 );
|
|
}
|
|
}
|
|
if( bSync ){
|
|
@@ -61889,6 +62943,7 @@
|
|
iFrame++;
|
|
rc = walIndexAppend(pWal, iFrame, p->pgno);
|
|
}
|
|
+ assert( pLast!=0 || nExtra==0 );
|
|
while( rc==SQLITE_OK && nExtra>0 ){
|
|
iFrame++;
|
|
nExtra--;
|
|
@@ -61953,45 +63008,52 @@
|
|
if( pWal->readOnly ) return SQLITE_READONLY;
|
|
WALTRACE(("WAL%p: checkpoint begins\n", pWal));
|
|
|
|
+ /* Enable blocking locks, if possible. If blocking locks are successfully
|
|
+ ** enabled, set xBusy2=0 so that the busy-handler is never invoked. */
|
|
+ sqlite3WalDb(pWal, db);
|
|
+ (void)walEnableBlocking(pWal);
|
|
+
|
|
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
|
|
- ** "checkpoint" lock on the database file. */
|
|
+ ** "checkpoint" lock on the database file.
|
|
+ ** EVIDENCE-OF: R-10421-19736 If any other process is running a
|
|
+ ** checkpoint operation at the same time, the lock cannot be obtained and
|
|
+ ** SQLITE_BUSY is returned.
|
|
+ ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
|
|
+ ** it will not be invoked in this case.
|
|
+ */
|
|
rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
|
- if( rc ){
|
|
- /* EVIDENCE-OF: R-10421-19736 If any other process is running a
|
|
- ** checkpoint operation at the same time, the lock cannot be obtained and
|
|
- ** SQLITE_BUSY is returned.
|
|
- ** EVIDENCE-OF: R-53820-33897 Even if there is a busy-handler configured,
|
|
- ** it will not be invoked in this case.
|
|
- */
|
|
- testcase( rc==SQLITE_BUSY );
|
|
- testcase( xBusy!=0 );
|
|
- return rc;
|
|
- }
|
|
- pWal->ckptLock = 1;
|
|
+ testcase( rc==SQLITE_BUSY );
|
|
+ testcase( rc!=SQLITE_OK && xBusy2!=0 );
|
|
+ if( rc==SQLITE_OK ){
|
|
+ pWal->ckptLock = 1;
|
|
|
|
- /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
|
|
- ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
|
|
- ** file.
|
|
- **
|
|
- ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
|
|
- ** immediately, and a busy-handler is configured, it is invoked and the
|
|
- ** writer lock retried until either the busy-handler returns 0 or the
|
|
- ** lock is successfully obtained.
|
|
- */
|
|
- if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
|
|
- rc = walBusyLock(pWal, xBusy, pBusyArg, WAL_WRITE_LOCK, 1);
|
|
- if( rc==SQLITE_OK ){
|
|
- pWal->writeLock = 1;
|
|
- }else if( rc==SQLITE_BUSY ){
|
|
- eMode2 = SQLITE_CHECKPOINT_PASSIVE;
|
|
- xBusy2 = 0;
|
|
- rc = SQLITE_OK;
|
|
+ /* IMPLEMENTATION-OF: R-59782-36818 The SQLITE_CHECKPOINT_FULL, RESTART and
|
|
+ ** TRUNCATE modes also obtain the exclusive "writer" lock on the database
|
|
+ ** file.
|
|
+ **
|
|
+ ** EVIDENCE-OF: R-60642-04082 If the writer lock cannot be obtained
|
|
+ ** immediately, and a busy-handler is configured, it is invoked and the
|
|
+ ** writer lock retried until either the busy-handler returns 0 or the
|
|
+ ** lock is successfully obtained.
|
|
+ */
|
|
+ if( eMode!=SQLITE_CHECKPOINT_PASSIVE ){
|
|
+ rc = walBusyLock(pWal, xBusy2, pBusyArg, WAL_WRITE_LOCK, 1);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ pWal->writeLock = 1;
|
|
+ }else if( rc==SQLITE_BUSY ){
|
|
+ eMode2 = SQLITE_CHECKPOINT_PASSIVE;
|
|
+ xBusy2 = 0;
|
|
+ rc = SQLITE_OK;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
+
|
|
/* Read the wal-index header. */
|
|
if( rc==SQLITE_OK ){
|
|
+ walDisableBlocking(pWal);
|
|
rc = walIndexReadHdr(pWal, &isChanged);
|
|
+ (void)walEnableBlocking(pWal);
|
|
if( isChanged && pWal->pDbFd->pMethods->iVersion>=3 ){
|
|
sqlite3OsUnfetch(pWal->pDbFd, 0, 0);
|
|
}
|
|
@@ -62023,11 +63085,19 @@
|
|
memset(&pWal->hdr, 0, sizeof(WalIndexHdr));
|
|
}
|
|
|
|
+ walDisableBlocking(pWal);
|
|
+ sqlite3WalDb(pWal, 0);
|
|
+
|
|
/* Release the locks. */
|
|
sqlite3WalEndWriteTransaction(pWal);
|
|
- walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
|
- pWal->ckptLock = 0;
|
|
+ if( pWal->ckptLock ){
|
|
+ walUnlockExclusive(pWal, WAL_CKPT_LOCK, 1);
|
|
+ pWal->ckptLock = 0;
|
|
+ }
|
|
WALTRACE(("WAL%p: checkpoint %s\n", pWal, rc ? "failed" : "ok"));
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
|
|
+#endif
|
|
return (rc==SQLITE_OK && eMode!=eMode2 ? SQLITE_BUSY : rc);
|
|
}
|
|
|
|
@@ -62144,7 +63214,10 @@
|
|
|
|
/* Try to open on pSnapshot when the next read-transaction starts
|
|
*/
|
|
-SQLITE_PRIVATE void sqlite3WalSnapshotOpen(Wal *pWal, sqlite3_snapshot *pSnapshot){
|
|
+SQLITE_PRIVATE void sqlite3WalSnapshotOpen(
|
|
+ Wal *pWal,
|
|
+ sqlite3_snapshot *pSnapshot
|
|
+){
|
|
pWal->pSnapshot = (WalIndexHdr*)pSnapshot;
|
|
}
|
|
|
|
@@ -62663,9 +63736,7 @@
|
|
#endif
|
|
u8 inTransaction; /* Transaction state */
|
|
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- u8 optimalReserve; /* Desired amount of reserved space per page */
|
|
-#endif
|
|
+ u8 nReserveWanted; /* Desired number of extra bytes per page */
|
|
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
|
|
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
|
|
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
|
|
@@ -62788,6 +63859,7 @@
|
|
#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
|
|
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
|
|
#define BTCF_Multiple 0x20 /* Maybe another cursor on the same btree */
|
|
+#define BTCF_Pinned 0x40 /* Cursor is busy and cannot be moved */
|
|
|
|
/*
|
|
** Potential values for BtCursor.eState.
|
|
@@ -62931,6 +64003,7 @@
|
|
int v1, v2; /* Values for up to two %d fields in zPfx */
|
|
StrAccum errMsg; /* Accumulate the error message text here */
|
|
u32 *heap; /* Min-heap used for analyzing cell coverage */
|
|
+ sqlite3 *db; /* Database connection running the check */
|
|
};
|
|
|
|
/*
|
|
@@ -63864,7 +64937,7 @@
|
|
*/
|
|
static int btreeGetHasContent(BtShared *pBt, Pgno pgno){
|
|
Bitvec *p = pBt->pHasContent;
|
|
- return (p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTest(p, pgno)));
|
|
+ return p && (pgno>sqlite3BitvecSize(p) || sqlite3BitvecTestNotNull(p, pgno));
|
|
}
|
|
|
|
/*
|
|
@@ -63952,6 +65025,9 @@
|
|
assert( 0==pCur->pKey );
|
|
assert( cursorHoldsMutex(pCur) );
|
|
|
|
+ if( pCur->curFlags & BTCF_Pinned ){
|
|
+ return SQLITE_CONSTRAINT_PINNED;
|
|
+ }
|
|
if( pCur->eState==CURSOR_SKIPNEXT ){
|
|
pCur->eState = CURSOR_VALID;
|
|
}else{
|
|
@@ -64708,7 +65784,7 @@
|
|
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
|
|
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
|
|
sz += sz2;
|
|
- }else if( iFree+sz>usableSize ){
|
|
+ }else if( NEVER(iFree+sz>usableSize) ){
|
|
return SQLITE_CORRUPT_PAGE(pPage);
|
|
}
|
|
|
|
@@ -64900,9 +65976,14 @@
|
|
if( (data[hdr+2] || data[hdr+1]) && gap+2<=top ){
|
|
u8 *pSpace = pageFindSlot(pPage, nByte, &rc);
|
|
if( pSpace ){
|
|
- assert( pSpace>=data && (pSpace - data)<65536 );
|
|
- *pIdx = (int)(pSpace - data);
|
|
- return SQLITE_OK;
|
|
+ int g2;
|
|
+ assert( pSpace+nByte<=data+pPage->pBt->usableSize );
|
|
+ *pIdx = g2 = (int)(pSpace-data);
|
|
+ if( NEVER(g2<=gap) ){
|
|
+ return SQLITE_CORRUPT_PAGE(pPage);
|
|
+ }else{
|
|
+ return SQLITE_OK;
|
|
+ }
|
|
}else if( rc ){
|
|
return rc;
|
|
}
|
|
@@ -64976,12 +66057,12 @@
|
|
}else{
|
|
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
|
|
if( iFreeBlk<iPtr+4 ){
|
|
- if( iFreeBlk==0 ) break;
|
|
+ if( iFreeBlk==0 ) break; /* TH3: corrupt082.100 */
|
|
return SQLITE_CORRUPT_PAGE(pPage);
|
|
}
|
|
iPtr = iFreeBlk;
|
|
}
|
|
- if( iFreeBlk>pPage->pBt->usableSize-4 ){
|
|
+ if( iFreeBlk>pPage->pBt->usableSize-4 ){ /* TH3: corrupt081.100 */
|
|
return SQLITE_CORRUPT_PAGE(pPage);
|
|
}
|
|
assert( iFreeBlk>iPtr || iFreeBlk==0 );
|
|
@@ -64996,7 +66077,7 @@
|
|
nFrag = iFreeBlk - iEnd;
|
|
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PAGE(pPage);
|
|
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
|
|
- if( iEnd > pPage->pBt->usableSize ){
|
|
+ if( NEVER(iEnd > pPage->pBt->usableSize) ){
|
|
return SQLITE_CORRUPT_PAGE(pPage);
|
|
}
|
|
iSize = iEnd - iStart;
|
|
@@ -65024,7 +66105,8 @@
|
|
/* The new freeblock is at the beginning of the cell content area,
|
|
** so just extend the cell content area rather than create another
|
|
** freelist entry */
|
|
- if( iStart<x || iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
|
|
+ if( iStart<x ) return SQLITE_CORRUPT_PAGE(pPage);
|
|
+ if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage);
|
|
put2byte(&data[hdr+1], iFreeBlk);
|
|
put2byte(&data[hdr+5], iEnd);
|
|
}else{
|
|
@@ -65144,7 +66226,7 @@
|
|
nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
|
|
if( pc>0 ){
|
|
u32 next, size;
|
|
- if( pc<iCellFirst ){
|
|
+ if( pc<top ){
|
|
/* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
|
|
** always be at least one cell before the first freeblock.
|
|
*/
|
|
@@ -65381,12 +66463,12 @@
|
|
** error, return ((unsigned int)-1).
|
|
*/
|
|
static Pgno btreePagecount(BtShared *pBt){
|
|
+ assert( (pBt->nPage & 0x80000000)==0 || CORRUPT_DB );
|
|
return pBt->nPage;
|
|
}
|
|
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree *p){
|
|
assert( sqlite3BtreeHoldsMutex(p) );
|
|
- assert( ((p->pBt->nPage)&0x80000000)==0 );
|
|
- return btreePagecount(p->pBt);
|
|
+ return btreePagecount(p->pBt) & 0x7fffffff;
|
|
}
|
|
|
|
/*
|
|
@@ -65548,8 +66630,7 @@
|
|
BtShared *pBt = (BtShared*)pArg;
|
|
assert( pBt->db );
|
|
assert( sqlite3_mutex_held(pBt->db->mutex) );
|
|
- return sqlite3InvokeBusyHandler(&pBt->db->busyHandler,
|
|
- sqlite3PagerFile(pBt->pPager));
|
|
+ return sqlite3InvokeBusyHandler(&pBt->db->busyHandler);
|
|
}
|
|
|
|
/*
|
|
@@ -65653,9 +66734,13 @@
|
|
rc = sqlite3OsFullPathname(pVfs, zFilename,
|
|
nFullPathname, zFullPathname);
|
|
if( rc ){
|
|
- sqlite3_free(zFullPathname);
|
|
- sqlite3_free(p);
|
|
- return rc;
|
|
+ if( rc==SQLITE_OK_SYMLINK ){
|
|
+ rc = SQLITE_OK;
|
|
+ }else{
|
|
+ sqlite3_free(zFullPathname);
|
|
+ sqlite3_free(p);
|
|
+ return rc;
|
|
+ }
|
|
}
|
|
}
|
|
#if SQLITE_THREADSAFE
|
|
@@ -66096,19 +67181,17 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve, int iFix){
|
|
int rc = SQLITE_OK;
|
|
+ int x;
|
|
BtShared *pBt = p->pBt;
|
|
- assert( nReserve>=-1 && nReserve<=255 );
|
|
+ assert( nReserve>=0 && nReserve<=255 );
|
|
sqlite3BtreeEnter(p);
|
|
-#if SQLITE_HAS_CODEC
|
|
- if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
|
|
-#endif
|
|
+ pBt->nReserveWanted = nReserve;
|
|
+ x = pBt->pageSize - pBt->usableSize;
|
|
+ if( nReserve<x ) nReserve = x;
|
|
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
|
|
sqlite3BtreeLeave(p);
|
|
return SQLITE_READONLY;
|
|
}
|
|
- if( nReserve<0 ){
|
|
- nReserve = pBt->pageSize - pBt->usableSize;
|
|
- }
|
|
assert( nReserve>=0 && nReserve<=255 );
|
|
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
|
|
((pageSize-1)&pageSize)==0 ){
|
|
@@ -66154,19 +67237,17 @@
|
|
** are intentually left unused. This is the "reserved" space that is
|
|
** sometimes used by extensions.
|
|
**
|
|
-** If SQLITE_HAS_MUTEX is defined then the number returned is the
|
|
-** greater of the current reserved space and the maximum requested
|
|
-** reserve space.
|
|
+** The value returned is the larger of the current reserve size and
|
|
+** the latest reserve size requested by SQLITE_FILECTRL_RESERVE_BYTES.
|
|
+** The amount of reserve can only grow - never shrink.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){
|
|
- int n;
|
|
+SQLITE_PRIVATE int sqlite3BtreeGetRequestedReserve(Btree *p){
|
|
+ int n1, n2;
|
|
sqlite3BtreeEnter(p);
|
|
- n = sqlite3BtreeGetReserveNoMutex(p);
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( n<p->pBt->optimalReserve ) n = p->pBt->optimalReserve;
|
|
-#endif
|
|
+ n1 = (int)p->pBt->nReserveWanted;
|
|
+ n2 = sqlite3BtreeGetReserveNoMutex(p);
|
|
sqlite3BtreeLeave(p);
|
|
- return n;
|
|
+ return n1>n2 ? n1 : n2;
|
|
}
|
|
|
|
|
|
@@ -66616,6 +67697,7 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
|
|
BtShared *pBt = p->pBt;
|
|
+ Pager *pPager = pBt->pPager;
|
|
int rc = SQLITE_OK;
|
|
|
|
sqlite3BtreeEnter(p);
|
|
@@ -66631,7 +67713,7 @@
|
|
assert( pBt->inTransaction==TRANS_WRITE || IfNotOmitAV(pBt->bDoTruncate)==0 );
|
|
|
|
if( (p->db->flags & SQLITE_ResetDatabase)
|
|
- && sqlite3PagerIsreadonly(pBt->pPager)==0
|
|
+ && sqlite3PagerIsreadonly(pPager)==0
|
|
){
|
|
pBt->btsFlags &= ~BTS_READ_ONLY;
|
|
}
|
|
@@ -66679,6 +67761,18 @@
|
|
pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
|
|
if( pBt->nPage==0 ) pBt->btsFlags |= BTS_INITIALLY_EMPTY;
|
|
do {
|
|
+ sqlite3PagerWalDb(pPager, p->db);
|
|
+
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ /* If transitioning from no transaction directly to a write transaction,
|
|
+ ** block for the WRITER lock first if possible. */
|
|
+ if( pBt->pPage1==0 && wrflag ){
|
|
+ assert( pBt->inTransaction==TRANS_NONE );
|
|
+ rc = sqlite3PagerWalWriteLock(pPager, 1);
|
|
+ if( rc!=SQLITE_BUSY && rc!=SQLITE_OK ) break;
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* Call lockBtree() until either pBt->pPage1 is populated or
|
|
** lockBtree() returns something other than SQLITE_OK. lockBtree()
|
|
** may return SQLITE_OK but leave pBt->pPage1 set to 0 if after
|
|
@@ -66692,7 +67786,7 @@
|
|
if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
|
|
rc = SQLITE_READONLY;
|
|
}else{
|
|
- rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
|
|
+ rc = sqlite3PagerBegin(pPager, wrflag>1, sqlite3TempInMemory(p->db));
|
|
if( rc==SQLITE_OK ){
|
|
rc = newDatabase(pBt);
|
|
}else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
|
|
@@ -66705,11 +67799,15 @@
|
|
}
|
|
|
|
if( rc!=SQLITE_OK ){
|
|
+ (void)sqlite3PagerWalWriteLock(pPager, 0);
|
|
unlockBtreeIfUnused(pBt);
|
|
}
|
|
}while( (rc&0xFF)==SQLITE_BUSY && pBt->inTransaction==TRANS_NONE &&
|
|
btreeInvokeBusyHandler(pBt) );
|
|
- sqlite3PagerResetLockTimeout(pBt->pPager);
|
|
+ sqlite3PagerWalDb(pPager, 0);
|
|
+#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
+ if( rc==SQLITE_BUSY_TIMEOUT ) rc = SQLITE_BUSY;
|
|
+#endif
|
|
|
|
if( rc==SQLITE_OK ){
|
|
if( p->inTrans==TRANS_NONE ){
|
|
@@ -66761,7 +67859,7 @@
|
|
** open savepoints. If the second parameter is greater than 0 and
|
|
** the sub-journal is not already open, then it will be opened here.
|
|
*/
|
|
- rc = sqlite3PagerOpenSavepoint(pBt->pPager, p->db->nSavepoint);
|
|
+ rc = sqlite3PagerOpenSavepoint(pPager, p->db->nSavepoint);
|
|
}
|
|
}
|
|
|
|
@@ -67615,8 +68713,9 @@
|
|
/* The following assert statements verify that if this is a sharable
|
|
** b-tree database, the connection is holding the required table locks,
|
|
** and that no other connection has any open cursor that conflicts with
|
|
- ** this lock. */
|
|
- assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1)) );
|
|
+ ** this lock. The iTable<1 term disables the check for corrupt schemas. */
|
|
+ assert( hasSharedCacheTableLock(p, iTable, pKeyInfo!=0, (wrFlag?2:1))
|
|
+ || iTable<1 );
|
|
assert( wrFlag==0 || !hasReadConflicts(p, iTable) );
|
|
|
|
/* Assert that the caller has opened the required transaction. */
|
|
@@ -67629,9 +68728,13 @@
|
|
allocateTempSpace(pBt);
|
|
if( pBt->pTmpSpace==0 ) return SQLITE_NOMEM_BKPT;
|
|
}
|
|
- if( iTable==1 && btreePagecount(pBt)==0 ){
|
|
- assert( wrFlag==0 );
|
|
- iTable = 0;
|
|
+ if( iTable<=1 ){
|
|
+ if( iTable<1 ){
|
|
+ return SQLITE_CORRUPT_BKPT;
|
|
+ }else if( btreePagecount(pBt)==0 ){
|
|
+ assert( wrFlag==0 );
|
|
+ iTable = 0;
|
|
+ }
|
|
}
|
|
|
|
/* Now that no other errors can occur, finish filling in the BtCursor
|
|
@@ -67656,6 +68759,19 @@
|
|
pCur->eState = CURSOR_INVALID;
|
|
return SQLITE_OK;
|
|
}
|
|
+static int btreeCursorWithLock(
|
|
+ Btree *p, /* The btree */
|
|
+ int iTable, /* Root page of table to open */
|
|
+ int wrFlag, /* 1 to write. 0 read-only */
|
|
+ struct KeyInfo *pKeyInfo, /* First arg to comparison function */
|
|
+ BtCursor *pCur /* Space for new cursor */
|
|
+){
|
|
+ int rc;
|
|
+ sqlite3BtreeEnter(p);
|
|
+ rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
|
|
+ sqlite3BtreeLeave(p);
|
|
+ return rc;
|
|
+}
|
|
SQLITE_PRIVATE int sqlite3BtreeCursor(
|
|
Btree *p, /* The btree */
|
|
int iTable, /* Root page of table to open */
|
|
@@ -67663,15 +68779,11 @@
|
|
struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
|
|
BtCursor *pCur /* Write new cursor here */
|
|
){
|
|
- int rc;
|
|
- if( iTable<1 ){
|
|
- rc = SQLITE_CORRUPT_BKPT;
|
|
+ if( p->sharable ){
|
|
+ return btreeCursorWithLock(p, iTable, wrFlag, pKeyInfo, pCur);
|
|
}else{
|
|
- sqlite3BtreeEnter(p);
|
|
- rc = btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
|
|
- sqlite3BtreeLeave(p);
|
|
+ return btreeCursor(p, iTable, wrFlag, pKeyInfo, pCur);
|
|
}
|
|
- return rc;
|
|
}
|
|
|
|
/*
|
|
@@ -67794,6 +68906,18 @@
|
|
return pCur->info.nKey;
|
|
}
|
|
|
|
+/*
|
|
+** Pin or unpin a cursor.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3BtreeCursorPin(BtCursor *pCur){
|
|
+ assert( (pCur->curFlags & BTCF_Pinned)==0 );
|
|
+ pCur->curFlags |= BTCF_Pinned;
|
|
+}
|
|
+SQLITE_PRIVATE void sqlite3BtreeCursorUnpin(BtCursor *pCur){
|
|
+ assert( (pCur->curFlags & BTCF_Pinned)!=0 );
|
|
+ pCur->curFlags &= ~BTCF_Pinned;
|
|
+}
|
|
+
|
|
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
|
/*
|
|
** Return the offset into the database file for the start of the
|
|
@@ -68129,6 +69253,7 @@
|
|
assert( aWrite>=pBufStart ); /* due to (6) */
|
|
memcpy(aSave, aWrite, 4);
|
|
rc = sqlite3OsRead(fd, aWrite, a+4, (i64)pBt->pageSize*(nextPage-1));
|
|
+ if( rc && nextPage>pBt->nPage ) rc = SQLITE_CORRUPT_BKPT;
|
|
nextPage = get4byte(aWrite);
|
|
memcpy(aWrite, aSave, 4);
|
|
}else
|
|
@@ -68949,8 +70074,11 @@
|
|
** to be invalid here. This can only occur if a second cursor modifies
|
|
** the page while cursor pCur is holding a reference to it. Which can
|
|
** only happen if the database is corrupt in such a way as to link the
|
|
- ** page into more than one b-tree structure. */
|
|
- testcase( idx>pPage->nCell );
|
|
+ ** page into more than one b-tree structure.
|
|
+ **
|
|
+ ** Update 2019-12-23: appears to long longer be possible after the
|
|
+ ** addition of anotherValidCursor() condition on balance_deeper(). */
|
|
+ harmless( idx>pPage->nCell );
|
|
|
|
if( idx>=pPage->nCell ){
|
|
if( !pPage->leaf ){
|
|
@@ -69917,12 +71045,7 @@
|
|
assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) );
|
|
assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) );
|
|
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
|
- /* The cell should normally be sized correctly. However, when moving a
|
|
- ** malformed cell from a leaf page to an interior page, if the cell size
|
|
- ** wanted to be less than 4 but got rounded up to 4 on the leaf, then size
|
|
- ** might be less than 8 (leaf-size + pointer) on the interior node. Hence
|
|
- ** the term after the || in the following assert(). */
|
|
- assert( sz==pPage->xCellSize(pPage, pCell) || (sz==8 && iChild>0) );
|
|
+ assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB );
|
|
assert( pPage->nFree>=0 );
|
|
if( pPage->nOverflow || sz+2>pPage->nFree ){
|
|
if( pTemp ){
|
|
@@ -70180,7 +71303,7 @@
|
|
if( pData < pCellptr ) return SQLITE_CORRUPT_BKPT;
|
|
memcpy(pData, pCell, sz);
|
|
assert( sz==pPg->xCellSize(pPg, pCell) || CORRUPT_DB );
|
|
- testcase( sz!=pPg->xCellSize(pPg,pCell) );
|
|
+ testcase( sz!=pPg->xCellSize(pPg,pCell) )
|
|
i++;
|
|
if( i>=iEnd ) break;
|
|
if( pCArray->ixNx[k]<=i ){
|
|
@@ -70246,7 +71369,8 @@
|
|
while( 1 /*Exit by break*/ ){
|
|
int sz, rc;
|
|
u8 *pSlot;
|
|
- sz = cachedCellSize(pCArray, i);
|
|
+ assert( pCArray->szCell[i]!=0 );
|
|
+ sz = pCArray->szCell[i];
|
|
if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
|
|
if( (pData - pBegin)<sz ) return 1;
|
|
pData -= sz;
|
|
@@ -70371,7 +71495,7 @@
|
|
assert( nCell>=0 );
|
|
if( iOld<iNew ){
|
|
int nShift = pageFreeArray(pPg, iOld, iNew-iOld, pCArray);
|
|
- if( nShift>nCell ) return SQLITE_CORRUPT_BKPT;
|
|
+ if( NEVER(nShift>nCell) ) return SQLITE_CORRUPT_BKPT;
|
|
memmove(pPg->aCellIdx, &pPg->aCellIdx[nShift*2], nCell*2);
|
|
nCell -= nShift;
|
|
}
|
|
@@ -70407,6 +71531,7 @@
|
|
memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
|
|
}
|
|
nCell++;
|
|
+ cachedCellSize(pCArray, iCell+iNew);
|
|
if( pageInsertArray(
|
|
pPg, pBegin, &pData, pCellptr,
|
|
iCell+iNew, 1, pCArray
|
|
@@ -70929,7 +72054,7 @@
|
|
*/
|
|
memset(&b.szCell[b.nCell], 0, sizeof(b.szCell[0])*(limit+pOld->nOverflow));
|
|
if( pOld->nOverflow>0 ){
|
|
- if( limit<pOld->aiOvfl[0] ){
|
|
+ if( NEVER(limit<pOld->aiOvfl[0]) ){
|
|
rc = SQLITE_CORRUPT_BKPT;
|
|
goto balance_cleanup;
|
|
}
|
|
@@ -71215,6 +72340,8 @@
|
|
));
|
|
|
|
assert( sqlite3PagerIswriteable(pParent->pDbPage) );
|
|
+ assert( nNew>=1 && nNew<=ArraySize(apNew) );
|
|
+ assert( apNew[nNew-1]!=0 );
|
|
put4byte(pRight, apNew[nNew-1]->pgno);
|
|
|
|
/* If the sibling pages are not leaves, ensure that the right-child pointer
|
|
@@ -71540,6 +72667,30 @@
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
+/*
|
|
+** Return SQLITE_CORRUPT if any cursor other than pCur is currently valid
|
|
+** on the same B-tree as pCur.
|
|
+**
|
|
+** This can if a database is corrupt with two or more SQL tables
|
|
+** pointing to the same b-tree. If an insert occurs on one SQL table
|
|
+** and causes a BEFORE TRIGGER to do a secondary insert on the other SQL
|
|
+** table linked to the same b-tree. If the secondary insert causes a
|
|
+** rebalance, that can change content out from under the cursor on the
|
|
+** first SQL table, violating invariants on the first insert.
|
|
+*/
|
|
+static int anotherValidCursor(BtCursor *pCur){
|
|
+ BtCursor *pOther;
|
|
+ for(pOther=pCur->pBt->pCursor; pOther; pOther=pOther->pNext){
|
|
+ if( pOther!=pCur
|
|
+ && pOther->eState==CURSOR_VALID
|
|
+ && pOther->pPage==pCur->pPage
|
|
+ ){
|
|
+ return SQLITE_CORRUPT_BKPT;
|
|
+ }
|
|
+ }
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
/*
|
|
** The page that pCur currently points to has just been modified in
|
|
** some way. This function figures out if this modification means the
|
|
@@ -71560,12 +72711,14 @@
|
|
VVA_ONLY( int balance_deeper_called = 0 );
|
|
|
|
do {
|
|
- int iPage = pCur->iPage;
|
|
+ int iPage;
|
|
MemPage *pPage = pCur->pPage;
|
|
|
|
if( NEVER(pPage->nFree<0) && btreeComputeFreeSpace(pPage) ) break;
|
|
- if( iPage==0 ){
|
|
- if( pPage->nOverflow ){
|
|
+ if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
|
|
+ break;
|
|
+ }else if( (iPage = pCur->iPage)==0 ){
|
|
+ if( pPage->nOverflow && (rc = anotherValidCursor(pCur))==SQLITE_OK ){
|
|
/* The root page of the b-tree is overfull. In this case call the
|
|
** balance_deeper() function to create a new child for the root-page
|
|
** and copy the current contents of the root-page to it. The
|
|
@@ -71585,8 +72738,6 @@
|
|
}else{
|
|
break;
|
|
}
|
|
- }else if( pPage->nOverflow==0 && pPage->nFree<=nMin ){
|
|
- break;
|
|
}else{
|
|
MemPage * const pParent = pCur->apPage[iPage-1];
|
|
int const iIdx = pCur->aiIdx[iPage-1];
|
|
@@ -71728,7 +72879,9 @@
|
|
Pgno ovflPgno; /* Next overflow page to write */
|
|
u32 ovflPageSize; /* Size to write on overflow page */
|
|
|
|
- if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
|
|
+ if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd
|
|
+ || pCur->info.pPayload < pPage->aData + pPage->cellOffset
|
|
+ ){
|
|
return SQLITE_CORRUPT_BKPT;
|
|
}
|
|
/* Overwrite the local portion first */
|
|
@@ -71861,7 +73014,6 @@
|
|
if( flags & BTREE_SAVEPOSITION ){
|
|
assert( pCur->curFlags & BTCF_ValidNKey );
|
|
assert( pX->nKey==pCur->info.nKey );
|
|
- assert( pCur->info.nSize!=0 );
|
|
assert( loc==0 );
|
|
}
|
|
#endif
|
|
@@ -71936,7 +73088,9 @@
|
|
}
|
|
|
|
}
|
|
- assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
|
|
+ assert( pCur->eState==CURSOR_VALID
|
|
+ || (pCur->eState==CURSOR_INVALID && loc)
|
|
+ || CORRUPT_DB );
|
|
|
|
pPage = pCur->pPage;
|
|
assert( pPage->intKey || pX->nKey>=0 );
|
|
@@ -71969,6 +73123,8 @@
|
|
memcpy(newCell, oldCell, 4);
|
|
}
|
|
rc = clearCell(pPage, oldCell, &info);
|
|
+ testcase( pCur->curFlags & BTCF_ValidOvfl );
|
|
+ invalidateOverflowCache(pCur);
|
|
if( info.nSize==szNew && info.nLocal==info.nPayload
|
|
&& (!ISAUTOVACUUM || szNew<pPage->minLocal)
|
|
){
|
|
@@ -71982,7 +73138,12 @@
|
|
** new entry uses overflow pages, as the insertCell() call below is
|
|
** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */
|
|
assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */
|
|
- if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
|
|
+ if( oldCell < pPage->aData+pPage->hdrOffset+10 ){
|
|
+ return SQLITE_CORRUPT_BKPT;
|
|
+ }
|
|
+ if( oldCell+szNew > pPage->aDataEnd ){
|
|
+ return SQLITE_CORRUPT_BKPT;
|
|
+ }
|
|
memcpy(oldCell, newCell, szNew);
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -72691,7 +73852,6 @@
|
|
return rc;
|
|
}
|
|
|
|
-#ifndef SQLITE_OMIT_BTREECOUNT
|
|
/*
|
|
** The first argument, pCur, is a cursor opened on some b-tree. Count the
|
|
** number of entries in the b-tree and write the result to *pnEntry.
|
|
@@ -72700,7 +73860,7 @@
|
|
** Otherwise, if an error is encountered (i.e. an IO error or database
|
|
** corruption) an SQLite error code is returned.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3BtreeCount(BtCursor *pCur, i64 *pnEntry){
|
|
+SQLITE_PRIVATE int sqlite3BtreeCount(sqlite3 *db, BtCursor *pCur, i64 *pnEntry){
|
|
i64 nEntry = 0; /* Value to return in *pnEntry */
|
|
int rc; /* Return code */
|
|
|
|
@@ -72713,7 +73873,7 @@
|
|
/* Unless an error occurs, the following loop runs one iteration for each
|
|
** page in the B-Tree structure (not including overflow pages).
|
|
*/
|
|
- while( rc==SQLITE_OK ){
|
|
+ while( rc==SQLITE_OK && !AtomicLoad(&db->u1.isInterrupted) ){
|
|
int iIdx; /* Index of child node in parent */
|
|
MemPage *pPage; /* Current page of the b-tree */
|
|
|
|
@@ -72764,7 +73924,6 @@
|
|
/* An error has occurred. Return an error code. */
|
|
return rc;
|
|
}
|
|
-#endif
|
|
|
|
/*
|
|
** Return the pager associated with a BTree. This routine is used for
|
|
@@ -72839,6 +73998,7 @@
|
|
checkAppendMsg(pCheck, "2nd reference to page %d", iPage);
|
|
return 1;
|
|
}
|
|
+ if( AtomicLoad(&pCheck->db->u1.isInterrupted) ) return 1;
|
|
setPageReferenced(pCheck, iPage);
|
|
return 0;
|
|
}
|
|
@@ -73282,6 +74442,7 @@
|
|
** returned. If a memory allocation error occurs, NULL is returned.
|
|
*/
|
|
SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
|
|
+ sqlite3 *db, /* Database connection that is running the check */
|
|
Btree *p, /* The btree to be checked */
|
|
int *aRoot, /* An array of root pages numbers for individual trees */
|
|
int nRoot, /* Number of entries in aRoot[] */
|
|
@@ -73299,6 +74460,7 @@
|
|
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
|
|
VVA_ONLY( nRef = sqlite3PagerRefcount(pBt->pPager) );
|
|
assert( nRef>=0 );
|
|
+ sCheck.db = db;
|
|
sCheck.pBt = pBt;
|
|
sCheck.pPager = pBt->pPager;
|
|
sCheck.nPage = btreePagecount(sCheck.pBt);
|
|
@@ -73812,7 +74974,7 @@
|
|
*/
|
|
static int setDestPgsz(sqlite3_backup *p){
|
|
int rc;
|
|
- rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),-1,0);
|
|
+ rc = sqlite3BtreeSetPageSize(p->pDest,sqlite3BtreeGetPageSize(p->pSrc),0,0);
|
|
return rc;
|
|
}
|
|
|
|
@@ -73935,13 +75097,6 @@
|
|
int nDestPgsz = sqlite3BtreeGetPageSize(p->pDest);
|
|
const int nCopy = MIN(nSrcPgsz, nDestPgsz);
|
|
const i64 iEnd = (i64)iSrcPg*(i64)nSrcPgsz;
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- /* Use BtreeGetReserveNoMutex() for the source b-tree, as although it is
|
|
- ** guaranteed that the shared-mutex is held by this thread, handle
|
|
- ** p->pSrc may not actually be the owner. */
|
|
- int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
|
|
- int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest);
|
|
-#endif
|
|
int rc = SQLITE_OK;
|
|
i64 iOff;
|
|
|
|
@@ -73958,26 +75113,6 @@
|
|
rc = SQLITE_READONLY;
|
|
}
|
|
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- /* Backup is not possible if the page size of the destination is changing
|
|
- ** and a codec is in use.
|
|
- */
|
|
- if( nSrcPgsz!=nDestPgsz && sqlite3PagerGetCodec(pDestPager)!=0 ){
|
|
- rc = SQLITE_READONLY;
|
|
- }
|
|
-
|
|
- /* Backup is not possible if the number of bytes of reserve space differ
|
|
- ** between source and destination. If there is a difference, try to
|
|
- ** fix the destination to agree with the source. If that is not possible,
|
|
- ** then the backup cannot proceed.
|
|
- */
|
|
- if( nSrcReserve!=nDestReserve ){
|
|
- u32 newPgsz = nSrcPgsz;
|
|
- rc = sqlite3PagerSetPagesize(pDestPager, &newPgsz, nSrcReserve);
|
|
- if( rc==SQLITE_OK && newPgsz!=(u32)nSrcPgsz ) rc = SQLITE_READONLY;
|
|
- }
|
|
-#endif
|
|
-
|
|
/* This loop runs once for each destination page spanned by the source
|
|
** page. For each iteration, variable iOff is set to the byte offset
|
|
** of the destination page.
|
|
@@ -74319,8 +75454,10 @@
|
|
}
|
|
if( p->isAttached ){
|
|
pp = sqlite3PagerBackupPtr(sqlite3BtreePager(p->pSrc));
|
|
+ assert( pp!=0 );
|
|
while( *pp!=p ){
|
|
pp = &(*pp)->pNext;
|
|
+ assert( pp!=0 );
|
|
}
|
|
*pp = p->pNext;
|
|
}
|
|
@@ -74471,10 +75608,6 @@
|
|
b.pDest = pTo;
|
|
b.iNext = 1;
|
|
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- sqlite3PagerAlignReserve(sqlite3BtreePager(pTo), sqlite3BtreePager(pFrom));
|
|
-#endif
|
|
-
|
|
/* 0x7FFFFFFF is the hard limit for the number of pages in a database
|
|
** file. By passing this as the number of pages to copy to
|
|
** sqlite3_backup_step(), we can guarantee that the copy finishes
|
|
@@ -74735,7 +75868,13 @@
|
|
assert( pMem->szMalloc==0
|
|
|| pMem->szMalloc==sqlite3DbMallocSize(pMem->db, pMem->zMalloc) );
|
|
if( pMem->szMalloc>0 && bPreserve && pMem->z==pMem->zMalloc ){
|
|
- pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
|
|
+ if( pMem->db ){
|
|
+ pMem->z = pMem->zMalloc = sqlite3DbReallocOrFree(pMem->db, pMem->z, n);
|
|
+ }else{
|
|
+ pMem->zMalloc = sqlite3Realloc(pMem->z, n);
|
|
+ if( pMem->zMalloc==0 ) sqlite3_free(pMem->z);
|
|
+ pMem->z = pMem->zMalloc;
|
|
+ }
|
|
bPreserve = 0;
|
|
}else{
|
|
if( pMem->szMalloc>0 ) sqlite3DbFreeNN(pMem->db, pMem->zMalloc);
|
|
@@ -74957,15 +76096,11 @@
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
SQLITE_PRIVATE int sqlite3VdbeMemAggValue(Mem *pAccum, Mem *pOut, FuncDef *pFunc){
|
|
sqlite3_context ctx;
|
|
- Mem t;
|
|
assert( pFunc!=0 );
|
|
assert( pFunc->xValue!=0 );
|
|
assert( (pAccum->flags & MEM_Null)!=0 || pFunc==pAccum->u.pDef );
|
|
assert( pAccum->db==0 || sqlite3_mutex_held(pAccum->db->mutex) );
|
|
memset(&ctx, 0, sizeof(ctx));
|
|
- memset(&t, 0, sizeof(t));
|
|
- t.flags = MEM_Null;
|
|
- t.db = pAccum->db;
|
|
sqlite3VdbeMemSetNull(pOut);
|
|
ctx.pOut = pOut;
|
|
ctx.pMem = pAccum;
|
|
@@ -75091,8 +76226,7 @@
|
|
return pMem->u.i;
|
|
}else if( flags & MEM_Real ){
|
|
return doubleToInt64(pMem->u.r);
|
|
- }else if( flags & (MEM_Str|MEM_Blob) ){
|
|
- assert( pMem->z || pMem->n==0 );
|
|
+ }else if( (flags & (MEM_Str|MEM_Blob))!=0 && pMem->z!=0 ){
|
|
return memIntValue(pMem);
|
|
}else{
|
|
return 0;
|
|
@@ -75249,8 +76383,8 @@
|
|
** affinity even if that results in loss of data. This routine is
|
|
** used (for example) to implement the SQL "cast()" operator.
|
|
*/
|
|
-SQLITE_PRIVATE void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
|
- if( pMem->flags & MEM_Null ) return;
|
|
+SQLITE_PRIVATE int sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
|
+ if( pMem->flags & MEM_Null ) return SQLITE_OK;
|
|
switch( aff ){
|
|
case SQLITE_AFF_BLOB: { /* Really a cast to BLOB */
|
|
if( (pMem->flags & MEM_Blob)==0 ){
|
|
@@ -75281,9 +76415,10 @@
|
|
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
|
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
|
pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal|MEM_Blob|MEM_Zero);
|
|
- break;
|
|
+ return sqlite3VdbeChangeEncoding(pMem, encoding);
|
|
}
|
|
}
|
|
+ return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
@@ -75449,25 +76584,27 @@
|
|
** its link to a shallow copy and by marking any current shallow
|
|
** copies of this cell as invalid.
|
|
**
|
|
-** This is used for testing and debugging only - to make sure shallow
|
|
-** copies are not misused.
|
|
+** This is used for testing and debugging only - to help ensure that shallow
|
|
+** copies (created by OP_SCopy) are not misused.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3VdbeMemAboutToChange(Vdbe *pVdbe, Mem *pMem){
|
|
int i;
|
|
Mem *pX;
|
|
- for(i=0, pX=pVdbe->aMem; i<pVdbe->nMem; i++, pX++){
|
|
+ for(i=1, pX=pVdbe->aMem+1; i<pVdbe->nMem; i++, pX++){
|
|
if( pX->pScopyFrom==pMem ){
|
|
- /* If pX is marked as a shallow copy of pMem, then verify that
|
|
+ u16 mFlags;
|
|
+ if( pVdbe->db->flags & SQLITE_VdbeTrace ){
|
|
+ sqlite3DebugPrintf("Invalidate R[%d] due to change in R[%d]\n",
|
|
+ (int)(pX - pVdbe->aMem), (int)(pMem - pVdbe->aMem));
|
|
+ }
|
|
+ /* If pX is marked as a shallow copy of pMem, then try to verify that
|
|
** no significant changes have been made to pX since the OP_SCopy.
|
|
** A significant change would indicated a missed call to this
|
|
** function for pX. Minor changes, such as adding or removing a
|
|
** dual type, are allowed, as long as the underlying value is the
|
|
** same. */
|
|
- u16 mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
|
|
+ mFlags = pMem->flags & pX->flags & pX->mScopyFlags;
|
|
assert( (mFlags&(MEM_Int|MEM_IntReal))==0 || pMem->u.i==pX->u.i );
|
|
- assert( (mFlags&MEM_Real)==0 || pMem->u.r==pX->u.r );
|
|
- assert( (mFlags&MEM_Str)==0 || (pMem->n==pX->n && pMem->z==pX->z) );
|
|
- assert( (mFlags&MEM_Blob)==0 || sqlite3BlobCompare(pMem,pX)==0 );
|
|
|
|
/* pMem is the register that is changing. But also mark pX as
|
|
** undefined so that we can quickly detect the shallow-copy error */
|
|
@@ -75479,7 +76616,6 @@
|
|
}
|
|
#endif /* SQLITE_DEBUG */
|
|
|
|
-
|
|
/*
|
|
** Make an shallow copy of pFrom into pTo. Prior contents of
|
|
** pTo are freed. The pFrom->z field is not duplicated. If
|
|
@@ -75625,10 +76761,19 @@
|
|
|
|
pMem->n = nByte;
|
|
pMem->flags = flags;
|
|
- pMem->enc = (enc==0 ? SQLITE_UTF8 : enc);
|
|
+ if( enc ){
|
|
+ pMem->enc = enc;
|
|
+#ifdef SQLITE_ENABLE_SESSION
|
|
+ }else if( pMem->db==0 ){
|
|
+ pMem->enc = SQLITE_UTF8;
|
|
+#endif
|
|
+ }else{
|
|
+ assert( pMem->db!=0 );
|
|
+ pMem->enc = ENC(pMem->db);
|
|
+ }
|
|
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
- if( pMem->enc!=SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
|
|
+ if( enc>SQLITE_UTF8 && sqlite3VdbeMemHandleBom(pMem) ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
#endif
|
|
@@ -75655,7 +76800,7 @@
|
|
** If this routine fails for any reason (malloc returns NULL or unable
|
|
** to read from the disk) then the pMem is left in an inconsistent state.
|
|
*/
|
|
-static SQLITE_NOINLINE int vdbeMemFromBtreeResize(
|
|
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
|
|
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
|
u32 offset, /* Offset from the start of data to return bytes from. */
|
|
u32 amt, /* Number of bytes to return. */
|
|
@@ -75678,13 +76823,11 @@
|
|
}
|
|
return rc;
|
|
}
|
|
-SQLITE_PRIVATE int sqlite3VdbeMemFromBtree(
|
|
+SQLITE_PRIVATE int sqlite3VdbeMemFromBtreeZeroOffset(
|
|
BtCursor *pCur, /* Cursor pointing at record to retrieve. */
|
|
- u32 offset, /* Offset from the start of data to return bytes from. */
|
|
u32 amt, /* Number of bytes to return. */
|
|
Mem *pMem /* OUT: Return data in this Mem structure. */
|
|
){
|
|
- char *zData; /* Data from the btree layer */
|
|
u32 available = 0; /* Number of bytes available on the local btree page */
|
|
int rc = SQLITE_OK; /* Return code */
|
|
|
|
@@ -75694,15 +76837,14 @@
|
|
/* Note: the calls to BtreeKeyFetch() and DataFetch() below assert()
|
|
** that both the BtShared and database handle mutexes are held. */
|
|
assert( !sqlite3VdbeMemIsRowSet(pMem) );
|
|
- zData = (char *)sqlite3BtreePayloadFetch(pCur, &available);
|
|
- assert( zData!=0 );
|
|
+ pMem->z = (char *)sqlite3BtreePayloadFetch(pCur, &available);
|
|
+ assert( pMem->z!=0 );
|
|
|
|
- if( offset+amt<=available ){
|
|
- pMem->z = &zData[offset];
|
|
+ if( amt<=available ){
|
|
pMem->flags = MEM_Blob|MEM_Ephem;
|
|
pMem->n = (int)amt;
|
|
}else{
|
|
- rc = vdbeMemFromBtreeResize(pCur, offset, amt, pMem);
|
|
+ rc = sqlite3VdbeMemFromBtree(pCur, 0, amt, pMem);
|
|
}
|
|
|
|
return rc;
|
|
@@ -75806,7 +76948,7 @@
|
|
** an sqlite3_value within the UnpackedRecord.a[] array.
|
|
*/
|
|
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( p ){
|
|
UnpackedRecord *pRec = p->ppRec[0];
|
|
|
|
@@ -75842,7 +76984,7 @@
|
|
}
|
|
#else
|
|
UNUSED_PARAMETER(p);
|
|
-#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
|
|
+#endif /* defined(SQLITE_ENABLE_STAT4) */
|
|
return sqlite3ValueNew(db);
|
|
}
|
|
|
|
@@ -75866,7 +77008,7 @@
|
|
** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
|
|
** NULL and an SQLite error code returned.
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
static int valueFromFunction(
|
|
sqlite3 *db, /* The database connection */
|
|
Expr *p, /* The expression to evaluate */
|
|
@@ -75949,7 +77091,7 @@
|
|
}
|
|
#else
|
|
# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
|
|
-#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
|
|
+#endif /* defined(SQLITE_ENABLE_STAT4) */
|
|
|
|
/*
|
|
** Extract a value from the supplied expression in the manner described
|
|
@@ -75978,7 +77120,7 @@
|
|
|
|
assert( pExpr!=0 );
|
|
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
|
|
-#if defined(SQLITE_ENABLE_STAT3_OR_STAT4)
|
|
+#if defined(SQLITE_ENABLE_STAT4)
|
|
if( op==TK_REGISTER ) op = pExpr->op2;
|
|
#else
|
|
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
|
@@ -76045,7 +77187,11 @@
|
|
if( pVal->flags & MEM_Real ){
|
|
pVal->u.r = -pVal->u.r;
|
|
}else if( pVal->u.i==SMALLEST_INT64 ){
|
|
+#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
pVal->u.r = -(double)SMALLEST_INT64;
|
|
+#else
|
|
+ pVal->u.r = LARGEST_INT64;
|
|
+#endif
|
|
MemSetTypeFlag(pVal, MEM_Real);
|
|
}else{
|
|
pVal->u.i = -pVal->u.i;
|
|
@@ -76071,7 +77217,7 @@
|
|
0, SQLITE_DYNAMIC);
|
|
}
|
|
#endif
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
else if( op==TK_FUNCTION && pCtx!=0 ){
|
|
rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
|
|
}
|
|
@@ -76088,13 +77234,13 @@
|
|
return rc;
|
|
|
|
no_mem:
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( pCtx==0 || pCtx->pParse->nErr==0 )
|
|
#endif
|
|
sqlite3OomFault(db);
|
|
sqlite3DbFree(db, zVal);
|
|
assert( *ppVal==0 );
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( pCtx==0 ) sqlite3ValueFree(pVal);
|
|
#else
|
|
assert( pCtx==0 ); sqlite3ValueFree(pVal);
|
|
@@ -76122,56 +77268,7 @@
|
|
return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
|
|
}
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-/*
|
|
-** The implementation of the sqlite_record() function. This function accepts
|
|
-** a single argument of any type. The return value is a formatted database
|
|
-** record (a blob) containing the argument value.
|
|
-**
|
|
-** This is used to convert the value stored in the 'sample' column of the
|
|
-** sqlite_stat3 table to the record format SQLite uses internally.
|
|
-*/
|
|
-static void recordFunc(
|
|
- sqlite3_context *context,
|
|
- int argc,
|
|
- sqlite3_value **argv
|
|
-){
|
|
- const int file_format = 1;
|
|
- u32 iSerial; /* Serial type */
|
|
- int nSerial; /* Bytes of space for iSerial as varint */
|
|
- u32 nVal; /* Bytes of space required for argv[0] */
|
|
- int nRet;
|
|
- sqlite3 *db;
|
|
- u8 *aRet;
|
|
-
|
|
- UNUSED_PARAMETER( argc );
|
|
- iSerial = sqlite3VdbeSerialType(argv[0], file_format, &nVal);
|
|
- nSerial = sqlite3VarintLen(iSerial);
|
|
- db = sqlite3_context_db_handle(context);
|
|
-
|
|
- nRet = 1 + nSerial + nVal;
|
|
- aRet = sqlite3DbMallocRawNN(db, nRet);
|
|
- if( aRet==0 ){
|
|
- sqlite3_result_error_nomem(context);
|
|
- }else{
|
|
- aRet[0] = nSerial+1;
|
|
- putVarint32(&aRet[1], iSerial);
|
|
- sqlite3VdbeSerialPut(&aRet[1+nSerial], argv[0], iSerial);
|
|
- sqlite3_result_blob(context, aRet, nRet, SQLITE_TRANSIENT);
|
|
- sqlite3DbFreeNN(db, aRet);
|
|
- }
|
|
-}
|
|
-
|
|
-/*
|
|
-** Register built-in functions used to help read ANALYZE data.
|
|
-*/
|
|
-SQLITE_PRIVATE void sqlite3AnalyzeFunctions(void){
|
|
- static FuncDef aAnalyzeTableFuncs[] = {
|
|
- FUNCTION(sqlite_record, 1, 0, 0, recordFunc),
|
|
- };
|
|
- sqlite3InsertBuiltinFuncs(aAnalyzeTableFuncs, ArraySize(aAnalyzeTableFuncs));
|
|
-}
|
|
-
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Attempt to extract a value from pExpr and use it to construct *ppVal.
|
|
**
|
|
@@ -76453,6 +77550,10 @@
|
|
/* #include "sqliteInt.h" */
|
|
/* #include "vdbeInt.h" */
|
|
|
|
+/* Forward references */
|
|
+static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef);
|
|
+static void vdbeFreeOpArray(sqlite3 *, Op *, int);
|
|
+
|
|
/*
|
|
** Create a new virtual database engine.
|
|
*/
|
|
@@ -76480,6 +77581,13 @@
|
|
return p;
|
|
}
|
|
|
|
+/*
|
|
+** Return the Parse object that owns a Vdbe object.
|
|
+*/
|
|
+SQLITE_PRIVATE Parse *sqlite3VdbeParser(Vdbe *p){
|
|
+ return p->pParse;
|
|
+}
|
|
+
|
|
/*
|
|
** Change the error string stored in Vdbe.zErrMsg
|
|
*/
|
|
@@ -76560,7 +77668,7 @@
|
|
zTmp = pA->zSql;
|
|
pA->zSql = pB->zSql;
|
|
pB->zSql = zTmp;
|
|
-#if 0
|
|
+#ifdef SQLITE_ENABLE_NORMALIZE
|
|
zTmp = pA->zNormSql;
|
|
pA->zNormSql = pB->zNormSql;
|
|
pB->zNormSql = zTmp;
|
|
@@ -76621,9 +77729,16 @@
|
|
#ifdef SQLITE_DEBUG
|
|
/* This routine is just a convenient place to set a breakpoint that will
|
|
** fire after each opcode is inserted and displayed using
|
|
-** "PRAGMA vdbe_addoptrace=on".
|
|
+** "PRAGMA vdbe_addoptrace=on". Parameters "pc" (program counter) and
|
|
+** pOp are available to make the breakpoint conditional.
|
|
+**
|
|
+** Other useful labels for breakpoints include:
|
|
+** test_trace_breakpoint(pc,pOp)
|
|
+** sqlite3CorruptError(lineno)
|
|
+** sqlite3MisuseError(lineno)
|
|
+** sqlite3CantopenError(lineno)
|
|
*/
|
|
-static void test_addop_breakpoint(void){
|
|
+static void test_addop_breakpoint(int pc, Op *pOp){
|
|
static int n = 0;
|
|
n++;
|
|
}
|
|
@@ -76676,7 +77791,7 @@
|
|
#ifdef SQLITE_DEBUG
|
|
if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
|
sqlite3VdbePrintOp(0, i, &p->aOp[i]);
|
|
- test_addop_breakpoint();
|
|
+ test_addop_breakpoint(i, &p->aOp[i]);
|
|
}
|
|
#endif
|
|
#ifdef VDBE_PROFILE
|
|
@@ -76759,6 +77874,49 @@
|
|
return addr;
|
|
}
|
|
|
|
+/*
|
|
+** Add an OP_Function or OP_PureFunc opcode.
|
|
+**
|
|
+** The eCallCtx argument is information (typically taken from Expr.op2)
|
|
+** that describes the calling context of the function. 0 means a general
|
|
+** function call. NC_IsCheck means called by a check constraint,
|
|
+** NC_IdxExpr means called as part of an index expression. NC_PartIdx
|
|
+** means in the WHERE clause of a partial index. NC_GenCol means called
|
|
+** while computing a generated column value. 0 is the usual case.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3VdbeAddFunctionCall(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ int p1, /* Constant argument mask */
|
|
+ int p2, /* First argument register */
|
|
+ int p3, /* Register into which results are written */
|
|
+ int nArg, /* Number of argument */
|
|
+ const FuncDef *pFunc, /* The function to be invoked */
|
|
+ int eCallCtx /* Calling context */
|
|
+){
|
|
+ Vdbe *v = pParse->pVdbe;
|
|
+ int nByte;
|
|
+ int addr;
|
|
+ sqlite3_context *pCtx;
|
|
+ assert( v );
|
|
+ nByte = sizeof(*pCtx) + (nArg-1)*sizeof(sqlite3_value*);
|
|
+ pCtx = sqlite3DbMallocRawNN(pParse->db, nByte);
|
|
+ if( pCtx==0 ){
|
|
+ assert( pParse->db->mallocFailed );
|
|
+ freeEphemeralFunction(pParse->db, (FuncDef*)pFunc);
|
|
+ return 0;
|
|
+ }
|
|
+ pCtx->pOut = 0;
|
|
+ pCtx->pFunc = (FuncDef*)pFunc;
|
|
+ pCtx->pVdbe = 0;
|
|
+ pCtx->isError = 0;
|
|
+ pCtx->argc = nArg;
|
|
+ pCtx->iOp = sqlite3VdbeCurrentAddr(v);
|
|
+ addr = sqlite3VdbeAddOp4(v, eCallCtx ? OP_PureFunc : OP_Function,
|
|
+ p1, p2, p3, (char*)pCtx, P4_FUNCCTX);
|
|
+ sqlite3VdbeChangeP5(v, eCallCtx & NC_SelfRef);
|
|
+ return addr;
|
|
+}
|
|
+
|
|
/*
|
|
** Add an opcode that includes the p4 value with a P4_INT64 or
|
|
** P4_REAL type.
|
|
@@ -76801,7 +77959,7 @@
|
|
#endif
|
|
|
|
/*
|
|
-** Add a new OP_ opcode.
|
|
+** Add a new OP_Explain opcode.
|
|
**
|
|
** If the bPush flag is true, then make this opcode the parent for
|
|
** subsequent Explains until sqlite3VdbeExplainPop() is called.
|
|
@@ -77051,6 +78209,7 @@
|
|
** * OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
|
|
** * OP_Destroy
|
|
** * OP_VUpdate
|
|
+** * OP_VCreate
|
|
** * OP_VRename
|
|
** * OP_FkCounter with P2==0 (immediate foreign key constraint)
|
|
** * OP_CreateBtree/BTREE_INTKEY and OP_InitCoroutine
|
|
@@ -77078,7 +78237,8 @@
|
|
int opcode = pOp->opcode;
|
|
if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename
|
|
|| opcode==OP_VDestroy
|
|
- || (opcode==OP_Function0 && pOp->p4.pFunc->funcFlags&SQLITE_FUNC_INTERNAL)
|
|
+ || opcode==OP_VCreate
|
|
+ || (opcode==OP_ParseSchema && pOp->p4.z==0)
|
|
|| ((opcode==OP_Halt || opcode==OP_HaltIfNull)
|
|
&& ((pOp->p1)!=SQLITE_OK && pOp->p2==OE_Abort))
|
|
){
|
|
@@ -77415,16 +78575,16 @@
|
|
** Change the value of the opcode, or P1, P2, P3, or P5 operands
|
|
** for a specific instruction.
|
|
*/
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, u32 addr, u8 iNewOpcode){
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){
|
|
sqlite3VdbeGetOp(p,addr)->opcode = iNewOpcode;
|
|
}
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeP1(Vdbe *p, int addr, int val){
|
|
sqlite3VdbeGetOp(p,addr)->p1 = val;
|
|
}
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, u32 addr, int val){
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeP2(Vdbe *p, int addr, int val){
|
|
sqlite3VdbeGetOp(p,addr)->p2 = val;
|
|
}
|
|
-SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
|
|
+SQLITE_PRIVATE void sqlite3VdbeChangeP3(Vdbe *p, int addr, int val){
|
|
sqlite3VdbeGetOp(p,addr)->p3 = val;
|
|
}
|
|
SQLITE_PRIVATE void sqlite3VdbeChangeP5(Vdbe *p, u16 p5){
|
|
@@ -77440,6 +78600,34 @@
|
|
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
|
}
|
|
|
|
+/*
|
|
+** Change the P2 operand of the jump instruction at addr so that
|
|
+** the jump lands on the next opcode. Or if the jump instruction was
|
|
+** the previous opcode (and is thus a no-op) then simply back up
|
|
+** the next instruction counter by one slot so that the jump is
|
|
+** overwritten by the next inserted opcode.
|
|
+**
|
|
+** This routine is an optimization of sqlite3VdbeJumpHere() that
|
|
+** strives to omit useless byte-code like this:
|
|
+**
|
|
+** 7 Once 0 8 0
|
|
+** 8 ...
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3VdbeJumpHereOrPopInst(Vdbe *p, int addr){
|
|
+ if( addr==p->nOp-1 ){
|
|
+ assert( p->aOp[addr].opcode==OP_Once
|
|
+ || p->aOp[addr].opcode==OP_If
|
|
+ || p->aOp[addr].opcode==OP_FkIfZero );
|
|
+ assert( p->aOp[addr].p4type==0 );
|
|
+#ifdef SQLITE_VDBE_COVERAGE
|
|
+ sqlite3VdbeGetOp(p,-1)->iSrcLine = 0; /* Erase VdbeCoverage() macros */
|
|
+#endif
|
|
+ p->nOp--;
|
|
+ }else{
|
|
+ sqlite3VdbeChangeP2(p, addr, p->nOp);
|
|
+ }
|
|
+}
|
|
+
|
|
|
|
/*
|
|
** If the input FuncDef structure is ephemeral, then free it. If
|
|
@@ -77451,8 +78639,6 @@
|
|
}
|
|
}
|
|
|
|
-static void vdbeFreeOpArray(sqlite3 *, Op *, int);
|
|
-
|
|
/*
|
|
** Delete a P4 value if necessary.
|
|
*/
|
|
@@ -77462,7 +78648,7 @@
|
|
}
|
|
static SQLITE_NOINLINE void freeP4FuncCtx(sqlite3 *db, sqlite3_context *p){
|
|
freeEphemeralFunction(db, p->pFunc);
|
|
- sqlite3DbFreeNN(db, p);
|
|
+ sqlite3DbFreeNN(db, p);
|
|
}
|
|
static void freeP4(sqlite3 *db, int p4type, void *p4){
|
|
assert( db );
|
|
@@ -77536,6 +78722,13 @@
|
|
pVdbe->pProgram = p;
|
|
}
|
|
|
|
+/*
|
|
+** Return true if the given Vdbe has any SubPrograms.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3VdbeHasSubProgram(Vdbe *pVdbe){
|
|
+ return pVdbe->pProgram!=0;
|
|
+}
|
|
+
|
|
/*
|
|
** Change the opcode at addr into OP_Noop
|
|
*/
|
|
@@ -77563,6 +78756,41 @@
|
|
}
|
|
}
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+/*
|
|
+** Generate an OP_ReleaseReg opcode to indicate that a range of
|
|
+** registers, except any identified by mask, are no longer in use.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3VdbeReleaseRegisters(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ int iFirst, /* Index of first register to be released */
|
|
+ int N, /* Number of registers to release */
|
|
+ u32 mask, /* Mask of registers to NOT release */
|
|
+ int bUndefine /* If true, mark registers as undefined */
|
|
+){
|
|
+ if( N==0 ) return;
|
|
+ assert( pParse->pVdbe );
|
|
+ assert( iFirst>=1 );
|
|
+ assert( iFirst+N-1<=pParse->nMem );
|
|
+ if( N<=31 && mask!=0 ){
|
|
+ while( N>0 && (mask&1)!=0 ){
|
|
+ mask >>= 1;
|
|
+ iFirst++;
|
|
+ N--;
|
|
+ }
|
|
+ while( N>0 && N<=32 && (mask & MASKBIT32(N-1))!=0 ){
|
|
+ mask &= ~MASKBIT32(N-1);
|
|
+ N--;
|
|
+ }
|
|
+ }
|
|
+ if( N>0 ){
|
|
+ sqlite3VdbeAddOp3(pParse->pVdbe, OP_ReleaseReg, iFirst, N, *(int*)&mask);
|
|
+ if( bUndefine ) sqlite3VdbeChangeP5(pParse->pVdbe, 1);
|
|
+ }
|
|
+}
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
+
|
|
/*
|
|
** Change the value of the P4 operand for a specific instruction.
|
|
** This routine is useful when a large program is loaded from a
|
|
@@ -77680,7 +78908,8 @@
|
|
*/
|
|
static void vdbeVComment(Vdbe *p, const char *zFormat, va_list ap){
|
|
assert( p->nOp>0 || p->aOp==0 );
|
|
- assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed );
|
|
+ assert( p->aOp==0 || p->aOp[p->nOp-1].zComment==0 || p->db->mallocFailed
|
|
+ || p->pParse->nErr>0 );
|
|
if( p->nOp ){
|
|
assert( p->aOp );
|
|
sqlite3DbFree(p->db, p->aOp[p->nOp-1].zComment);
|
|
@@ -77770,17 +78999,19 @@
|
|
** "PX@PY+1" -> "r[X..X+Y]" or "r[x]" if y is 0
|
|
** "PY..PY" -> "r[X..Y]" or "r[x]" if y<=x
|
|
*/
|
|
-static int displayComment(
|
|
+SQLITE_PRIVATE char *sqlite3VdbeDisplayComment(
|
|
+ sqlite3 *db, /* Optional - Oom error reporting only */
|
|
const Op *pOp, /* The opcode to be commented */
|
|
- const char *zP4, /* Previously obtained value for P4 */
|
|
- char *zTemp, /* Write result here */
|
|
- int nTemp /* Space available in zTemp[] */
|
|
+ const char *zP4 /* Previously obtained value for P4 */
|
|
){
|
|
const char *zOpName;
|
|
const char *zSynopsis;
|
|
int nOpName;
|
|
- int ii, jj;
|
|
+ int ii;
|
|
char zAlt[50];
|
|
+ StrAccum x;
|
|
+
|
|
+ sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
|
|
zOpName = sqlite3OpcodeName(pOp->opcode);
|
|
nOpName = sqlite3Strlen30(zOpName);
|
|
if( zOpName[nOpName+1] ){
|
|
@@ -77795,53 +79026,64 @@
|
|
}
|
|
zSynopsis = zAlt;
|
|
}
|
|
- for(ii=jj=0; jj<nTemp-1 && (c = zSynopsis[ii])!=0; ii++){
|
|
+ for(ii=0; (c = zSynopsis[ii])!=0; ii++){
|
|
if( c=='P' ){
|
|
c = zSynopsis[++ii];
|
|
if( c=='4' ){
|
|
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", zP4);
|
|
+ sqlite3_str_appendall(&x, zP4);
|
|
}else if( c=='X' ){
|
|
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%s", pOp->zComment);
|
|
+ sqlite3_str_appendall(&x, pOp->zComment);
|
|
seenCom = 1;
|
|
}else{
|
|
int v1 = translateP(c, pOp);
|
|
int v2;
|
|
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "%d", v1);
|
|
if( strncmp(zSynopsis+ii+1, "@P", 2)==0 ){
|
|
ii += 3;
|
|
- jj += sqlite3Strlen30(zTemp+jj);
|
|
v2 = translateP(zSynopsis[ii], pOp);
|
|
if( strncmp(zSynopsis+ii+1,"+1",2)==0 ){
|
|
ii += 2;
|
|
v2++;
|
|
}
|
|
- if( v2>1 ){
|
|
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "..%d", v1+v2-1);
|
|
+ if( v2<2 ){
|
|
+ sqlite3_str_appendf(&x, "%d", v1);
|
|
+ }else{
|
|
+ sqlite3_str_appendf(&x, "%d..%d", v1, v1+v2-1);
|
|
+ }
|
|
+ }else if( strncmp(zSynopsis+ii+1, "@NP", 3)==0 ){
|
|
+ sqlite3_context *pCtx = pOp->p4.pCtx;
|
|
+ if( pOp->p4type!=P4_FUNCCTX || pCtx->argc==1 ){
|
|
+ sqlite3_str_appendf(&x, "%d", v1);
|
|
+ }else if( pCtx->argc>1 ){
|
|
+ sqlite3_str_appendf(&x, "%d..%d", v1, v1+pCtx->argc-1);
|
|
+ }else{
|
|
+ assert( x.nChar>2 );
|
|
+ x.nChar -= 2;
|
|
+ ii++;
|
|
+ }
|
|
+ ii += 3;
|
|
+ }else{
|
|
+ sqlite3_str_appendf(&x, "%d", v1);
|
|
+ if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
|
|
+ ii += 4;
|
|
}
|
|
- }else if( strncmp(zSynopsis+ii+1, "..P3", 4)==0 && pOp->p3==0 ){
|
|
- ii += 4;
|
|
}
|
|
}
|
|
- jj += sqlite3Strlen30(zTemp+jj);
|
|
}else{
|
|
- zTemp[jj++] = c;
|
|
+ sqlite3_str_appendchar(&x, 1, c);
|
|
}
|
|
}
|
|
- if( !seenCom && jj<nTemp-5 && pOp->zComment ){
|
|
- sqlite3_snprintf(nTemp-jj, zTemp+jj, "; %s", pOp->zComment);
|
|
- jj += sqlite3Strlen30(zTemp+jj);
|
|
+ if( !seenCom && pOp->zComment ){
|
|
+ sqlite3_str_appendf(&x, "; %s", pOp->zComment);
|
|
}
|
|
- if( jj<nTemp ) zTemp[jj] = 0;
|
|
}else if( pOp->zComment ){
|
|
- sqlite3_snprintf(nTemp, zTemp, "%s", pOp->zComment);
|
|
- jj = sqlite3Strlen30(zTemp);
|
|
- }else{
|
|
- zTemp[0] = 0;
|
|
- jj = 0;
|
|
+ sqlite3_str_appendall(&x, pOp->zComment);
|
|
+ }
|
|
+ if( (x.accError & SQLITE_NOMEM)!=0 && db!=0 ){
|
|
+ sqlite3OomFault(db);
|
|
}
|
|
- return jj;
|
|
+ return sqlite3StrAccumFinish(&x);
|
|
}
|
|
-#endif /* SQLITE_DEBUG */
|
|
+#endif /* SQLITE_ENABLE_EXPLAIN_COMMENTS */
|
|
|
|
#if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS)
|
|
/*
|
|
@@ -77922,23 +79164,25 @@
|
|
** Compute a string that describes the P4 parameter for an opcode.
|
|
** Use zTemp for any required temporary buffer space.
|
|
*/
|
|
-static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
|
- char *zP4 = zTemp;
|
|
+SQLITE_PRIVATE char *sqlite3VdbeDisplayP4(sqlite3 *db, Op *pOp){
|
|
+ char *zP4 = 0;
|
|
StrAccum x;
|
|
- assert( nTemp>=20 );
|
|
- sqlite3StrAccumInit(&x, 0, zTemp, nTemp, 0);
|
|
+
|
|
+ sqlite3StrAccumInit(&x, 0, 0, 0, SQLITE_MAX_LENGTH);
|
|
switch( pOp->p4type ){
|
|
case P4_KEYINFO: {
|
|
int j;
|
|
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
|
|
- assert( pKeyInfo->aSortOrder!=0 );
|
|
+ assert( pKeyInfo->aSortFlags!=0 );
|
|
sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField);
|
|
for(j=0; j<pKeyInfo->nKeyField; j++){
|
|
CollSeq *pColl = pKeyInfo->aColl[j];
|
|
const char *zColl = pColl ? pColl->zName : "";
|
|
if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
|
|
- sqlite3_str_appendf(&x, ",%s%s",
|
|
- pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
|
|
+ sqlite3_str_appendf(&x, ",%s%s%s",
|
|
+ (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_DESC) ? "-" : "",
|
|
+ (pKeyInfo->aSortFlags[j] & KEYINFO_ORDER_BIGNULL)? "N." : "",
|
|
+ zColl);
|
|
}
|
|
sqlite3_str_append(&x, ")", 1);
|
|
break;
|
|
@@ -77950,8 +79194,11 @@
|
|
}
|
|
#endif
|
|
case P4_COLLSEQ: {
|
|
+ static const char *const encnames[] = {"?", "8", "16LE", "16BE"};
|
|
CollSeq *pColl = pOp->p4.pColl;
|
|
- sqlite3_str_appendf(&x, "(%.20s)", pColl->zName);
|
|
+ assert( pColl->enc>=0 && pColl->enc<4 );
|
|
+ sqlite3_str_appendf(&x, "%.18s-%s", pColl->zName,
|
|
+ encnames[pColl->enc]);
|
|
break;
|
|
}
|
|
case P4_FUNCDEF: {
|
|
@@ -77959,13 +79206,11 @@
|
|
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
|
break;
|
|
}
|
|
-#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
|
case P4_FUNCCTX: {
|
|
FuncDef *pDef = pOp->p4.pCtx->pFunc;
|
|
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
|
break;
|
|
}
|
|
-#endif
|
|
case P4_INT64: {
|
|
sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
|
|
break;
|
|
@@ -78007,36 +79252,32 @@
|
|
int n = ai[0]; /* The first element of an INTARRAY is always the
|
|
** count of the number of elements to follow */
|
|
for(i=1; i<=n; i++){
|
|
- sqlite3_str_appendf(&x, ",%d", ai[i]);
|
|
+ sqlite3_str_appendf(&x, "%c%d", (i==1 ? '[' : ','), ai[i]);
|
|
}
|
|
- zTemp[0] = '[';
|
|
sqlite3_str_append(&x, "]", 1);
|
|
break;
|
|
}
|
|
case P4_SUBPROGRAM: {
|
|
- sqlite3_str_appendf(&x, "program");
|
|
+ zP4 = "program";
|
|
break;
|
|
}
|
|
case P4_DYNBLOB:
|
|
case P4_ADVANCE: {
|
|
- zTemp[0] = 0;
|
|
break;
|
|
}
|
|
case P4_TABLE: {
|
|
- sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
|
|
+ zP4 = pOp->p4.pTab->zName;
|
|
break;
|
|
}
|
|
default: {
|
|
zP4 = pOp->p4.z;
|
|
- if( zP4==0 ){
|
|
- zP4 = zTemp;
|
|
- zTemp[0] = 0;
|
|
- }
|
|
}
|
|
}
|
|
- sqlite3StrAccumFinish(&x);
|
|
- assert( zP4!=0 );
|
|
- return zP4;
|
|
+ if( zP4 ) sqlite3_str_appendall(&x, zP4);
|
|
+ if( (x.accError & SQLITE_NOMEM)!=0 ){
|
|
+ sqlite3OomFault(db);
|
|
+ }
|
|
+ return sqlite3StrAccumFinish(&x);
|
|
}
|
|
#endif /* VDBE_DISPLAY_P4 */
|
|
|
|
@@ -78126,24 +79367,30 @@
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3VdbePrintOp(FILE *pOut, int pc, VdbeOp *pOp){
|
|
char *zP4;
|
|
- char zPtr[50];
|
|
- char zCom[100];
|
|
+ char *zCom;
|
|
+ sqlite3 dummyDb;
|
|
static const char *zFormat1 = "%4d %-13s %4d %4d %4d %-13s %.2X %s\n";
|
|
if( pOut==0 ) pOut = stdout;
|
|
- zP4 = displayP4(pOp, zPtr, sizeof(zPtr));
|
|
+ sqlite3BeginBenignMalloc();
|
|
+ dummyDb.mallocFailed = 1;
|
|
+ zP4 = sqlite3VdbeDisplayP4(&dummyDb, pOp);
|
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
- displayComment(pOp, zP4, zCom, sizeof(zCom));
|
|
+ zCom = sqlite3VdbeDisplayComment(0, pOp, zP4);
|
|
#else
|
|
- zCom[0] = 0;
|
|
+ zCom = 0;
|
|
#endif
|
|
/* NB: The sqlite3OpcodeName() function is implemented by code created
|
|
** by the mkopcodeh.awk and mkopcodec.awk scripts which extract the
|
|
** information from the vdbe.c source text */
|
|
fprintf(pOut, zFormat1, pc,
|
|
- sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3, zP4, pOp->p5,
|
|
- zCom
|
|
+ sqlite3OpcodeName(pOp->opcode), pOp->p1, pOp->p2, pOp->p3,
|
|
+ zP4 ? zP4 : "", pOp->p5,
|
|
+ zCom ? zCom : ""
|
|
);
|
|
fflush(pOut);
|
|
+ sqlite3_free(zP4);
|
|
+ sqlite3_free(zCom);
|
|
+ sqlite3EndBenignMalloc();
|
|
}
|
|
#endif
|
|
|
|
@@ -78234,6 +79481,121 @@
|
|
pFrame->v->pDelFrame = pFrame;
|
|
}
|
|
|
|
+#if defined(SQLITE_ENABLE_BYTECODE_VTAB) || !defined(SQLITE_OMIT_EXPLAIN)
|
|
+/*
|
|
+** Locate the next opcode to be displayed in EXPLAIN or EXPLAIN
|
|
+** QUERY PLAN output.
|
|
+**
|
|
+** Return SQLITE_ROW on success. Return SQLITE_DONE if there are no
|
|
+** more opcodes to be displayed.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3VdbeNextOpcode(
|
|
+ Vdbe *p, /* The statement being explained */
|
|
+ Mem *pSub, /* Storage for keeping track of subprogram nesting */
|
|
+ int eMode, /* 0: normal. 1: EQP. 2: TablesUsed */
|
|
+ int *piPc, /* IN/OUT: Current rowid. Overwritten with next rowid */
|
|
+ int *piAddr, /* OUT: Write index into (*paOp)[] here */
|
|
+ Op **paOp /* OUT: Write the opcode array here */
|
|
+){
|
|
+ int nRow; /* Stop when row count reaches this */
|
|
+ int nSub = 0; /* Number of sub-vdbes seen so far */
|
|
+ SubProgram **apSub = 0; /* Array of sub-vdbes */
|
|
+ int i; /* Next instruction address */
|
|
+ int rc = SQLITE_OK; /* Result code */
|
|
+ Op *aOp = 0; /* Opcode array */
|
|
+ int iPc; /* Rowid. Copy of value in *piPc */
|
|
+
|
|
+ /* When the number of output rows reaches nRow, that means the
|
|
+ ** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
|
+ ** nRow is the sum of the number of rows in the main program, plus
|
|
+ ** the sum of the number of rows in all trigger subprograms encountered
|
|
+ ** so far. The nRow value will increase as new trigger subprograms are
|
|
+ ** encountered, but p->pc will eventually catch up to nRow.
|
|
+ */
|
|
+ nRow = p->nOp;
|
|
+ if( pSub!=0 ){
|
|
+ if( pSub->flags&MEM_Blob ){
|
|
+ /* pSub is initiallly NULL. It is initialized to a BLOB by
|
|
+ ** the P4_SUBPROGRAM processing logic below */
|
|
+ nSub = pSub->n/sizeof(Vdbe*);
|
|
+ apSub = (SubProgram **)pSub->z;
|
|
+ }
|
|
+ for(i=0; i<nSub; i++){
|
|
+ nRow += apSub[i]->nOp;
|
|
+ }
|
|
+ }
|
|
+ iPc = *piPc;
|
|
+ while(1){ /* Loop exits via break */
|
|
+ i = iPc++;
|
|
+ if( i>=nRow ){
|
|
+ p->rc = SQLITE_OK;
|
|
+ rc = SQLITE_DONE;
|
|
+ break;
|
|
+ }
|
|
+ if( i<p->nOp ){
|
|
+ /* The rowid is small enough that we are still in the
|
|
+ ** main program. */
|
|
+ aOp = p->aOp;
|
|
+ }else{
|
|
+ /* We are currently listing subprograms. Figure out which one and
|
|
+ ** pick up the appropriate opcode. */
|
|
+ int j;
|
|
+ i -= p->nOp;
|
|
+ assert( apSub!=0 );
|
|
+ assert( nSub>0 );
|
|
+ for(j=0; i>=apSub[j]->nOp; j++){
|
|
+ i -= apSub[j]->nOp;
|
|
+ assert( i<apSub[j]->nOp || j+1<nSub );
|
|
+ }
|
|
+ aOp = apSub[j]->aOp;
|
|
+ }
|
|
+
|
|
+ /* When an OP_Program opcode is encounter (the only opcode that has
|
|
+ ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
|
+ ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
|
+ ** has not already been seen.
|
|
+ */
|
|
+ if( pSub!=0 && aOp[i].p4type==P4_SUBPROGRAM ){
|
|
+ int nByte = (nSub+1)*sizeof(SubProgram*);
|
|
+ int j;
|
|
+ for(j=0; j<nSub; j++){
|
|
+ if( apSub[j]==aOp[i].p4.pProgram ) break;
|
|
+ }
|
|
+ if( j==nSub ){
|
|
+ p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
|
|
+ if( p->rc!=SQLITE_OK ){
|
|
+ rc = SQLITE_ERROR;
|
|
+ break;
|
|
+ }
|
|
+ apSub = (SubProgram **)pSub->z;
|
|
+ apSub[nSub++] = aOp[i].p4.pProgram;
|
|
+ MemSetTypeFlag(pSub, MEM_Blob);
|
|
+ pSub->n = nSub*sizeof(SubProgram*);
|
|
+ nRow += aOp[i].p4.pProgram->nOp;
|
|
+ }
|
|
+ }
|
|
+ if( eMode==0 ) break;
|
|
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
|
+ if( eMode==2 ){
|
|
+ Op *pOp = aOp + i;
|
|
+ if( pOp->opcode==OP_OpenRead ) break;
|
|
+ if( pOp->opcode==OP_OpenWrite && (pOp->p5 & OPFLAG_P2ISREG)==0 ) break;
|
|
+ if( pOp->opcode==OP_ReopenIdx ) break;
|
|
+ }else
|
|
+#endif
|
|
+ {
|
|
+ assert( eMode==1 );
|
|
+ if( aOp[i].opcode==OP_Explain ) break;
|
|
+ if( aOp[i].opcode==OP_Init && iPc>1 ) break;
|
|
+ }
|
|
+ }
|
|
+ *piPc = iPc;
|
|
+ *piAddr = i;
|
|
+ *paOp = aOp;
|
|
+ return rc;
|
|
+}
|
|
+#endif /* SQLITE_ENABLE_BYTECODE_VTAB || !SQLITE_OMIT_EXPLAIN */
|
|
+
|
|
|
|
/*
|
|
** Delete a VdbeFrame object and its contents. VdbeFrame objects are
|
|
@@ -78274,16 +79636,14 @@
|
|
SQLITE_PRIVATE int sqlite3VdbeList(
|
|
Vdbe *p /* The VDBE */
|
|
){
|
|
- int nRow; /* Stop when row count reaches this */
|
|
- int nSub = 0; /* Number of sub-vdbes seen so far */
|
|
- SubProgram **apSub = 0; /* Array of sub-vdbes */
|
|
Mem *pSub = 0; /* Memory cell hold array of subprogs */
|
|
sqlite3 *db = p->db; /* The database connection */
|
|
int i; /* Loop counter */
|
|
int rc = SQLITE_OK; /* Return code */
|
|
Mem *pMem = &p->aMem[1]; /* First Mem of result set */
|
|
int bListSubprogs = (p->explain==1 || (db->flags & SQLITE_TriggerEQP)!=0);
|
|
- Op *pOp = 0;
|
|
+ Op *aOp; /* Array of opcodes */
|
|
+ Op *pOp; /* Current opcode */
|
|
|
|
assert( p->explain );
|
|
assert( p->magic==VDBE_MAGIC_RUN );
|
|
@@ -78303,14 +79663,6 @@
|
|
return SQLITE_ERROR;
|
|
}
|
|
|
|
- /* When the number of output rows reaches nRow, that means the
|
|
- ** listing has finished and sqlite3_step() should return SQLITE_DONE.
|
|
- ** nRow is the sum of the number of rows in the main program, plus
|
|
- ** the sum of the number of rows in all trigger subprograms encountered
|
|
- ** so far. The nRow value will increase as new trigger subprograms are
|
|
- ** encountered, but p->pc will eventually catch up to nRow.
|
|
- */
|
|
- nRow = p->nOp;
|
|
if( bListSubprogs ){
|
|
/* The first 8 memory cells are used for the result set. So we will
|
|
** commandeer the 9th cell to use as storage for an array of pointers
|
|
@@ -78318,144 +79670,55 @@
|
|
** cells. */
|
|
assert( p->nMem>9 );
|
|
pSub = &p->aMem[9];
|
|
- if( pSub->flags&MEM_Blob ){
|
|
- /* On the first call to sqlite3_step(), pSub will hold a NULL. It is
|
|
- ** initialized to a BLOB by the P4_SUBPROGRAM processing logic below */
|
|
- nSub = pSub->n/sizeof(Vdbe*);
|
|
- apSub = (SubProgram **)pSub->z;
|
|
- }
|
|
- for(i=0; i<nSub; i++){
|
|
- nRow += apSub[i]->nOp;
|
|
- }
|
|
+ }else{
|
|
+ pSub = 0;
|
|
}
|
|
|
|
- while(1){ /* Loop exits via break */
|
|
- i = p->pc++;
|
|
- if( i>=nRow ){
|
|
- p->rc = SQLITE_OK;
|
|
- rc = SQLITE_DONE;
|
|
- break;
|
|
- }
|
|
- if( i<p->nOp ){
|
|
- /* The output line number is small enough that we are still in the
|
|
- ** main program. */
|
|
- pOp = &p->aOp[i];
|
|
- }else{
|
|
- /* We are currently listing subprograms. Figure out which one and
|
|
- ** pick up the appropriate opcode. */
|
|
- int j;
|
|
- i -= p->nOp;
|
|
- for(j=0; i>=apSub[j]->nOp; j++){
|
|
- i -= apSub[j]->nOp;
|
|
- }
|
|
- pOp = &apSub[j]->aOp[i];
|
|
- }
|
|
-
|
|
- /* When an OP_Program opcode is encounter (the only opcode that has
|
|
- ** a P4_SUBPROGRAM argument), expand the size of the array of subprograms
|
|
- ** kept in p->aMem[9].z to hold the new program - assuming this subprogram
|
|
- ** has not already been seen.
|
|
- */
|
|
- if( bListSubprogs && pOp->p4type==P4_SUBPROGRAM ){
|
|
- int nByte = (nSub+1)*sizeof(SubProgram*);
|
|
- int j;
|
|
- for(j=0; j<nSub; j++){
|
|
- if( apSub[j]==pOp->p4.pProgram ) break;
|
|
- }
|
|
- if( j==nSub ){
|
|
- p->rc = sqlite3VdbeMemGrow(pSub, nByte, nSub!=0);
|
|
- if( p->rc!=SQLITE_OK ){
|
|
- rc = SQLITE_ERROR;
|
|
- break;
|
|
- }
|
|
- apSub = (SubProgram **)pSub->z;
|
|
- apSub[nSub++] = pOp->p4.pProgram;
|
|
- pSub->flags |= MEM_Blob;
|
|
- pSub->n = nSub*sizeof(SubProgram*);
|
|
- nRow += pOp->p4.pProgram->nOp;
|
|
- }
|
|
- }
|
|
- if( p->explain<2 ) break;
|
|
- if( pOp->opcode==OP_Explain ) break;
|
|
- if( pOp->opcode==OP_Init && p->pc>1 ) break;
|
|
- }
|
|
+ /* Figure out which opcode is next to display */
|
|
+ rc = sqlite3VdbeNextOpcode(p, pSub, p->explain==2, &p->pc, &i, &aOp);
|
|
|
|
if( rc==SQLITE_OK ){
|
|
- if( db->u1.isInterrupted ){
|
|
+ pOp = aOp + i;
|
|
+ if( AtomicLoad(&db->u1.isInterrupted) ){
|
|
p->rc = SQLITE_INTERRUPT;
|
|
rc = SQLITE_ERROR;
|
|
sqlite3VdbeError(p, sqlite3ErrStr(p->rc));
|
|
}else{
|
|
- char *zP4;
|
|
- if( p->explain==1 ){
|
|
- pMem->flags = MEM_Int;
|
|
- pMem->u.i = i; /* Program counter */
|
|
- pMem++;
|
|
-
|
|
- pMem->flags = MEM_Static|MEM_Str|MEM_Term;
|
|
- pMem->z = (char*)sqlite3OpcodeName(pOp->opcode); /* Opcode */
|
|
- assert( pMem->z!=0 );
|
|
- pMem->n = sqlite3Strlen30(pMem->z);
|
|
- pMem->enc = SQLITE_UTF8;
|
|
- pMem++;
|
|
- }
|
|
-
|
|
- pMem->flags = MEM_Int;
|
|
- pMem->u.i = pOp->p1; /* P1 */
|
|
- pMem++;
|
|
-
|
|
- pMem->flags = MEM_Int;
|
|
- pMem->u.i = pOp->p2; /* P2 */
|
|
- pMem++;
|
|
-
|
|
- pMem->flags = MEM_Int;
|
|
- pMem->u.i = pOp->p3; /* P3 */
|
|
- pMem++;
|
|
-
|
|
- if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */
|
|
- assert( p->db->mallocFailed );
|
|
- return SQLITE_ERROR;
|
|
- }
|
|
- pMem->flags = MEM_Str|MEM_Term;
|
|
- zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
|
|
- if( zP4!=pMem->z ){
|
|
- pMem->n = 0;
|
|
- sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
|
+ char *zP4 = sqlite3VdbeDisplayP4(db, pOp);
|
|
+ if( p->explain==2 ){
|
|
+ sqlite3VdbeMemSetInt64(pMem, pOp->p1);
|
|
+ sqlite3VdbeMemSetInt64(pMem+1, pOp->p2);
|
|
+ sqlite3VdbeMemSetInt64(pMem+2, pOp->p3);
|
|
+ sqlite3VdbeMemSetStr(pMem+3, zP4, -1, SQLITE_UTF8, sqlite3_free);
|
|
+ p->nResColumn = 4;
|
|
}else{
|
|
- assert( pMem->z!=0 );
|
|
- pMem->n = sqlite3Strlen30(pMem->z);
|
|
- pMem->enc = SQLITE_UTF8;
|
|
- }
|
|
- pMem++;
|
|
-
|
|
- if( p->explain==1 ){
|
|
- if( sqlite3VdbeMemClearAndResize(pMem, 4) ){
|
|
- assert( p->db->mallocFailed );
|
|
- return SQLITE_ERROR;
|
|
- }
|
|
- pMem->flags = MEM_Str|MEM_Term;
|
|
- pMem->n = 2;
|
|
- sqlite3_snprintf(3, pMem->z, "%.2x", pOp->p5); /* P5 */
|
|
- pMem->enc = SQLITE_UTF8;
|
|
- pMem++;
|
|
-
|
|
+ sqlite3VdbeMemSetInt64(pMem+0, i);
|
|
+ sqlite3VdbeMemSetStr(pMem+1, (char*)sqlite3OpcodeName(pOp->opcode),
|
|
+ -1, SQLITE_UTF8, SQLITE_STATIC);
|
|
+ sqlite3VdbeMemSetInt64(pMem+2, pOp->p1);
|
|
+ sqlite3VdbeMemSetInt64(pMem+3, pOp->p2);
|
|
+ sqlite3VdbeMemSetInt64(pMem+4, pOp->p3);
|
|
+ /* pMem+5 for p4 is done last */
|
|
+ sqlite3VdbeMemSetInt64(pMem+6, pOp->p5);
|
|
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
- if( sqlite3VdbeMemClearAndResize(pMem, 500) ){
|
|
- assert( p->db->mallocFailed );
|
|
- return SQLITE_ERROR;
|
|
+ {
|
|
+ char *zCom = sqlite3VdbeDisplayComment(db, pOp, zP4);
|
|
+ sqlite3VdbeMemSetStr(pMem+7, zCom, -1, SQLITE_UTF8, sqlite3_free);
|
|
}
|
|
- pMem->flags = MEM_Str|MEM_Term;
|
|
- pMem->n = displayComment(pOp, zP4, pMem->z, 500);
|
|
- pMem->enc = SQLITE_UTF8;
|
|
#else
|
|
- pMem->flags = MEM_Null; /* Comment */
|
|
+ sqlite3VdbeMemSetNull(pMem+7);
|
|
#endif
|
|
+ sqlite3VdbeMemSetStr(pMem+5, zP4, -1, SQLITE_UTF8, sqlite3_free);
|
|
+ p->nResColumn = 8;
|
|
+ }
|
|
+ p->pResultSet = pMem;
|
|
+ if( db->mallocFailed ){
|
|
+ p->rc = SQLITE_NOMEM;
|
|
+ rc = SQLITE_ERROR;
|
|
+ }else{
|
|
+ p->rc = SQLITE_OK;
|
|
+ rc = SQLITE_ROW;
|
|
}
|
|
-
|
|
- p->nResColumn = 8 - 4*(p->explain-1);
|
|
- p->pResultSet = &p->aMem[1];
|
|
- p->rc = SQLITE_OK;
|
|
- rc = SQLITE_ROW;
|
|
}
|
|
}
|
|
return rc;
|
|
@@ -78656,8 +79919,27 @@
|
|
|
|
resolveP2Values(p, &nArg);
|
|
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
|
- if( pParse->explain && nMem<10 ){
|
|
- nMem = 10;
|
|
+ if( pParse->explain ){
|
|
+ static const char * const azColName[] = {
|
|
+ "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
|
|
+ "id", "parent", "notused", "detail"
|
|
+ };
|
|
+ int iFirst, mx, i;
|
|
+ if( nMem<10 ) nMem = 10;
|
|
+ p->explain = pParse->explain;
|
|
+ if( pParse->explain==2 ){
|
|
+ sqlite3VdbeSetNumCols(p, 4);
|
|
+ iFirst = 8;
|
|
+ mx = 12;
|
|
+ }else{
|
|
+ sqlite3VdbeSetNumCols(p, 8);
|
|
+ iFirst = 0;
|
|
+ mx = 8;
|
|
+ }
|
|
+ for(i=iFirst; i<mx; i++){
|
|
+ sqlite3VdbeSetColName(p, i-iFirst, COLNAME_NAME,
|
|
+ azColName[i], SQLITE_STATIC);
|
|
+ }
|
|
}
|
|
p->expired = 0;
|
|
|
|
@@ -78695,7 +79977,6 @@
|
|
|
|
p->pVList = pParse->pVList;
|
|
pParse->pVList = 0;
|
|
- p->explain = pParse->explain;
|
|
if( db->mallocFailed ){
|
|
p->nVar = 0;
|
|
p->nCursor = 0;
|
|
@@ -79007,8 +80288,9 @@
|
|
|
|
/* Select a master journal file name */
|
|
nMainFile = sqlite3Strlen30(zMainFile);
|
|
- zMaster = sqlite3MPrintf(db, "%s-mjXXXXXX9XXz", zMainFile);
|
|
+ zMaster = sqlite3MPrintf(db, "%.4c%s%.16c", 0,zMainFile,0);
|
|
if( zMaster==0 ) return SQLITE_NOMEM_BKPT;
|
|
+ zMaster += 4;
|
|
do {
|
|
u32 iRandom;
|
|
if( retryCount ){
|
|
@@ -79038,7 +80320,7 @@
|
|
);
|
|
}
|
|
if( rc!=SQLITE_OK ){
|
|
- sqlite3DbFree(db, zMaster);
|
|
+ sqlite3DbFree(db, zMaster-4);
|
|
return rc;
|
|
}
|
|
|
|
@@ -79061,7 +80343,7 @@
|
|
if( rc!=SQLITE_OK ){
|
|
sqlite3OsCloseFree(pMaster);
|
|
sqlite3OsDelete(pVfs, zMaster, 0);
|
|
- sqlite3DbFree(db, zMaster);
|
|
+ sqlite3DbFree(db, zMaster-4);
|
|
return rc;
|
|
}
|
|
}
|
|
@@ -79075,7 +80357,7 @@
|
|
){
|
|
sqlite3OsCloseFree(pMaster);
|
|
sqlite3OsDelete(pVfs, zMaster, 0);
|
|
- sqlite3DbFree(db, zMaster);
|
|
+ sqlite3DbFree(db, zMaster-4);
|
|
return rc;
|
|
}
|
|
|
|
@@ -79098,7 +80380,7 @@
|
|
sqlite3OsCloseFree(pMaster);
|
|
assert( rc!=SQLITE_BUSY );
|
|
if( rc!=SQLITE_OK ){
|
|
- sqlite3DbFree(db, zMaster);
|
|
+ sqlite3DbFree(db, zMaster-4);
|
|
return rc;
|
|
}
|
|
|
|
@@ -79107,7 +80389,7 @@
|
|
** transaction files are deleted.
|
|
*/
|
|
rc = sqlite3OsDelete(pVfs, zMaster, 1);
|
|
- sqlite3DbFree(db, zMaster);
|
|
+ sqlite3DbFree(db, zMaster-4);
|
|
zMaster = 0;
|
|
if( rc ){
|
|
return rc;
|
|
@@ -79746,7 +81028,7 @@
|
|
** carried out. Seek the cursor now. If an error occurs, return
|
|
** the appropriate error code.
|
|
*/
|
|
-static int SQLITE_NOINLINE handleDeferredMoveto(VdbeCursor *p){
|
|
+SQLITE_PRIVATE int SQLITE_NOINLINE sqlite3VdbeFinishMoveto(VdbeCursor *p){
|
|
int res, rc;
|
|
#ifdef SQLITE_TEST
|
|
extern int sqlite3_search_count;
|
|
@@ -79813,12 +81095,12 @@
|
|
assert( p->eCurType==CURTYPE_BTREE || p->eCurType==CURTYPE_PSEUDO );
|
|
if( p->deferredMoveto ){
|
|
int iMap;
|
|
- if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 ){
|
|
+ if( p->aAltMap && (iMap = p->aAltMap[1+*piCol])>0 && !p->nullRow ){
|
|
*pp = p->pAltCursor;
|
|
*piCol = iMap - 1;
|
|
return SQLITE_OK;
|
|
}
|
|
- return handleDeferredMoveto(p);
|
|
+ return sqlite3VdbeFinishMoveto(p);
|
|
}
|
|
if( sqlite3BtreeCursorHasMoved(p->uc.pCursor) ){
|
|
return handleMovedCursor(p);
|
|
@@ -79868,10 +81150,17 @@
|
|
** of SQLite will not understand those serial types.
|
|
*/
|
|
|
|
+#if 0 /* Inlined into the OP_MakeRecord opcode */
|
|
/*
|
|
** Return the serial-type for the value stored in pMem.
|
|
**
|
|
** This routine might convert a large MEM_IntReal value into MEM_Real.
|
|
+**
|
|
+** 2019-07-11: The primary user of this subroutine was the OP_MakeRecord
|
|
+** opcode in the byte-code engine. But by moving this routine in-line, we
|
|
+** can omit some redundant tests and make that opcode a lot faster. So
|
|
+** this routine is now only used by the STAT3 logic and STAT3 support has
|
|
+** ended. The code is kept here for historical reference only.
|
|
*/
|
|
SQLITE_PRIVATE u32 sqlite3VdbeSerialType(Mem *pMem, int file_format, u32 *pLen){
|
|
int flags = pMem->flags;
|
|
@@ -79932,6 +81221,7 @@
|
|
*pLen = n;
|
|
return ((n*2) + 12 + ((flags&MEM_Str)!=0));
|
|
}
|
|
+#endif /* inlined into OP_MakeRecord */
|
|
|
|
/*
|
|
** The sizes for serial types less than 128
|
|
@@ -80240,7 +81530,7 @@
|
|
p = (UnpackedRecord *)sqlite3DbMallocRaw(pKeyInfo->db, nByte);
|
|
if( !p ) return 0;
|
|
p->aMem = (Mem*)&((char*)p)[ROUND8(sizeof(UnpackedRecord))];
|
|
- assert( pKeyInfo->aSortOrder!=0 );
|
|
+ assert( pKeyInfo->aSortFlags!=0 );
|
|
p->pKeyInfo = pKeyInfo;
|
|
p->nField = pKeyInfo->nKeyField + 1;
|
|
return p;
|
|
@@ -80339,7 +81629,7 @@
|
|
if( szHdr1>98307 ) return SQLITE_CORRUPT;
|
|
d1 = szHdr1;
|
|
assert( pKeyInfo->nAllField>=pPKey2->nField || CORRUPT_DB );
|
|
- assert( pKeyInfo->aSortOrder!=0 );
|
|
+ assert( pKeyInfo->aSortFlags!=0 );
|
|
assert( pKeyInfo->nKeyField>0 );
|
|
assert( idx1<=szHdr1 || CORRUPT_DB );
|
|
do{
|
|
@@ -80370,7 +81660,12 @@
|
|
pKeyInfo->nAllField>i ? pKeyInfo->aColl[i] : 0);
|
|
if( rc!=0 ){
|
|
assert( mem1.szMalloc==0 ); /* See comment below */
|
|
- if( pKeyInfo->aSortOrder[i] ){
|
|
+ if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
|
|
+ && ((mem1.flags & MEM_Null) || (pPKey2->aMem[i].flags & MEM_Null))
|
|
+ ){
|
|
+ rc = -rc;
|
|
+ }
|
|
+ if( pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC ){
|
|
rc = -rc; /* Invert the result for DESC sort order. */
|
|
}
|
|
goto debugCompareEnd;
|
|
@@ -80746,7 +82041,7 @@
|
|
VVA_ONLY( mem1.szMalloc = 0; ) /* Only needed by assert() statements */
|
|
assert( pPKey2->pKeyInfo->nAllField>=pPKey2->nField
|
|
|| CORRUPT_DB );
|
|
- assert( pPKey2->pKeyInfo->aSortOrder!=0 );
|
|
+ assert( pPKey2->pKeyInfo->aSortFlags!=0 );
|
|
assert( pPKey2->pKeyInfo->nKeyField>0 );
|
|
assert( idx1<=szHdr1 || CORRUPT_DB );
|
|
do{
|
|
@@ -80803,7 +82098,7 @@
|
|
|
|
/* RHS is a string */
|
|
else if( pRhs->flags & MEM_Str ){
|
|
- getVarint32(&aKey1[idx1], serial_type);
|
|
+ getVarint32NR(&aKey1[idx1], serial_type);
|
|
testcase( serial_type==12 );
|
|
if( serial_type<12 ){
|
|
rc = -1;
|
|
@@ -80837,7 +82132,7 @@
|
|
/* RHS is a blob */
|
|
else if( pRhs->flags & MEM_Blob ){
|
|
assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 );
|
|
- getVarint32(&aKey1[idx1], serial_type);
|
|
+ getVarint32NR(&aKey1[idx1], serial_type);
|
|
testcase( serial_type==12 );
|
|
if( serial_type<12 || (serial_type & 0x01) ){
|
|
rc = -1;
|
|
@@ -80869,8 +82164,14 @@
|
|
}
|
|
|
|
if( rc!=0 ){
|
|
- if( pPKey2->pKeyInfo->aSortOrder[i] ){
|
|
- rc = -rc;
|
|
+ int sortFlags = pPKey2->pKeyInfo->aSortFlags[i];
|
|
+ if( sortFlags ){
|
|
+ if( (sortFlags & KEYINFO_ORDER_BIGNULL)==0
|
|
+ || ((sortFlags & KEYINFO_ORDER_DESC)
|
|
+ !=(serial_type==0 || (pRhs->flags&MEM_Null)))
|
|
+ ){
|
|
+ rc = -rc;
|
|
+ }
|
|
}
|
|
assert( vdbeRecordCompareDebug(nKey1, pKey1, pPKey2, rc) );
|
|
assert( mem1.szMalloc==0 ); /* See comment below */
|
|
@@ -81020,7 +82321,10 @@
|
|
|
|
assert( pPKey2->aMem[0].flags & MEM_Str );
|
|
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
|
|
- getVarint32(&aKey1[1], serial_type);
|
|
+ serial_type = (u8)(aKey1[1]);
|
|
+ if( serial_type >= 0x80 ){
|
|
+ sqlite3GetVarint32(&aKey1[1], (u32*)&serial_type);
|
|
+ }
|
|
if( serial_type<12 ){
|
|
res = pPKey2->r1; /* (pKey1/nKey1) is a number or a null */
|
|
}else if( !(serial_type & 0x01) ){
|
|
@@ -81038,7 +82342,11 @@
|
|
nCmp = MIN( pPKey2->aMem[0].n, nStr );
|
|
res = memcmp(&aKey1[szHdr], pPKey2->aMem[0].z, nCmp);
|
|
|
|
- if( res==0 ){
|
|
+ if( res>0 ){
|
|
+ res = pPKey2->r2;
|
|
+ }else if( res<0 ){
|
|
+ res = pPKey2->r1;
|
|
+ }else{
|
|
res = nStr - pPKey2->aMem[0].n;
|
|
if( res==0 ){
|
|
if( pPKey2->nField>1 ){
|
|
@@ -81052,10 +82360,6 @@
|
|
}else{
|
|
res = pPKey2->r1;
|
|
}
|
|
- }else if( res>0 ){
|
|
- res = pPKey2->r2;
|
|
- }else{
|
|
- res = pPKey2->r1;
|
|
}
|
|
}
|
|
|
|
@@ -81087,7 +82391,10 @@
|
|
** header size is (12*5 + 1 + 1) bytes. */
|
|
if( p->pKeyInfo->nAllField<=13 ){
|
|
int flags = p->aMem[0].flags;
|
|
- if( p->pKeyInfo->aSortOrder[0] ){
|
|
+ if( p->pKeyInfo->aSortFlags[0] ){
|
|
+ if( p->pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL ){
|
|
+ return sqlite3VdbeRecordCompare;
|
|
+ }
|
|
p->r1 = 1;
|
|
p->r2 = -1;
|
|
}else{
|
|
@@ -81138,13 +82445,13 @@
|
|
|
|
/* Read in the complete content of the index entry */
|
|
sqlite3VdbeMemInit(&m, db, 0);
|
|
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
|
|
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
|
|
if( rc ){
|
|
return rc;
|
|
}
|
|
|
|
/* The index entry must begin with a header size */
|
|
- (void)getVarint32((u8*)m.z, szHdr);
|
|
+ getVarint32NR((u8*)m.z, szHdr);
|
|
testcase( szHdr==3 );
|
|
testcase( szHdr==m.n );
|
|
testcase( szHdr>0x7fffffff );
|
|
@@ -81155,7 +82462,7 @@
|
|
|
|
/* The last field of the index should be an integer - the ROWID.
|
|
** Verify that the last entry really is an integer. */
|
|
- (void)getVarint32((u8*)&m.z[szHdr-1], typeRowid);
|
|
+ getVarint32NR((u8*)&m.z[szHdr-1], typeRowid);
|
|
testcase( typeRowid==1 );
|
|
testcase( typeRowid==2 );
|
|
testcase( typeRowid==3 );
|
|
@@ -81220,7 +82527,7 @@
|
|
return SQLITE_CORRUPT_BKPT;
|
|
}
|
|
sqlite3VdbeMemInit(&m, db, 0);
|
|
- rc = sqlite3VdbeMemFromBtree(pCur, 0, (u32)nCellKey, &m);
|
|
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCur, (u32)nCellKey, &m);
|
|
if( rc ){
|
|
return rc;
|
|
}
|
|
@@ -81336,13 +82643,25 @@
|
|
** features such as 'now'.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3NotPureFunc(sqlite3_context *pCtx){
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+ const VdbeOp *pOp;
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( pCtx->pVdbe==0 ) return 1;
|
|
#endif
|
|
- if( pCtx->pVdbe->aOp[pCtx->iOp].opcode==OP_PureFunc ){
|
|
- sqlite3_result_error(pCtx,
|
|
- "non-deterministic function in index expression or CHECK constraint",
|
|
- -1);
|
|
+ pOp = pCtx->pVdbe->aOp + pCtx->iOp;
|
|
+ if( pOp->opcode==OP_PureFunc ){
|
|
+ const char *zContext;
|
|
+ char *zMsg;
|
|
+ if( pOp->p5 & NC_IsCheck ){
|
|
+ zContext = "a CHECK constraint";
|
|
+ }else if( pOp->p5 & NC_GenCol ){
|
|
+ zContext = "a generated column";
|
|
+ }else{
|
|
+ zContext = "an index";
|
|
+ }
|
|
+ zMsg = sqlite3_mprintf("non-deterministic use of %s() in %s",
|
|
+ pCtx->pFunc->zName, zContext);
|
|
+ sqlite3_result_error(pCtx, zMsg, -1);
|
|
+ sqlite3_free(zMsg);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
@@ -81433,7 +82752,7 @@
|
|
preupdate.keyinfo.db = db;
|
|
preupdate.keyinfo.enc = ENC(db);
|
|
preupdate.keyinfo.nKeyField = pTab->nCol;
|
|
- preupdate.keyinfo.aSortOrder = (u8*)&fakeSortOrder;
|
|
+ preupdate.keyinfo.aSortFlags = (u8*)&fakeSortOrder;
|
|
preupdate.iKey1 = iKey1;
|
|
preupdate.iKey2 = iKey2;
|
|
preupdate.pTab = pTab;
|
|
@@ -82121,7 +83440,7 @@
|
|
** from interrupting a statement that has not yet started.
|
|
*/
|
|
if( db->nVdbeActive==0 ){
|
|
- db->u1.isInterrupted = 0;
|
|
+ AtomicStore(&db->u1.isInterrupted, 0);
|
|
}
|
|
|
|
assert( db->nVdbeWrite>0 || db->autoCommit==0
|
|
@@ -82302,7 +83621,7 @@
|
|
*/
|
|
SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
|
|
int rc;
|
|
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifndef SQLITE_ENABLE_STAT4
|
|
sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
|
|
assert( p->pVdbe!=0 );
|
|
#else
|
|
@@ -82367,7 +83686,7 @@
|
|
AuxData *pAuxData;
|
|
|
|
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
|
-#if SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#if SQLITE_ENABLE_STAT4
|
|
if( pCtx->pVdbe==0 ) return 0;
|
|
#else
|
|
assert( pCtx->pVdbe!=0 );
|
|
@@ -82401,7 +83720,7 @@
|
|
Vdbe *pVdbe = pCtx->pVdbe;
|
|
|
|
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( pVdbe==0 ) goto failed;
|
|
#else
|
|
assert( pVdbe!=0 );
|
|
@@ -82813,7 +84132,7 @@
|
|
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
|
|
** binding a new value to this variable invalidates the current query plan.
|
|
**
|
|
- ** IMPLEMENTATION-OF: R-48440-37595 If the specific value bound to host
|
|
+ ** IMPLEMENTATION-OF: R-57496-20354 If the specific value bound to a host
|
|
** parameter in the WHERE clause might influence the choice of query plan
|
|
** for a statement, then the statement will be automatically recompiled,
|
|
** as if there had been a schema change, on the first sqlite3_step() call
|
|
@@ -83289,7 +84608,7 @@
|
|
goto preupdate_old_out;
|
|
}
|
|
if( p->pPk ){
|
|
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
|
|
+ iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
|
|
}
|
|
if( iIdx>=p->pCsr->nField || iIdx<0 ){
|
|
rc = SQLITE_RANGE;
|
|
@@ -83379,7 +84698,7 @@
|
|
goto preupdate_new_out;
|
|
}
|
|
if( p->pPk && p->op!=SQLITE_UPDATE ){
|
|
- iIdx = sqlite3ColumnOfIndex(p->pPk, iIdx);
|
|
+ iIdx = sqlite3TableColumnToIndex(p->pPk, iIdx);
|
|
}
|
|
if( iIdx>=p->pCsr->nField || iIdx<0 ){
|
|
rc = SQLITE_RANGE;
|
|
@@ -83827,6 +85146,26 @@
|
|
# define UPDATE_MAX_BLOBSIZE(P)
|
|
#endif
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+/* This routine provides a convenient place to set a breakpoint during
|
|
+** tracing with PRAGMA vdbe_trace=on. The breakpoint fires right after
|
|
+** each opcode is printed. Variables "pc" (program counter) and pOp are
|
|
+** available to add conditionals to the breakpoint. GDB example:
|
|
+**
|
|
+** break test_trace_breakpoint if pc=22
|
|
+**
|
|
+** Other useful labels for breakpoints include:
|
|
+** test_addop_breakpoint(pc,pOp)
|
|
+** sqlite3CorruptError(lineno)
|
|
+** sqlite3MisuseError(lineno)
|
|
+** sqlite3CantopenError(lineno)
|
|
+*/
|
|
+static void test_trace_breakpoint(int pc, Op *pOp, Vdbe *v){
|
|
+ static int n = 0;
|
|
+ n++;
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
** Invoke the VDBE coverage callback, if that callback is defined. This
|
|
** feature is used for test suite validation only and does not appear an
|
|
@@ -84053,6 +85392,7 @@
|
|
** Convert pRec to a text representation.
|
|
**
|
|
** SQLITE_AFF_BLOB:
|
|
+** SQLITE_AFF_NONE:
|
|
** No-op. pRec is unchanged.
|
|
*/
|
|
static void applyAffinity(
|
|
@@ -84170,12 +85510,9 @@
|
|
** Write a nice string representation of the contents of cell pMem
|
|
** into buffer zBuf, length nBuf.
|
|
*/
|
|
-SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf){
|
|
- char *zCsr = zBuf;
|
|
+SQLITE_PRIVATE void sqlite3VdbeMemPrettyPrint(Mem *pMem, StrAccum *pStr){
|
|
int f = pMem->flags;
|
|
-
|
|
static const char *const encnames[] = {"(X)", "(8)", "(16LE)", "(16BE)"};
|
|
-
|
|
if( f&MEM_Blob ){
|
|
int i;
|
|
char c;
|
|
@@ -84191,55 +85528,40 @@
|
|
}else{
|
|
c = 's';
|
|
}
|
|
- *(zCsr++) = c;
|
|
- sqlite3_snprintf(100, zCsr, "%d[", pMem->n);
|
|
- zCsr += sqlite3Strlen30(zCsr);
|
|
- for(i=0; i<16 && i<pMem->n; i++){
|
|
- sqlite3_snprintf(100, zCsr, "%02X", ((int)pMem->z[i] & 0xFF));
|
|
- zCsr += sqlite3Strlen30(zCsr);
|
|
+ sqlite3_str_appendf(pStr, "%cx[", c);
|
|
+ for(i=0; i<25 && i<pMem->n; i++){
|
|
+ sqlite3_str_appendf(pStr, "%02X", ((int)pMem->z[i] & 0xFF));
|
|
}
|
|
- for(i=0; i<16 && i<pMem->n; i++){
|
|
+ sqlite3_str_appendf(pStr, "|");
|
|
+ for(i=0; i<25 && i<pMem->n; i++){
|
|
char z = pMem->z[i];
|
|
- if( z<32 || z>126 ) *zCsr++ = '.';
|
|
- else *zCsr++ = z;
|
|
+ sqlite3_str_appendchar(pStr, 1, (z<32||z>126)?'.':z);
|
|
}
|
|
- *(zCsr++) = ']';
|
|
+ sqlite3_str_appendf(pStr,"]");
|
|
if( f & MEM_Zero ){
|
|
- sqlite3_snprintf(100, zCsr,"+%dz",pMem->u.nZero);
|
|
- zCsr += sqlite3Strlen30(zCsr);
|
|
+ sqlite3_str_appendf(pStr, "+%dz",pMem->u.nZero);
|
|
}
|
|
- *zCsr = '\0';
|
|
}else if( f & MEM_Str ){
|
|
- int j, k;
|
|
- zBuf[0] = ' ';
|
|
+ int j;
|
|
+ u8 c;
|
|
if( f & MEM_Dyn ){
|
|
- zBuf[1] = 'z';
|
|
+ c = 'z';
|
|
assert( (f & (MEM_Static|MEM_Ephem))==0 );
|
|
}else if( f & MEM_Static ){
|
|
- zBuf[1] = 't';
|
|
+ c = 't';
|
|
assert( (f & (MEM_Dyn|MEM_Ephem))==0 );
|
|
}else if( f & MEM_Ephem ){
|
|
- zBuf[1] = 'e';
|
|
+ c = 'e';
|
|
assert( (f & (MEM_Static|MEM_Dyn))==0 );
|
|
}else{
|
|
- zBuf[1] = 's';
|
|
+ c = 's';
|
|
}
|
|
- k = 2;
|
|
- sqlite3_snprintf(100, &zBuf[k], "%d", pMem->n);
|
|
- k += sqlite3Strlen30(&zBuf[k]);
|
|
- zBuf[k++] = '[';
|
|
- for(j=0; j<15 && j<pMem->n; j++){
|
|
- u8 c = pMem->z[j];
|
|
- if( c>=0x20 && c<0x7f ){
|
|
- zBuf[k++] = c;
|
|
- }else{
|
|
- zBuf[k++] = '.';
|
|
- }
|
|
+ sqlite3_str_appendf(pStr, " %c%d[", c, pMem->n);
|
|
+ for(j=0; j<25 && j<pMem->n; j++){
|
|
+ c = pMem->z[j];
|
|
+ sqlite3_str_appendchar(pStr, 1, (c>=0x20&&c<=0x7f) ? c : '.');
|
|
}
|
|
- zBuf[k++] = ']';
|
|
- sqlite3_snprintf(100,&zBuf[k], encnames[pMem->enc]);
|
|
- k += sqlite3Strlen30(&zBuf[k]);
|
|
- zBuf[k++] = 0;
|
|
+ sqlite3_str_appendf(pStr, "]%s", encnames[pMem->enc]);
|
|
}
|
|
}
|
|
#endif
|
|
@@ -84261,25 +85583,42 @@
|
|
printf(" i:%lld", p->u.i);
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
}else if( p->flags & MEM_Real ){
|
|
- printf(" r:%g", p->u.r);
|
|
+ printf(" r:%.17g", p->u.r);
|
|
#endif
|
|
}else if( sqlite3VdbeMemIsRowSet(p) ){
|
|
printf(" (rowset)");
|
|
}else{
|
|
- char zBuf[200];
|
|
- sqlite3VdbeMemPrettyPrint(p, zBuf);
|
|
- printf(" %s", zBuf);
|
|
+ StrAccum acc;
|
|
+ char zBuf[1000];
|
|
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
|
+ sqlite3VdbeMemPrettyPrint(p, &acc);
|
|
+ printf(" %s", sqlite3StrAccumFinish(&acc));
|
|
}
|
|
if( p->flags & MEM_Subtype ) printf(" subtype=0x%02x", p->eSubtype);
|
|
}
|
|
static void registerTrace(int iReg, Mem *p){
|
|
- printf("REG[%d] = ", iReg);
|
|
+ printf("R[%d] = ", iReg);
|
|
memTracePrint(p);
|
|
+ if( p->pScopyFrom ){
|
|
+ printf(" <== R[%d]", (int)(p->pScopyFrom - &p[-iReg]));
|
|
+ }
|
|
printf("\n");
|
|
sqlite3VdbeCheckMemInvariants(p);
|
|
}
|
|
#endif
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+/*
|
|
+** Show the values of all registers in the virtual machine. Used for
|
|
+** interactive debugging.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3VdbeRegisterDump(Vdbe *v){
|
|
+ int i;
|
|
+ for(i=1; i<v->nMem; i++) registerTrace(i, v->aMem+i);
|
|
+}
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
+
|
|
#ifdef SQLITE_DEBUG
|
|
# define REGISTER_TRACE(R,M) if(db->flags&SQLITE_VdbeTrace)registerTrace(R,M)
|
|
#else
|
|
@@ -84308,7 +85647,7 @@
|
|
******************************************************************************
|
|
**
|
|
** This file contains inline asm code for retrieving "high-performance"
|
|
-** counters for x86 class CPUs.
|
|
+** counters for x86 and x86_64 class CPUs.
|
|
*/
|
|
#ifndef SQLITE_HWTIME_H
|
|
#define SQLITE_HWTIME_H
|
|
@@ -84319,8 +85658,9 @@
|
|
** processor and returns that value. This can be used for high-res
|
|
** profiling.
|
|
*/
|
|
-#if (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
- (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
+#if !defined(__STRICT_ANSI__) && \
|
|
+ (defined(__GNUC__) || defined(_MSC_VER)) && \
|
|
+ (defined(i386) || defined(__i386__) || defined(_M_IX86))
|
|
|
|
#if defined(__GNUC__)
|
|
|
|
@@ -84341,7 +85681,7 @@
|
|
|
|
#endif
|
|
|
|
-#elif (defined(__GNUC__) && defined(__x86_64__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__x86_64__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long val;
|
|
@@ -84349,7 +85689,7 @@
|
|
return val;
|
|
}
|
|
|
|
-#elif (defined(__GNUC__) && defined(__ppc__))
|
|
+#elif !defined(__STRICT_ANSI__) && (defined(__GNUC__) && defined(__ppc__))
|
|
|
|
__inline__ sqlite_uint64 sqlite3Hwtime(void){
|
|
unsigned long long retval;
|
|
@@ -84366,14 +85706,13 @@
|
|
|
|
#else
|
|
|
|
- #error Need implementation of sqlite3Hwtime() for your platform.
|
|
-
|
|
/*
|
|
- ** To compile without implementing sqlite3Hwtime() for your platform,
|
|
- ** you can remove the above #error and use the following
|
|
- ** stub function. You will lose timing support for many
|
|
- ** of the debugging and testing utilities, but it should at
|
|
- ** least compile and run.
|
|
+ ** asm() is needed for hardware timing support. Without asm(),
|
|
+ ** disable the sqlite3Hwtime() routine.
|
|
+ **
|
|
+ ** sqlite3Hwtime() is only used for some obscure debugging
|
|
+ ** and analysis configurations, not in any deliverable, so this
|
|
+ ** should not be a great loss.
|
|
*/
|
|
SQLITE_PRIVATE sqlite_uint64 sqlite3Hwtime(void){ return ((sqlite_uint64)0); }
|
|
|
|
@@ -84481,12 +85820,14 @@
|
|
goto no_mem;
|
|
}
|
|
assert( p->rc==SQLITE_OK || (p->rc&0xff)==SQLITE_BUSY );
|
|
+ testcase( p->rc!=SQLITE_OK );
|
|
+ p->rc = SQLITE_OK;
|
|
assert( p->bIsReader || p->readOnly!=0 );
|
|
p->iCurrentTime = 0;
|
|
assert( p->explain==0 );
|
|
p->pResultSet = 0;
|
|
db->busyHandler.nBusy = 0;
|
|
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
|
+ if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
|
|
sqlite3VdbeIOTraceSql(p);
|
|
#ifdef SQLITE_DEBUG
|
|
sqlite3BeginBenignMalloc();
|
|
@@ -84534,6 +85875,7 @@
|
|
#ifdef SQLITE_DEBUG
|
|
if( db->flags & SQLITE_VdbeTrace ){
|
|
sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
|
|
+ test_trace_breakpoint((int)(pOp - aOp),pOp,p);
|
|
}
|
|
#endif
|
|
|
|
@@ -84641,6 +85983,20 @@
|
|
** to the current line should be indented for EXPLAIN output.
|
|
*/
|
|
case OP_Goto: { /* jump */
|
|
+
|
|
+#ifdef SQLITE_DEBUG
|
|
+ /* In debuggging mode, when the p5 flags is set on an OP_Goto, that
|
|
+ ** means we should really jump back to the preceeding OP_ReleaseReg
|
|
+ ** instruction. */
|
|
+ if( pOp->p5 ){
|
|
+ assert( pOp->p2 < (int)(pOp - aOp) );
|
|
+ assert( pOp->p2 > 1 );
|
|
+ pOp = &aOp[pOp->p2 - 2];
|
|
+ assert( pOp[1].opcode==OP_ReleaseReg );
|
|
+ goto check_for_interrupt;
|
|
+ }
|
|
+#endif
|
|
+
|
|
jump_to_p2_and_check_for_interrupt:
|
|
pOp = &aOp[pOp->p2 - 1];
|
|
|
|
@@ -84655,7 +86011,7 @@
|
|
** checks on every opcode. This helps sqlite3_step() to run about 1.5%
|
|
** faster according to "valgrind --tool=cachegrind" */
|
|
check_for_interrupt:
|
|
- if( db->u1.isInterrupted ) goto abort_due_to_interrupt;
|
|
+ if( AtomicLoad(&db->u1.isInterrupted) ) goto abort_due_to_interrupt;
|
|
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
|
/* Call the progress callback if it is configured and the required number
|
|
** of VDBE ops have been executed (either since this invocation of
|
|
@@ -84939,7 +86295,6 @@
|
|
case OP_String8: { /* same as TK_STRING, out2 */
|
|
assert( pOp->p4.z!=0 );
|
|
pOut = out2Prerelease(p, pOp);
|
|
- pOp->opcode = OP_String;
|
|
pOp->p1 = sqlite3Strlen30(pOp->p4.z);
|
|
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
@@ -84963,6 +86318,7 @@
|
|
if( pOp->p1>db->aLimit[SQLITE_LIMIT_LENGTH] ){
|
|
goto too_big;
|
|
}
|
|
+ pOp->opcode = OP_String;
|
|
assert( rc==SQLITE_OK );
|
|
/* Fall through to the next case, OP_String */
|
|
}
|
|
@@ -85117,8 +86473,13 @@
|
|
memAboutToChange(p, pOut);
|
|
sqlite3VdbeMemMove(pOut, pIn1);
|
|
#ifdef SQLITE_DEBUG
|
|
- if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
|
|
- pOut->pScopyFrom += pOp->p2 - p1;
|
|
+ pIn1->pScopyFrom = 0;
|
|
+ { int i;
|
|
+ for(i=1; i<p->nMem; i++){
|
|
+ if( aMem[i].pScopyFrom==pIn1 ){
|
|
+ aMem[i].pScopyFrom = pOut;
|
|
+ }
|
|
+ }
|
|
}
|
|
#endif
|
|
Deephemeralize(pOut);
|
|
@@ -85259,6 +86620,14 @@
|
|
|| (pMem[i].flags & (MEM_Str|MEM_Blob))==0 );
|
|
sqlite3VdbeMemNulTerminate(&pMem[i]);
|
|
REGISTER_TRACE(pOp->p1+i, &pMem[i]);
|
|
+#ifdef SQLITE_DEBUG
|
|
+ /* The registers in the result will not be used again when the
|
|
+ ** prepared statement restarts. This is because sqlite3_column()
|
|
+ ** APIs might have caused type conversions of made other changes to
|
|
+ ** the register values. Therefore, we can go ahead and break any
|
|
+ ** OP_SCopy dependencies. */
|
|
+ pMem[i].pScopyFrom = 0;
|
|
+#endif
|
|
}
|
|
if( db->mallocFailed ) goto no_mem;
|
|
|
|
@@ -85266,6 +86635,7 @@
|
|
db->xTrace(SQLITE_TRACE_ROW, db->pTraceArg, p, 0);
|
|
}
|
|
|
|
+
|
|
/* Return SQLITE_ROW
|
|
*/
|
|
p->pc = (int)(pOp - aOp) + 1;
|
|
@@ -85294,7 +86664,6 @@
|
|
pIn1 = &aMem[pOp->p1];
|
|
pIn2 = &aMem[pOp->p2];
|
|
pOut = &aMem[pOp->p3];
|
|
- testcase( pIn1==pIn2 );
|
|
testcase( pOut==pIn2 );
|
|
assert( pIn1!=pOut );
|
|
flags1 = pIn1->flags;
|
|
@@ -85630,6 +86999,7 @@
|
|
testcase( pIn1->flags & MEM_Int );
|
|
testcase( pIn1->flags & MEM_IntReal );
|
|
sqlite3VdbeMemRealify(pIn1);
|
|
+ REGISTER_TRACE(pOp->p1, pIn1);
|
|
}
|
|
break;
|
|
}
|
|
@@ -85661,9 +87031,11 @@
|
|
pIn1 = &aMem[pOp->p1];
|
|
memAboutToChange(p, pIn1);
|
|
rc = ExpandBlob(pIn1);
|
|
- sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
|
|
- UPDATE_MAX_BLOBSIZE(pIn1);
|
|
if( rc ) goto abort_due_to_error;
|
|
+ rc = sqlite3VdbeMemCast(pIn1, pOp->p2, encoding);
|
|
+ if( rc ) goto abort_due_to_error;
|
|
+ UPDATE_MAX_BLOBSIZE(pIn1);
|
|
+ REGISTER_TRACE(pOp->p1, pIn1);
|
|
break;
|
|
}
|
|
#endif /* SQLITE_OMIT_CAST */
|
|
@@ -85823,11 +87195,6 @@
|
|
if( (flags1 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
|
|
applyNumericAffinity(pIn1,0);
|
|
assert( flags3==pIn3->flags );
|
|
- /* testcase( flags3!=pIn3->flags );
|
|
- ** this used to be possible with pIn1==pIn3, but not since
|
|
- ** the column cache was removed. The following assignment
|
|
- ** is essentially a no-op. But, it provides defense-in-depth
|
|
- ** in case our analysis is incorrect, so it is left in. */
|
|
flags3 = pIn3->flags;
|
|
}
|
|
if( (flags3 & (MEM_Int|MEM_IntReal|MEM_Real|MEM_Str))==MEM_Str ){
|
|
@@ -85850,7 +87217,7 @@
|
|
sqlite3VdbeMemStringify(pIn1, encoding, 1);
|
|
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
|
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
|
- assert( pIn1!=pIn3 );
|
|
+ if( NEVER(pIn1==pIn3) ) flags3 = flags1 | MEM_Str;
|
|
}
|
|
if( (flags3 & MEM_Str)==0 && (flags3&(MEM_Int|MEM_Real|MEM_IntReal))!=0 ){
|
|
testcase( pIn3->flags & MEM_Int );
|
|
@@ -85885,10 +87252,10 @@
|
|
}
|
|
|
|
/* Undo any changes made by applyAffinity() to the input registers. */
|
|
- assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
|
|
- pIn1->flags = flags1;
|
|
assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
|
|
pIn3->flags = flags3;
|
|
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
|
|
+ pIn1->flags = flags1;
|
|
|
|
if( pOp->p5 & SQLITE_STOREP2 ){
|
|
pOut = &aMem[pOp->p2];
|
|
@@ -85924,16 +87291,31 @@
|
|
|
|
/* Opcode: ElseNotEq * P2 * * *
|
|
**
|
|
-** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator.
|
|
-** If result of an OP_Eq comparison on the same two operands
|
|
-** would have be NULL or false (0), then then jump to P2.
|
|
-** If the result of an OP_Eq comparison on the two previous operands
|
|
-** would have been true (1), then fall through.
|
|
+** This opcode must follow an OP_Lt or OP_Gt comparison operator. There
|
|
+** can be zero or more OP_ReleaseReg opcodes intervening, but no other
|
|
+** opcodes are allowed to occur between this instruction and the previous
|
|
+** OP_Lt or OP_Gt. Furthermore, the prior OP_Lt or OP_Gt must have the
|
|
+** SQLITE_STOREP2 bit set in the P5 field.
|
|
+**
|
|
+** If result of an OP_Eq comparison on the same two operands as the
|
|
+** prior OP_Lt or OP_Gt would have been NULL or false (0), then then
|
|
+** jump to P2. If the result of an OP_Eq comparison on the two previous
|
|
+** operands would have been true (1), then fall through.
|
|
*/
|
|
case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
|
|
- assert( pOp>aOp );
|
|
- assert( pOp[-1].opcode==OP_Lt || pOp[-1].opcode==OP_Gt );
|
|
- assert( pOp[-1].p5 & SQLITE_STOREP2 );
|
|
+
|
|
+#ifdef SQLITE_DEBUG
|
|
+ /* Verify the preconditions of this opcode - that it follows an OP_Lt or
|
|
+ ** OP_Gt with the SQLITE_STOREP2 flag set, with zero or more intervening
|
|
+ ** OP_ReleaseReg opcodes */
|
|
+ int iAddr;
|
|
+ for(iAddr = (int)(pOp - aOp) - 1; ALWAYS(iAddr>=0); iAddr--){
|
|
+ if( aOp[iAddr].opcode==OP_ReleaseReg ) continue;
|
|
+ assert( aOp[iAddr].opcode==OP_Lt || aOp[iAddr].opcode==OP_Gt );
|
|
+ assert( aOp[iAddr].p5 & SQLITE_STOREP2 );
|
|
+ break;
|
|
+ }
|
|
+#endif /* SQLITE_DEBUG */
|
|
VdbeBranchTaken(iCompare!=0, 2);
|
|
if( iCompare!=0 ) goto jump_to_p2;
|
|
break;
|
|
@@ -86025,9 +87407,14 @@
|
|
REGISTER_TRACE(p2+idx, &aMem[p2+idx]);
|
|
assert( i<pKeyInfo->nKeyField );
|
|
pColl = pKeyInfo->aColl[i];
|
|
- bRev = pKeyInfo->aSortOrder[i];
|
|
+ bRev = (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_DESC);
|
|
iCompare = sqlite3MemCompare(&aMem[p1+idx], &aMem[p2+idx], pColl);
|
|
if( iCompare ){
|
|
+ if( (pKeyInfo->aSortFlags[i] & KEYINFO_ORDER_BIGNULL)
|
|
+ && ((aMem[p1+idx].flags & MEM_Null) || (aMem[p2+idx].flags & MEM_Null))
|
|
+ ){
|
|
+ iCompare = -iCompare;
|
|
+ }
|
|
if( bRev ) iCompare = -iCompare;
|
|
break;
|
|
}
|
|
@@ -86318,11 +87705,6 @@
|
|
** if the P4 argument is a P4_MEM use the value of the P4 argument as
|
|
** the result.
|
|
**
|
|
-** If the OPFLAG_CLEARCACHE bit is set on P5 and P1 is a pseudo-table cursor,
|
|
-** then the cache of the cursor is reset prior to extracting the column.
|
|
-** The first OP_Column against a pseudo-table after the value of the content
|
|
-** register has changed should have this bit set.
|
|
-**
|
|
** If the OPFLAG_LENGTHARG and OPFLAG_TYPEOFARG bits are set on P5 then
|
|
** the result is guaranteed to only be used as the argument of a length()
|
|
** or typeof() function, respectively. The loading of large blobs can be
|
|
@@ -86344,7 +87726,9 @@
|
|
u32 t; /* A type code from the record header */
|
|
Mem *pReg; /* PseudoTable input register */
|
|
|
|
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
pC = p->apCsr[pOp->p1];
|
|
+ assert( pC!=0 );
|
|
p2 = pOp->p2;
|
|
|
|
/* If the cursor cache is stale (meaning it is not currently point at
|
|
@@ -86356,7 +87740,6 @@
|
|
assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
|
|
pDest = &aMem[pOp->p3];
|
|
memAboutToChange(p, pDest);
|
|
- assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
assert( pC!=0 );
|
|
assert( p2<pC->nField );
|
|
aOffset = pC->aOffset;
|
|
@@ -86449,7 +87832,7 @@
|
|
/* Make sure zData points to enough of the record to cover the header. */
|
|
if( pC->aRow==0 ){
|
|
memset(&sMem, 0, sizeof(sMem));
|
|
- rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, 0, aOffset[0], &sMem);
|
|
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pC->uc.pCursor,aOffset[0],&sMem);
|
|
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
|
zData = (u8*)sMem.z;
|
|
}else{
|
|
@@ -86567,10 +87950,11 @@
|
|
**
|
|
** Although sqlite3VdbeSerialGet() may read at most 8 bytes from the
|
|
** buffer passed to it, debugging function VdbeMemPrettyPrint() may
|
|
- ** read up to 16. So 16 bytes of bogus content is supplied.
|
|
+ ** read more. Use the global constant sqlite3CtypeMap[] as the array,
|
|
+ ** as that array is 256 bytes long (plenty for VdbeMemPrettyPrint())
|
|
+ ** and it begins with a bunch of zeros.
|
|
*/
|
|
- static u8 aZero[16]; /* This is the bogus content */
|
|
- sqlite3VdbeSerialGet(aZero, t, pDest);
|
|
+ sqlite3VdbeSerialGet((u8*)sqlite3CtypeMap, t, pDest);
|
|
}else{
|
|
rc = sqlite3VdbeMemFromBtree(pC->uc.pCursor, aOffset[p2], len, pDest);
|
|
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
|
@@ -86611,15 +87995,27 @@
|
|
assert( pOp->p2>0 );
|
|
assert( zAffinity[pOp->p2]==0 );
|
|
pIn1 = &aMem[pOp->p1];
|
|
- while( 1 /*edit-by-break*/ ){
|
|
+ while( 1 /*exit-by-break*/ ){
|
|
assert( pIn1 <= &p->aMem[(p->nMem+1 - p->nCursor)] );
|
|
- assert( memIsValid(pIn1) );
|
|
+ assert( zAffinity[0]==SQLITE_AFF_NONE || memIsValid(pIn1) );
|
|
applyAffinity(pIn1, zAffinity[0], encoding);
|
|
if( zAffinity[0]==SQLITE_AFF_REAL && (pIn1->flags & MEM_Int)!=0 ){
|
|
- /* When applying REAL affinity, if the result is still MEM_Int,
|
|
- ** indicate that REAL is actually desired */
|
|
- pIn1->flags |= MEM_IntReal;
|
|
- pIn1->flags &= ~MEM_Int;
|
|
+ /* When applying REAL affinity, if the result is still an MEM_Int
|
|
+ ** that will fit in 6 bytes, then change the type to MEM_IntReal
|
|
+ ** so that we keep the high-resolution integer value but know that
|
|
+ ** the type really wants to be REAL. */
|
|
+ testcase( pIn1->u.i==140737488355328LL );
|
|
+ testcase( pIn1->u.i==140737488355327LL );
|
|
+ testcase( pIn1->u.i==-140737488355328LL );
|
|
+ testcase( pIn1->u.i==-140737488355329LL );
|
|
+ if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){
|
|
+ pIn1->flags |= MEM_IntReal;
|
|
+ pIn1->flags &= ~MEM_Int;
|
|
+ }else{
|
|
+ pIn1->u.r = (double)pIn1->u.i;
|
|
+ pIn1->flags |= MEM_Real;
|
|
+ pIn1->flags &= ~MEM_Int;
|
|
+ }
|
|
}
|
|
REGISTER_TRACE((int)(pIn1-aMem), pIn1);
|
|
zAffinity++;
|
|
@@ -86726,14 +88122,36 @@
|
|
#endif
|
|
|
|
/* Loop through the elements that will make up the record to figure
|
|
- ** out how much space is required for the new record.
|
|
+ ** out how much space is required for the new record. After this loop,
|
|
+ ** the Mem.uTemp field of each term should hold the serial-type that will
|
|
+ ** be used for that term in the generated record:
|
|
+ **
|
|
+ ** Mem.uTemp value type
|
|
+ ** --------------- ---------------
|
|
+ ** 0 NULL
|
|
+ ** 1 1-byte signed integer
|
|
+ ** 2 2-byte signed integer
|
|
+ ** 3 3-byte signed integer
|
|
+ ** 4 4-byte signed integer
|
|
+ ** 5 6-byte signed integer
|
|
+ ** 6 8-byte signed integer
|
|
+ ** 7 IEEE float
|
|
+ ** 8 Integer constant 0
|
|
+ ** 9 Integer constant 1
|
|
+ ** 10,11 reserved for expansion
|
|
+ ** N>=12 and even BLOB
|
|
+ ** N>=13 and odd text
|
|
+ **
|
|
+ ** The following additional values are computed:
|
|
+ ** nHdr Number of bytes needed for the record header
|
|
+ ** nData Number of bytes of data space needed for the record
|
|
+ ** nZero Zero bytes at the end of the record
|
|
*/
|
|
pRec = pLast;
|
|
do{
|
|
assert( memIsValid(pRec) );
|
|
- serial_type = sqlite3VdbeSerialType(pRec, file_format, &len);
|
|
- if( pRec->flags & MEM_Zero ){
|
|
- if( serial_type==0 ){
|
|
+ if( pRec->flags & MEM_Null ){
|
|
+ if( pRec->flags & MEM_Zero ){
|
|
/* Values with MEM_Null and MEM_Zero are created by xColumn virtual
|
|
** table methods that never invoke sqlite3_result_xxxxx() while
|
|
** computing an unchanging column value in an UPDATE statement.
|
|
@@ -86741,19 +88159,83 @@
|
|
** so that they can be passed through to xUpdate and have
|
|
** a true sqlite3_value_nochange(). */
|
|
assert( pOp->p5==OPFLAG_NOCHNG_MAGIC || CORRUPT_DB );
|
|
- serial_type = 10;
|
|
- }else if( nData ){
|
|
- if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
|
|
+ pRec->uTemp = 10;
|
|
+ }else{
|
|
+ pRec->uTemp = 0;
|
|
+ }
|
|
+ nHdr++;
|
|
+ }else if( pRec->flags & (MEM_Int|MEM_IntReal) ){
|
|
+ /* Figure out whether to use 1, 2, 4, 6 or 8 bytes. */
|
|
+ i64 i = pRec->u.i;
|
|
+ u64 uu;
|
|
+ testcase( pRec->flags & MEM_Int );
|
|
+ testcase( pRec->flags & MEM_IntReal );
|
|
+ if( i<0 ){
|
|
+ uu = ~i;
|
|
}else{
|
|
- nZero += pRec->u.nZero;
|
|
- len -= pRec->u.nZero;
|
|
+ uu = i;
|
|
+ }
|
|
+ nHdr++;
|
|
+ testcase( uu==127 ); testcase( uu==128 );
|
|
+ testcase( uu==32767 ); testcase( uu==32768 );
|
|
+ testcase( uu==8388607 ); testcase( uu==8388608 );
|
|
+ testcase( uu==2147483647 ); testcase( uu==2147483648 );
|
|
+ testcase( uu==140737488355327LL ); testcase( uu==140737488355328LL );
|
|
+ if( uu<=127 ){
|
|
+ if( (i&1)==i && file_format>=4 ){
|
|
+ pRec->uTemp = 8+(u32)uu;
|
|
+ }else{
|
|
+ nData++;
|
|
+ pRec->uTemp = 1;
|
|
+ }
|
|
+ }else if( uu<=32767 ){
|
|
+ nData += 2;
|
|
+ pRec->uTemp = 2;
|
|
+ }else if( uu<=8388607 ){
|
|
+ nData += 3;
|
|
+ pRec->uTemp = 3;
|
|
+ }else if( uu<=2147483647 ){
|
|
+ nData += 4;
|
|
+ pRec->uTemp = 4;
|
|
+ }else if( uu<=140737488355327LL ){
|
|
+ nData += 6;
|
|
+ pRec->uTemp = 5;
|
|
+ }else{
|
|
+ nData += 8;
|
|
+ if( pRec->flags & MEM_IntReal ){
|
|
+ /* If the value is IntReal and is going to take up 8 bytes to store
|
|
+ ** as an integer, then we might as well make it an 8-byte floating
|
|
+ ** point value */
|
|
+ pRec->u.r = (double)pRec->u.i;
|
|
+ pRec->flags &= ~MEM_IntReal;
|
|
+ pRec->flags |= MEM_Real;
|
|
+ pRec->uTemp = 7;
|
|
+ }else{
|
|
+ pRec->uTemp = 6;
|
|
+ }
|
|
+ }
|
|
+ }else if( pRec->flags & MEM_Real ){
|
|
+ nHdr++;
|
|
+ nData += 8;
|
|
+ pRec->uTemp = 7;
|
|
+ }else{
|
|
+ assert( db->mallocFailed || pRec->flags&(MEM_Str|MEM_Blob) );
|
|
+ assert( pRec->n>=0 );
|
|
+ len = (u32)pRec->n;
|
|
+ serial_type = (len*2) + 12 + ((pRec->flags & MEM_Str)!=0);
|
|
+ if( pRec->flags & MEM_Zero ){
|
|
+ serial_type += pRec->u.nZero*2;
|
|
+ if( nData ){
|
|
+ if( sqlite3VdbeMemExpandBlob(pRec) ) goto no_mem;
|
|
+ len += pRec->u.nZero;
|
|
+ }else{
|
|
+ nZero += pRec->u.nZero;
|
|
+ }
|
|
}
|
|
+ nData += len;
|
|
+ nHdr += sqlite3VarintLen(serial_type);
|
|
+ pRec->uTemp = serial_type;
|
|
}
|
|
- nData += len;
|
|
- testcase( serial_type==127 );
|
|
- testcase( serial_type==128 );
|
|
- nHdr += serial_type<=127 ? 1 : sqlite3VarintLen(serial_type);
|
|
- pRec->uTemp = serial_type;
|
|
if( pRec==pData0 ) break;
|
|
pRec--;
|
|
}while(1);
|
|
@@ -86825,13 +88307,16 @@
|
|
break;
|
|
}
|
|
|
|
-/* Opcode: Count P1 P2 * * *
|
|
+/* Opcode: Count P1 P2 p3 * *
|
|
** Synopsis: r[P2]=count()
|
|
**
|
|
** Store the number of entries (an integer value) in the table or index
|
|
-** opened by cursor P1 in register P2
|
|
+** opened by cursor P1 in register P2.
|
|
+**
|
|
+** If P3==0, then an exact count is obtained, which involves visiting
|
|
+** every btree page of the table. But if P3 is non-zero, an estimate
|
|
+** is returned based on the current cursor position.
|
|
*/
|
|
-#ifndef SQLITE_OMIT_BTREECOUNT
|
|
case OP_Count: { /* out2 */
|
|
i64 nEntry;
|
|
BtCursor *pCrsr;
|
|
@@ -86839,14 +88324,17 @@
|
|
assert( p->apCsr[pOp->p1]->eCurType==CURTYPE_BTREE );
|
|
pCrsr = p->apCsr[pOp->p1]->uc.pCursor;
|
|
assert( pCrsr );
|
|
- nEntry = 0; /* Not needed. Only used to silence a warning. */
|
|
- rc = sqlite3BtreeCount(pCrsr, &nEntry);
|
|
- if( rc ) goto abort_due_to_error;
|
|
+ if( pOp->p3 ){
|
|
+ nEntry = sqlite3BtreeRowCountEst(pCrsr);
|
|
+ }else{
|
|
+ nEntry = 0; /* Not needed. Only used to silence a warning. */
|
|
+ rc = sqlite3BtreeCount(db, pCrsr, &nEntry);
|
|
+ if( rc ) goto abort_due_to_error;
|
|
+ }
|
|
pOut = out2Prerelease(p, pOp);
|
|
pOut->u.i = nEntry;
|
|
- break;
|
|
+ goto check_for_interrupt;
|
|
}
|
|
-#endif
|
|
|
|
/* Opcode: Savepoint P1 * * P4 *
|
|
**
|
|
@@ -86961,8 +88449,12 @@
|
|
p->rc = rc = SQLITE_BUSY;
|
|
goto vdbe_return;
|
|
}
|
|
- db->isTransactionSavepoint = 0;
|
|
rc = p->rc;
|
|
+ if( rc ){
|
|
+ db->autoCommit = 0;
|
|
+ }else{
|
|
+ db->isTransactionSavepoint = 0;
|
|
+ }
|
|
}else{
|
|
int isSchemaChange;
|
|
iSavepoint = db->nSavepoint - iSavepoint - 1;
|
|
@@ -86990,6 +88482,7 @@
|
|
db->mDbFlags |= DBFLAG_SchemaChange;
|
|
}
|
|
}
|
|
+ if( rc ) goto abort_due_to_error;
|
|
|
|
/* Regardless of whether this is a RELEASE or ROLLBACK, destroy all
|
|
** savepoints nested inside of the savepoint being operated on. */
|
|
@@ -87072,7 +88565,6 @@
|
|
p->rc = rc = SQLITE_BUSY;
|
|
goto vdbe_return;
|
|
}
|
|
- assert( db->nStatement==0 );
|
|
sqlite3CloseSavepoints(db);
|
|
if( p->rc==SQLITE_OK ){
|
|
rc = SQLITE_DONE;
|
|
@@ -87089,7 +88581,7 @@
|
|
rc = SQLITE_ERROR;
|
|
goto abort_due_to_error;
|
|
}
|
|
- break;
|
|
+ /*NOTREACHED*/ assert(0);
|
|
}
|
|
|
|
/* Opcode: Transaction P1 P2 P3 P4 P5
|
|
@@ -87153,7 +88645,8 @@
|
|
goto abort_due_to_error;
|
|
}
|
|
|
|
- if( pOp->p2 && p->usesStmtJournal
|
|
+ if( p->usesStmtJournal
|
|
+ && pOp->p2
|
|
&& (db->autoCommit==0 || db->nVdbeRead>1)
|
|
){
|
|
assert( sqlite3BtreeIsInTrans(pBt) );
|
|
@@ -87297,7 +88790,7 @@
|
|
** <ul>
|
|
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
|
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
|
-** of OP_SeekLE/OP_IdxGT)
|
|
+** of OP_SeekLE/OP_IdxLT)
|
|
** </ul>
|
|
**
|
|
** The P4 value may be either an integer (P4_INT32) or a pointer to
|
|
@@ -87327,7 +88820,7 @@
|
|
** <ul>
|
|
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
|
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
|
-** of OP_SeekLE/OP_IdxGT)
|
|
+** of OP_SeekLE/OP_IdxLT)
|
|
** </ul>
|
|
**
|
|
** See also: OP_OpenRead, OP_OpenWrite
|
|
@@ -87351,7 +88844,7 @@
|
|
** <ul>
|
|
** <li> <b>0x02 OPFLAG_SEEKEQ</b>: This cursor will only be used for
|
|
** equality lookups (implemented as a pair of opcodes OP_SeekGE/OP_IdxGT
|
|
-** of OP_SeekLE/OP_IdxGT)
|
|
+** of OP_SeekLE/OP_IdxLT)
|
|
** <li> <b>0x08 OPFLAG_FORDELETE</b>: This cursor is used only to seek
|
|
** and subsequently delete entries in an index btree. This is a
|
|
** hint to the storage engine that the storage engine is allowed to
|
|
@@ -87463,9 +88956,7 @@
|
|
assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
|
|
assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
|
|
testcase( pOp->p5 & OPFLAG_BULKCSR );
|
|
-#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
|
testcase( pOp->p2 & OPFLAG_SEEKEQ );
|
|
-#endif
|
|
sqlite3BtreeCursorHintFlags(pCur->uc.pCursor,
|
|
(pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
|
|
if( rc ) goto abort_due_to_error;
|
|
@@ -87485,6 +88976,7 @@
|
|
VdbeCursor *pCx; /* The new cursor */
|
|
|
|
pOrig = p->apCsr[pOp->p2];
|
|
+ assert( pOrig );
|
|
assert( pOrig->pBtx!=0 ); /* Only ephemeral cursors can be duplicated */
|
|
|
|
pCx = allocateCursor(p, pOp->p1, pOrig->nField, -1, CURTYPE_BTREE);
|
|
@@ -87548,15 +89040,13 @@
|
|
assert( pOp->p1>=0 );
|
|
assert( pOp->p2>=0 );
|
|
pCx = p->apCsr[pOp->p1];
|
|
- if( pCx ){
|
|
+ if( pCx && pCx->pBtx ){
|
|
/* If the ephermeral table is already open, erase all existing content
|
|
** so that the table is empty again, rather than creating a new table. */
|
|
assert( pCx->isEphemeral );
|
|
pCx->seqCount = 0;
|
|
pCx->cacheStatus = CACHE_STALE;
|
|
- if( pCx->pBtx ){
|
|
- rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
|
|
- }
|
|
+ rc = sqlite3BtreeClearTable(pCx->pBtx, pCx->pgnoRoot, 0);
|
|
}else{
|
|
pCx = allocateCursor(p, pOp->p1, pOp->p2, -1, CURTYPE_BTREE);
|
|
if( pCx==0 ) goto no_mem;
|
|
@@ -87722,11 +89212,13 @@
|
|
** greater than or equal to the key and P2 is not zero, then jump to P2.
|
|
**
|
|
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
|
|
-** opcode will always land on a record that equally equals the key, or
|
|
-** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
|
|
-** opcode must be followed by an IdxLE opcode with the same arguments.
|
|
-** The IdxLE opcode will be skipped if this opcode succeeds, but the
|
|
-** IdxLE opcode will be used on subsequent loop iterations.
|
|
+** opcode will either land on a record that exactly matches the key, or
|
|
+** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ,
|
|
+** this opcode must be followed by an IdxLE opcode with the same arguments.
|
|
+** The IdxGT opcode will be skipped if this opcode succeeds, but the
|
|
+** IdxGT opcode will be used on subsequent loop iterations. The
|
|
+** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
|
|
+** is an equality search.
|
|
**
|
|
** This opcode leaves the cursor configured to move in forward order,
|
|
** from the beginning toward the end. In other words, the cursor is
|
|
@@ -87742,7 +89234,7 @@
|
|
** to an SQL index, then P3 is the first in an array of P4 registers
|
|
** that are used as an unpacked index key.
|
|
**
|
|
-** Reposition cursor P1 so that it points to the smallest entry that
|
|
+** Reposition cursor P1 so that it points to the smallest entry that
|
|
** is greater than the key value. If there are no records greater than
|
|
** the key and P2 is not zero, then jump to P2.
|
|
**
|
|
@@ -87787,11 +89279,13 @@
|
|
** configured to use Prev, not Next.
|
|
**
|
|
** If the cursor P1 was opened using the OPFLAG_SEEKEQ flag, then this
|
|
-** opcode will always land on a record that equally equals the key, or
|
|
-** else jump immediately to P2. When the cursor is OPFLAG_SEEKEQ, this
|
|
-** opcode must be followed by an IdxGE opcode with the same arguments.
|
|
+** opcode will either land on a record that exactly matches the key, or
|
|
+** else it will cause a jump to P2. When the cursor is OPFLAG_SEEKEQ,
|
|
+** this opcode must be followed by an IdxLE opcode with the same arguments.
|
|
** The IdxGE opcode will be skipped if this opcode succeeds, but the
|
|
-** IdxGE opcode will be used on subsequent loop iterations.
|
|
+** IdxGE opcode will be used on subsequent loop iterations. The
|
|
+** OPFLAG_SEEKEQ flags is a hint to the btree layer to say that this
|
|
+** is an equality search.
|
|
**
|
|
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
|
|
*/
|
|
@@ -87827,7 +89321,8 @@
|
|
pC->deferredMoveto = 0;
|
|
pC->cacheStatus = CACHE_STALE;
|
|
if( pC->isTable ){
|
|
- /* The BTREE_SEEK_EQ flag is only set on index cursors */
|
|
+ u16 flags3, newType;
|
|
+ /* The OPFLAG_SEEKEQ/BTREE_SEEK_EQ flag is only set on index cursors */
|
|
assert( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ)==0
|
|
|| CORRUPT_DB );
|
|
|
|
@@ -87835,18 +89330,21 @@
|
|
** blob, or NULL. But it needs to be an integer before we can do
|
|
** the seek, so convert it. */
|
|
pIn3 = &aMem[pOp->p3];
|
|
- if( (pIn3->flags & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
|
|
+ flags3 = pIn3->flags;
|
|
+ if( (flags3 & (MEM_Int|MEM_Real|MEM_IntReal|MEM_Str))==MEM_Str ){
|
|
applyNumericAffinity(pIn3, 0);
|
|
}
|
|
- iKey = sqlite3VdbeIntValue(pIn3);
|
|
+ iKey = sqlite3VdbeIntValue(pIn3); /* Get the integer key value */
|
|
+ newType = pIn3->flags; /* Record the type after applying numeric affinity */
|
|
+ pIn3->flags = flags3; /* But convert the type back to its original */
|
|
|
|
/* If the P3 value could not be converted into an integer without
|
|
** loss of information, then special processing is required... */
|
|
- if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
|
|
- if( (pIn3->flags & MEM_Real)==0 ){
|
|
- if( (pIn3->flags & MEM_Null) || oc>=OP_SeekGE ){
|
|
- VdbeBranchTaken(1,2); goto jump_to_p2;
|
|
- break;
|
|
+ if( (newType & (MEM_Int|MEM_IntReal))==0 ){
|
|
+ if( (newType & MEM_Real)==0 ){
|
|
+ if( (newType & MEM_Null) || oc>=OP_SeekGE ){
|
|
+ VdbeBranchTaken(1,2);
|
|
+ goto jump_to_p2;
|
|
}else{
|
|
rc = sqlite3BtreeLast(pC->uc.pCursor, &res);
|
|
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
|
@@ -87883,14 +89381,17 @@
|
|
goto abort_due_to_error;
|
|
}
|
|
}else{
|
|
- /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
|
|
- ** OP_SeekLE opcodes are allowed, and these must be immediately followed
|
|
- ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
|
|
+ /* For a cursor with the OPFLAG_SEEKEQ/BTREE_SEEK_EQ hint, only the
|
|
+ ** OP_SeekGE and OP_SeekLE opcodes are allowed, and these must be
|
|
+ ** immediately followed by an OP_IdxGT or OP_IdxLT opcode, respectively,
|
|
+ ** with the same key.
|
|
*/
|
|
if( sqlite3BtreeCursorHasHint(pC->uc.pCursor, BTREE_SEEK_EQ) ){
|
|
eqOnly = 1;
|
|
assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
|
|
assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
|
|
+ assert( pOp->opcode==OP_SeekGE || pOp[1].opcode==OP_IdxLT );
|
|
+ assert( pOp->opcode==OP_SeekLE || pOp[1].opcode==OP_IdxGT );
|
|
assert( pOp[1].p1==pOp[0].p1 );
|
|
assert( pOp[1].p2==pOp[0].p2 );
|
|
assert( pOp[1].p3==pOp[0].p3 );
|
|
@@ -87984,7 +89485,7 @@
|
|
** Synopsis: seekHit=P2
|
|
**
|
|
** Set the seekHit flag on cursor P1 to the value in P2.
|
|
-** The seekHit flag is used by the IfNoHope opcode.
|
|
+* The seekHit flag is used by the IfNoHope opcode.
|
|
**
|
|
** P1 must be a valid b-tree cursor. P2 must be a boolean value,
|
|
** either 0 or 1.
|
|
@@ -87999,6 +89500,20 @@
|
|
break;
|
|
}
|
|
|
|
+/* Opcode: IfNotOpen P1 P2 * * *
|
|
+** Synopsis: if( !csr[P1] ) goto P2
|
|
+**
|
|
+** If cursor P1 is not open, jump to instruction P2. Otherwise, fall through.
|
|
+*/
|
|
+case OP_IfNotOpen: { /* jump */
|
|
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
+ VdbeBranchTaken(p->apCsr[pOp->p1]==0, 2);
|
|
+ if( !p->apCsr[pOp->p1] ){
|
|
+ goto jump_to_p2_and_check_for_interrupt;
|
|
+ }
|
|
+ break;
|
|
+}
|
|
+
|
|
/* Opcode: Found P1 P2 P3 P4 *
|
|
** Synopsis: key=r[P3@P4]
|
|
**
|
|
@@ -88231,23 +89746,27 @@
|
|
pIn3 = &aMem[pOp->p3];
|
|
testcase( pIn3->flags & MEM_Int );
|
|
testcase( pIn3->flags & MEM_IntReal );
|
|
+ testcase( pIn3->flags & MEM_Real );
|
|
+ testcase( (pIn3->flags & (MEM_Str|MEM_Int))==MEM_Str );
|
|
if( (pIn3->flags & (MEM_Int|MEM_IntReal))==0 ){
|
|
- /* Make sure pIn3->u.i contains a valid integer representation of
|
|
- ** the key value, but do not change the datatype of the register, as
|
|
- ** other parts of the perpared statement might be depending on the
|
|
- ** current datatype. */
|
|
- u16 origFlags = pIn3->flags;
|
|
- int isNotInt;
|
|
- applyAffinity(pIn3, SQLITE_AFF_NUMERIC, encoding);
|
|
- isNotInt = (pIn3->flags & MEM_Int)==0;
|
|
- pIn3->flags = origFlags;
|
|
- if( isNotInt ) goto jump_to_p2;
|
|
+ /* If pIn3->u.i does not contain an integer, compute iKey as the
|
|
+ ** integer value of pIn3. Jump to P2 if pIn3 cannot be converted
|
|
+ ** into an integer without loss of information. Take care to avoid
|
|
+ ** changing the datatype of pIn3, however, as it is used by other
|
|
+ ** parts of the prepared statement. */
|
|
+ Mem x = pIn3[0];
|
|
+ applyAffinity(&x, SQLITE_AFF_NUMERIC, encoding);
|
|
+ if( (x.flags & MEM_Int)==0 ) goto jump_to_p2;
|
|
+ iKey = x.u.i;
|
|
+ goto notExistsWithKey;
|
|
}
|
|
/* Fall through into OP_NotExists */
|
|
case OP_NotExists: /* jump, in3 */
|
|
pIn3 = &aMem[pOp->p3];
|
|
assert( (pIn3->flags & MEM_Int)!=0 || pOp->opcode==OP_SeekRowid );
|
|
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
+ iKey = pIn3->u.i;
|
|
+notExistsWithKey:
|
|
pC = p->apCsr[pOp->p1];
|
|
assert( pC!=0 );
|
|
#ifdef SQLITE_DEBUG
|
|
@@ -88258,7 +89777,6 @@
|
|
pCrsr = pC->uc.pCursor;
|
|
assert( pCrsr!=0 );
|
|
res = 0;
|
|
- iKey = pIn3->u.i;
|
|
rc = sqlite3BtreeMovetoUnpacked(pCrsr, 0, iKey, 0, &res);
|
|
assert( rc==SQLITE_OK || res==0 );
|
|
pC->movetoTarget = iKey; /* Used by OP_Delete */
|
|
@@ -88484,6 +90002,7 @@
|
|
pC = p->apCsr[pOp->p1];
|
|
assert( pC!=0 );
|
|
assert( pC->eCurType==CURTYPE_BTREE );
|
|
+ assert( pC->deferredMoveto==0 );
|
|
assert( pC->uc.pCursor!=0 );
|
|
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
|
|
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
|
|
@@ -88601,7 +90120,11 @@
|
|
sqlite3VdbeIncrWriteCounter(p, pC);
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
- if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
|
|
+ if( pOp->p4type==P4_TABLE
|
|
+ && HasRowid(pOp->p4.pTab)
|
|
+ && pOp->p5==0
|
|
+ && sqlite3BtreeCursorIsValidNN(pC->uc.pCursor)
|
|
+ ){
|
|
/* If p5 is zero, the seek operation that positioned the cursor prior to
|
|
** OP_Delete will have also set the pC->movetoTarget field to the rowid of
|
|
** the row that is being deleted */
|
|
@@ -88816,7 +90339,7 @@
|
|
goto too_big;
|
|
}
|
|
testcase( n==0 );
|
|
- rc = sqlite3VdbeMemFromBtree(pCrsr, 0, n, pOut);
|
|
+ rc = sqlite3VdbeMemFromBtreeZeroOffset(pCrsr, n, pOut);
|
|
if( rc ) goto abort_due_to_error;
|
|
if( !pOp->p3 ) Deephemeralize(pOut);
|
|
UPDATE_MAX_BLOBSIZE(pOut);
|
|
@@ -89140,11 +90663,12 @@
|
|
** The Prev opcode is only used after SeekLT, SeekLE, and Last. */
|
|
assert( pOp->opcode!=OP_Next
|
|
|| pC->seekOp==OP_SeekGT || pC->seekOp==OP_SeekGE
|
|
- || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|
|
- || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid);
|
|
+ || pC->seekOp==OP_Rewind || pC->seekOp==OP_Found
|
|
+ || pC->seekOp==OP_NullRow|| pC->seekOp==OP_SeekRowid
|
|
+ || pC->seekOp==OP_IfNoHope);
|
|
assert( pOp->opcode!=OP_Prev
|
|
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|
|
- || pC->seekOp==OP_Last
|
|
+ || pC->seekOp==OP_Last || pC->seekOp==OP_IfNoHope
|
|
|| pC->seekOp==OP_NullRow);
|
|
|
|
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
|
|
@@ -89193,6 +90717,36 @@
|
|
** This instruction only works for indices. The equivalent instruction
|
|
** for tables is OP_Insert.
|
|
*/
|
|
+case OP_IdxInsert: { /* in2 */
|
|
+ VdbeCursor *pC;
|
|
+ BtreePayload x;
|
|
+
|
|
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
+ pC = p->apCsr[pOp->p1];
|
|
+ sqlite3VdbeIncrWriteCounter(p, pC);
|
|
+ assert( pC!=0 );
|
|
+ assert( !isSorter(pC) );
|
|
+ pIn2 = &aMem[pOp->p2];
|
|
+ assert( pIn2->flags & MEM_Blob );
|
|
+ if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
|
+ assert( pC->eCurType==CURTYPE_BTREE );
|
|
+ assert( pC->isTable==0 );
|
|
+ rc = ExpandBlob(pIn2);
|
|
+ if( rc ) goto abort_due_to_error;
|
|
+ x.nKey = pIn2->n;
|
|
+ x.pKey = pIn2->z;
|
|
+ x.aMem = aMem + pOp->p3;
|
|
+ x.nMem = (u16)pOp->p4.i;
|
|
+ rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
|
|
+ (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
|
|
+ ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
|
|
+ );
|
|
+ assert( pC->deferredMoveto==0 );
|
|
+ pC->cacheStatus = CACHE_STALE;
|
|
+ if( rc) goto abort_due_to_error;
|
|
+ break;
|
|
+}
|
|
+
|
|
/* Opcode: SorterInsert P1 P2 * * *
|
|
** Synopsis: key=r[P2]
|
|
**
|
|
@@ -89200,47 +90754,37 @@
|
|
** MakeRecord instructions. This opcode writes that key
|
|
** into the sorter P1. Data for the entry is nil.
|
|
*/
|
|
-case OP_SorterInsert: /* in2 */
|
|
-case OP_IdxInsert: { /* in2 */
|
|
+case OP_SorterInsert: { /* in2 */
|
|
VdbeCursor *pC;
|
|
- BtreePayload x;
|
|
|
|
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
pC = p->apCsr[pOp->p1];
|
|
sqlite3VdbeIncrWriteCounter(p, pC);
|
|
assert( pC!=0 );
|
|
- assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
|
|
+ assert( isSorter(pC) );
|
|
pIn2 = &aMem[pOp->p2];
|
|
assert( pIn2->flags & MEM_Blob );
|
|
- if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++;
|
|
- assert( pC->eCurType==CURTYPE_BTREE || pOp->opcode==OP_SorterInsert );
|
|
assert( pC->isTable==0 );
|
|
rc = ExpandBlob(pIn2);
|
|
if( rc ) goto abort_due_to_error;
|
|
- if( pOp->opcode==OP_SorterInsert ){
|
|
- rc = sqlite3VdbeSorterWrite(pC, pIn2);
|
|
- }else{
|
|
- x.nKey = pIn2->n;
|
|
- x.pKey = pIn2->z;
|
|
- x.aMem = aMem + pOp->p3;
|
|
- x.nMem = (u16)pOp->p4.i;
|
|
- rc = sqlite3BtreeInsert(pC->uc.pCursor, &x,
|
|
- (pOp->p5 & (OPFLAG_APPEND|OPFLAG_SAVEPOSITION)),
|
|
- ((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
|
|
- );
|
|
- assert( pC->deferredMoveto==0 );
|
|
- pC->cacheStatus = CACHE_STALE;
|
|
- }
|
|
+ rc = sqlite3VdbeSorterWrite(pC, pIn2);
|
|
if( rc) goto abort_due_to_error;
|
|
break;
|
|
}
|
|
|
|
-/* Opcode: IdxDelete P1 P2 P3 * *
|
|
+/* Opcode: IdxDelete P1 P2 P3 * P5
|
|
** Synopsis: key=r[P2@P3]
|
|
**
|
|
** The content of P3 registers starting at register P2 form
|
|
** an unpacked index key. This opcode removes that entry from the
|
|
** index opened by cursor P1.
|
|
+**
|
|
+** If P5 is not zero, then raise an SQLITE_CORRUPT_INDEX error
|
|
+** if no matching index entry is found. This happens when running
|
|
+** an UPDATE or DELETE statement and the index entry to be updated
|
|
+** or deleted is not found. For some uses of IdxDelete
|
|
+** (example: the EXCEPT operator) it does not matter that no matching
|
|
+** entry is found. For those cases, P5 is zero.
|
|
*/
|
|
case OP_IdxDelete: {
|
|
VdbeCursor *pC;
|
|
@@ -89257,7 +90801,6 @@
|
|
sqlite3VdbeIncrWriteCounter(p, pC);
|
|
pCrsr = pC->uc.pCursor;
|
|
assert( pCrsr!=0 );
|
|
- assert( pOp->p5==0 );
|
|
r.pKeyInfo = pC->pKeyInfo;
|
|
r.nField = (u16)pOp->p3;
|
|
r.default_rc = 0;
|
|
@@ -89267,6 +90810,9 @@
|
|
if( res==0 ){
|
|
rc = sqlite3BtreeDelete(pCrsr, BTREE_AUXDELETE);
|
|
if( rc ) goto abort_due_to_error;
|
|
+ }else if( pOp->p5 ){
|
|
+ rc = SQLITE_CORRUPT_INDEX;
|
|
+ goto abort_due_to_error;
|
|
}
|
|
assert( pC->deferredMoveto==0 );
|
|
pC->cacheStatus = CACHE_STALE;
|
|
@@ -89356,6 +90902,24 @@
|
|
break;
|
|
}
|
|
|
|
+/* Opcode: FinishSeek P1 * * * *
|
|
+**
|
|
+** If cursor P1 was previously moved via OP_DeferredSeek, complete that
|
|
+** seek operation now, without further delay. If the cursor seek has
|
|
+** already occurred, this instruction is a no-op.
|
|
+*/
|
|
+case OP_FinishSeek: {
|
|
+ VdbeCursor *pC; /* The P1 index cursor */
|
|
+
|
|
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
+ pC = p->apCsr[pOp->p1];
|
|
+ if( pC->deferredMoveto ){
|
|
+ rc = sqlite3VdbeFinishMoveto(pC);
|
|
+ if( rc ) goto abort_due_to_error;
|
|
+ }
|
|
+ break;
|
|
+}
|
|
+
|
|
/* Opcode: IdxGE P1 P2 P3 P4 P5
|
|
** Synopsis: key=r[P3@P4]
|
|
**
|
|
@@ -89663,7 +91227,7 @@
|
|
initData.pzErrMsg = &p->zErrMsg;
|
|
initData.mInitFlags = 0;
|
|
zSql = sqlite3MPrintf(db,
|
|
- "SELECT name, rootpage, sql FROM '%q'.%s WHERE %s ORDER BY rowid",
|
|
+ "SELECT*FROM\"%w\".%s WHERE %s ORDER BY rowid",
|
|
db->aDb[iDb].zDbSName, zMaster, pOp->p4.z);
|
|
if( zSql==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
@@ -89792,7 +91356,7 @@
|
|
pIn1 = &aMem[pOp->p1];
|
|
assert( pOp->p5<db->nDb );
|
|
assert( DbMaskTest(p->btreeMask, pOp->p5) );
|
|
- z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
|
|
+ z = sqlite3BtreeIntegrityCheck(db, db->aDb[pOp->p5].pBt, &aRoot[1], nRoot,
|
|
(int)pnErr->u.i+1, &nErr);
|
|
sqlite3VdbeMemSetNull(pIn1);
|
|
if( nErr==0 ){
|
|
@@ -89805,7 +91369,7 @@
|
|
}
|
|
UPDATE_MAX_BLOBSIZE(pIn1);
|
|
sqlite3VdbeChangeEncoding(pIn1, encoding);
|
|
- break;
|
|
+ goto check_for_interrupt;
|
|
}
|
|
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
|
|
|
@@ -90051,7 +91615,7 @@
|
|
int i;
|
|
for(i=0; i<p->nMem; i++){
|
|
aMem[i].pScopyFrom = 0; /* Prevent false-positive AboutToChange() errs */
|
|
- aMem[i].flags |= MEM_Undefined; /* Cause a fault if this reg is reused */
|
|
+ MemSetTypeFlag(&aMem[i], MEM_Undefined); /* Fault if this reg is reused */
|
|
}
|
|
}
|
|
#endif
|
|
@@ -90662,6 +92226,36 @@
|
|
break;
|
|
}
|
|
|
|
+/* Opcode: CursorLock P1 * * * *
|
|
+**
|
|
+** Lock the btree to which cursor P1 is pointing so that the btree cannot be
|
|
+** written by an other cursor.
|
|
+*/
|
|
+case OP_CursorLock: {
|
|
+ VdbeCursor *pC;
|
|
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
+ pC = p->apCsr[pOp->p1];
|
|
+ assert( pC!=0 );
|
|
+ assert( pC->eCurType==CURTYPE_BTREE );
|
|
+ sqlite3BtreeCursorPin(pC->uc.pCursor);
|
|
+ break;
|
|
+}
|
|
+
|
|
+/* Opcode: CursorUnlock P1 * * * *
|
|
+**
|
|
+** Unlock the btree to which cursor P1 is pointing so that it can be
|
|
+** written by other cursors.
|
|
+*/
|
|
+case OP_CursorUnlock: {
|
|
+ VdbeCursor *pC;
|
|
+ assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
|
+ pC = p->apCsr[pOp->p1];
|
|
+ assert( pC!=0 );
|
|
+ assert( pC->eCurType==CURTYPE_BTREE );
|
|
+ sqlite3BtreeCursorUnpin(pC->uc.pCursor);
|
|
+ break;
|
|
+}
|
|
+
|
|
#ifndef SQLITE_OMIT_SHARED_CACHE
|
|
/* Opcode: TableLock P1 P2 P3 P4 *
|
|
** Synopsis: iDb=P1 root=P2 write=P3
|
|
@@ -90906,7 +92500,7 @@
|
|
assert( pModule->xColumn );
|
|
memset(&sContext, 0, sizeof(sContext));
|
|
sContext.pOut = pDest;
|
|
- testcase( (pOp->p5 & OPFLAG_NOCHNG)==0 && pOp->p5!=0 );
|
|
+ assert( pOp->p5==OPFLAG_NOCHNG || pOp->p5==0 );
|
|
if( pOp->p5 & OPFLAG_NOCHNG ){
|
|
sqlite3VdbeMemSetNull(pDest);
|
|
pDest->flags = MEM_Null|MEM_Zero;
|
|
@@ -91131,13 +92725,15 @@
|
|
}
|
|
#endif
|
|
|
|
-/* Opcode: Function0 P1 P2 P3 P4 P5
|
|
-** Synopsis: r[P3]=func(r[P2@P5])
|
|
+/* Opcode: Function P1 P2 P3 P4 *
|
|
+** Synopsis: r[P3]=func(r[P2@NP])
|
|
**
|
|
-** Invoke a user function (P4 is a pointer to a FuncDef object that
|
|
-** defines the function) with P5 arguments taken from register P2 and
|
|
-** successors. The result of the function is stored in register P3.
|
|
-** Register P3 must not be one of the function inputs.
|
|
+** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
|
+** contains a pointer to the function to be run) with arguments taken
|
|
+** from register P2 and successors. The number of arguments is in
|
|
+** the sqlite3_context object that P4 points to.
|
|
+** 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
|
|
@@ -91146,14 +92742,16 @@
|
|
** sqlite3_set_auxdata() API may be safely retained until the next
|
|
** invocation of this opcode.
|
|
**
|
|
-** See also: Function, AggStep, AggFinal
|
|
+** See also: AggStep, AggFinal, PureFunc
|
|
*/
|
|
-/* Opcode: Function P1 P2 P3 P4 P5
|
|
-** Synopsis: r[P3]=func(r[P2@P5])
|
|
+/* Opcode: PureFunc P1 P2 P3 P4 *
|
|
+** Synopsis: r[P3]=func(r[P2@NP])
|
|
**
|
|
** Invoke a user function (P4 is a pointer to an sqlite3_context object that
|
|
-** contains a pointer to the function to be run) with P5 arguments taken
|
|
-** from register P2 and successors. The result of the function is stored
|
|
+** contains a pointer to the function to be run) with arguments taken
|
|
+** from register P2 and successors. The number of arguments is in
|
|
+** the sqlite3_context object that P4 points to.
|
|
+** 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
|
|
@@ -91163,40 +92761,16 @@
|
|
** sqlite3_set_auxdata() API may be safely retained until the next
|
|
** invocation of this opcode.
|
|
**
|
|
-** SQL functions are initially coded as OP_Function0 with P4 pointing
|
|
-** to a FuncDef object. But on first evaluation, the P4 operand is
|
|
-** automatically converted into an sqlite3_context object and the operation
|
|
-** changed to this OP_Function opcode. In this way, the initialization of
|
|
-** the sqlite3_context object occurs only once, rather than once for each
|
|
-** evaluation of the function.
|
|
+** This opcode works exactly like OP_Function. The only difference is in
|
|
+** its name. This opcode is used in places where the function must be
|
|
+** purely non-deterministic. Some built-in date/time functions can be
|
|
+** either determinitic of non-deterministic, depending on their arguments.
|
|
+** When those function are used in a non-deterministic way, they will check
|
|
+** to see if they were called using OP_PureFunc instead of OP_Function, and
|
|
+** if they were, they throw an error.
|
|
**
|
|
-** See also: Function0, AggStep, AggFinal
|
|
+** See also: AggStep, AggFinal, Function
|
|
*/
|
|
-case OP_PureFunc0: /* group */
|
|
-case OP_Function0: { /* group */
|
|
- int n;
|
|
- sqlite3_context *pCtx;
|
|
-
|
|
- assert( pOp->p4type==P4_FUNCDEF );
|
|
- n = pOp->p5;
|
|
- assert( pOp->p3>0 && pOp->p3<=(p->nMem+1 - p->nCursor) );
|
|
- assert( n==0 || (pOp->p2>0 && pOp->p2+n<=(p->nMem+1 - p->nCursor)+1) );
|
|
- assert( pOp->p3<pOp->p2 || pOp->p3>=pOp->p2+n );
|
|
- pCtx = sqlite3DbMallocRawNN(db, sizeof(*pCtx) + (n-1)*sizeof(sqlite3_value*));
|
|
- if( pCtx==0 ) goto no_mem;
|
|
- pCtx->pOut = 0;
|
|
- pCtx->pFunc = pOp->p4.pFunc;
|
|
- pCtx->iOp = (int)(pOp - aOp);
|
|
- pCtx->pVdbe = p;
|
|
- pCtx->isError = 0;
|
|
- pCtx->argc = n;
|
|
- pOp->p4type = P4_FUNCCTX;
|
|
- pOp->p4.pCtx = pCtx;
|
|
- assert( OP_PureFunc == OP_PureFunc0+2 );
|
|
- assert( OP_Function == OP_Function0+2 );
|
|
- pOp->opcode += 2;
|
|
- /* Fall through into OP_Function */
|
|
-}
|
|
case OP_PureFunc: /* group */
|
|
case OP_Function: { /* group */
|
|
int i;
|
|
@@ -91211,9 +92785,11 @@
|
|
** reinitializes the relavant parts of the sqlite3_context object */
|
|
pOut = &aMem[pOp->p3];
|
|
if( pCtx->pOut != pOut ){
|
|
+ pCtx->pVdbe = p;
|
|
pCtx->pOut = pOut;
|
|
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
|
|
}
|
|
+ assert( pCtx->pVdbe==p );
|
|
|
|
memAboutToChange(p, pOut);
|
|
#ifdef SQLITE_DEBUG
|
|
@@ -91385,6 +92961,55 @@
|
|
}
|
|
#endif
|
|
|
|
+#ifdef SQLITE_DEBUG
|
|
+/* Opcode: ReleaseReg P1 P2 P3 * P5
|
|
+** Synopsis: release r[P1@P2] mask P3
|
|
+**
|
|
+** Release registers from service. Any content that was in the
|
|
+** the registers is unreliable after this opcode completes.
|
|
+**
|
|
+** The registers released will be the P2 registers starting at P1,
|
|
+** except if bit ii of P3 set, then do not release register P1+ii.
|
|
+** In other words, P3 is a mask of registers to preserve.
|
|
+**
|
|
+** Releasing a register clears the Mem.pScopyFrom pointer. That means
|
|
+** that if the content of the released register was set using OP_SCopy,
|
|
+** a change to the value of the source register for the OP_SCopy will no longer
|
|
+** generate an assertion fault in sqlite3VdbeMemAboutToChange().
|
|
+**
|
|
+** If P5 is set, then all released registers have their type set
|
|
+** to MEM_Undefined so that any subsequent attempt to read the released
|
|
+** register (before it is reinitialized) will generate an assertion fault.
|
|
+**
|
|
+** P5 ought to be set on every call to this opcode.
|
|
+** However, there are places in the code generator will release registers
|
|
+** before their are used, under the (valid) assumption that the registers
|
|
+** will not be reallocated for some other purpose before they are used and
|
|
+** hence are safe to release.
|
|
+**
|
|
+** This opcode is only available in testing and debugging builds. It is
|
|
+** not generated for release builds. The purpose of this opcode is to help
|
|
+** validate the generated bytecode. This opcode does not actually contribute
|
|
+** to computing an answer.
|
|
+*/
|
|
+case OP_ReleaseReg: {
|
|
+ Mem *pMem;
|
|
+ int i;
|
|
+ u32 constMask;
|
|
+ assert( pOp->p1>0 );
|
|
+ assert( pOp->p1+pOp->p2<=(p->nMem+1 - p->nCursor)+1 );
|
|
+ pMem = &aMem[pOp->p1];
|
|
+ constMask = pOp->p3;
|
|
+ for(i=0; i<pOp->p2; i++, pMem++){
|
|
+ if( i>=32 || (constMask & MASKBIT32(i))==0 ){
|
|
+ pMem->pScopyFrom = 0;
|
|
+ if( i<32 && pOp->p5 ) MemSetTypeFlag(pMem, MEM_Undefined);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
+}
|
|
+#endif
|
|
+
|
|
/* Opcode: Noop * * * * *
|
|
**
|
|
** Do nothing. This instruction is often useful as a jump
|
|
@@ -91436,6 +93061,12 @@
|
|
if( opProperty & OPFLG_OUT3 ){
|
|
registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
|
|
}
|
|
+ if( opProperty==0xff ){
|
|
+ /* Never happens. This code exists to avoid a harmless linkage
|
|
+ ** warning aboud sqlite3VdbeRegisterDump() being defined but not
|
|
+ ** used. */
|
|
+ sqlite3VdbeRegisterDump(p);
|
|
+ }
|
|
}
|
|
#endif /* SQLITE_DEBUG */
|
|
#endif /* NDEBUG */
|
|
@@ -91503,7 +93134,7 @@
|
|
** flag.
|
|
*/
|
|
abort_due_to_interrupt:
|
|
- assert( db->u1.isInterrupted );
|
|
+ assert( AtomicLoad(&db->u1.isInterrupted) );
|
|
rc = db->mallocFailed ? SQLITE_NOMEM_BKPT : SQLITE_INTERRUPT;
|
|
p->rc = rc;
|
|
sqlite3VdbeError(p, "%s", sqlite3ErrStr(rc));
|
|
@@ -91870,11 +93501,12 @@
|
|
sqlite3 *db;
|
|
|
|
if( p ){
|
|
+ sqlite3_stmt *pStmt = p->pStmt;
|
|
db = p->db;
|
|
sqlite3_mutex_enter(db->mutex);
|
|
- rc = sqlite3_finalize(p->pStmt);
|
|
sqlite3DbFree(db, p);
|
|
sqlite3_mutex_leave(db->mutex);
|
|
+ rc = sqlite3_finalize(pStmt);
|
|
}else{
|
|
rc = SQLITE_OK;
|
|
}
|
|
@@ -92840,8 +94472,8 @@
|
|
int n2;
|
|
int res;
|
|
|
|
- getVarint32(&p1[1], n1);
|
|
- getVarint32(&p2[1], n2);
|
|
+ getVarint32NR(&p1[1], n1);
|
|
+ getVarint32NR(&p2[1], n2);
|
|
res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
|
|
if( res==0 ){
|
|
res = n1 - n2;
|
|
@@ -92854,7 +94486,8 @@
|
|
);
|
|
}
|
|
}else{
|
|
- if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
|
+ assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
|
|
+ if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
|
|
res = res * -1;
|
|
}
|
|
}
|
|
@@ -92922,7 +94555,8 @@
|
|
pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
|
|
);
|
|
}
|
|
- }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
|
|
+ }else if( pTask->pSorter->pKeyInfo->aSortFlags[0] ){
|
|
+ assert( !(pTask->pSorter->pKeyInfo->aSortFlags[0]&KEYINFO_ORDER_BIGNULL) );
|
|
res = res * -1;
|
|
}
|
|
|
|
@@ -93037,6 +94671,7 @@
|
|
|
|
if( pKeyInfo->nAllField<13
|
|
&& (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
|
|
+ && (pKeyInfo->aSortFlags[0] & KEYINFO_ORDER_BIGNULL)==0
|
|
){
|
|
pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
|
|
}
|
|
@@ -93418,20 +95053,16 @@
|
|
*/
|
|
static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
|
|
int i;
|
|
- SorterRecord **aSlot;
|
|
SorterRecord *p;
|
|
int rc;
|
|
+ SorterRecord *aSlot[64];
|
|
|
|
rc = vdbeSortAllocUnpacked(pTask);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
|
|
p = pList->pList;
|
|
pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
|
|
-
|
|
- aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
|
|
- if( !aSlot ){
|
|
- return SQLITE_NOMEM_BKPT;
|
|
- }
|
|
+ memset(aSlot, 0, sizeof(aSlot));
|
|
|
|
while( p ){
|
|
SorterRecord *pNext;
|
|
@@ -93456,13 +95087,12 @@
|
|
}
|
|
|
|
p = 0;
|
|
- for(i=0; i<64; i++){
|
|
+ for(i=0; i<ArraySize(aSlot); i++){
|
|
if( aSlot[i]==0 ) continue;
|
|
p = p ? vdbeSorterMerge(pTask, p, aSlot[i]) : aSlot[i];
|
|
}
|
|
pList->pList = p;
|
|
|
|
- sqlite3_free(aSlot);
|
|
assert( pTask->pUnpacked->errCode==SQLITE_OK
|
|
|| pTask->pUnpacked->errCode==SQLITE_NOMEM
|
|
);
|
|
@@ -93753,13 +95383,16 @@
|
|
rc = vdbeSorterListToPMA(&pSorter->aTask[nWorker], &pSorter->list);
|
|
}else{
|
|
/* Launch a background thread for this operation */
|
|
- u8 *aMem = pTask->list.aMemory;
|
|
- void *pCtx = (void*)pTask;
|
|
+ u8 *aMem;
|
|
+ void *pCtx;
|
|
|
|
+ assert( pTask!=0 );
|
|
assert( pTask->pThread==0 && pTask->bDone==0 );
|
|
assert( pTask->list.pList==0 );
|
|
assert( pTask->list.aMemory==0 || pSorter->list.aMemory!=0 );
|
|
|
|
+ aMem = pTask->list.aMemory;
|
|
+ pCtx = (void*)pTask;
|
|
pSorter->iPrev = (u8)(pTask - pSorter->aTask);
|
|
pTask->list = pSorter->list;
|
|
pSorter->list.pList = 0;
|
|
@@ -93797,7 +95430,7 @@
|
|
|
|
assert( pCsr->eCurType==CURTYPE_SORTER );
|
|
pSorter = pCsr->uc.pSorter;
|
|
- getVarint32((const u8*)&pVal->z[1], t);
|
|
+ getVarint32NR((const u8*)&pVal->z[1], t);
|
|
if( t>0 && t<10 && t!=7 ){
|
|
pSorter->typeMask &= SORTER_TYPE_INTEGER;
|
|
}else if( t>10 && (t & 0x01) ){
|
|
@@ -94784,6 +96417,433 @@
|
|
}
|
|
|
|
/************** End of vdbesort.c ********************************************/
|
|
+/************** Begin file vdbevtab.c ****************************************/
|
|
+/*
|
|
+** 2020-03-23
|
|
+**
|
|
+** The author disclaims copyright to this source code. In place of
|
|
+** a legal notice, here is a blessing:
|
|
+**
|
|
+** May you do good and not evil.
|
|
+** May you find forgiveness for yourself and forgive others.
|
|
+** May you share freely, never taking more than you give.
|
|
+**
|
|
+*************************************************************************
|
|
+**
|
|
+** This file implements virtual-tables for examining the bytecode content
|
|
+** of a prepared statement.
|
|
+*/
|
|
+/* #include "sqliteInt.h" */
|
|
+#if defined(SQLITE_ENABLE_BYTECODE_VTAB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
+/* #include "vdbeInt.h" */
|
|
+
|
|
+/* An instance of the bytecode() table-valued function.
|
|
+*/
|
|
+typedef struct bytecodevtab bytecodevtab;
|
|
+struct bytecodevtab {
|
|
+ sqlite3_vtab base; /* Base class - must be first */
|
|
+ sqlite3 *db; /* Database connection */
|
|
+ int bTablesUsed; /* 2 for tables_used(). 0 for bytecode(). */
|
|
+};
|
|
+
|
|
+/* A cursor for scanning through the bytecode
|
|
+*/
|
|
+typedef struct bytecodevtab_cursor bytecodevtab_cursor;
|
|
+struct bytecodevtab_cursor {
|
|
+ sqlite3_vtab_cursor base; /* Base class - must be first */
|
|
+ sqlite3_stmt *pStmt; /* The statement whose bytecode is displayed */
|
|
+ int iRowid; /* The rowid of the output table */
|
|
+ int iAddr; /* Address */
|
|
+ int needFinalize; /* Cursors owns pStmt and must finalize it */
|
|
+ int showSubprograms; /* Provide a listing of subprograms */
|
|
+ Op *aOp; /* Operand array */
|
|
+ char *zP4; /* Rendered P4 value */
|
|
+ const char *zType; /* tables_used.type */
|
|
+ const char *zSchema; /* tables_used.schema */
|
|
+ const char *zName; /* tables_used.name */
|
|
+ Mem sub; /* Subprograms */
|
|
+};
|
|
+
|
|
+/*
|
|
+** Create a new bytecode() table-valued function.
|
|
+*/
|
|
+static int bytecodevtabConnect(
|
|
+ sqlite3 *db,
|
|
+ void *pAux,
|
|
+ int argc, const char *const*argv,
|
|
+ sqlite3_vtab **ppVtab,
|
|
+ char **pzErr
|
|
+){
|
|
+ bytecodevtab *pNew;
|
|
+ int rc;
|
|
+ int isTabUsed = pAux!=0;
|
|
+ const char *azSchema[2] = {
|
|
+ /* bytecode() schema */
|
|
+ "CREATE TABLE x("
|
|
+ "addr INT,"
|
|
+ "opcode TEXT,"
|
|
+ "p1 INT,"
|
|
+ "p2 INT,"
|
|
+ "p3 INT,"
|
|
+ "p4 TEXT,"
|
|
+ "p5 INT,"
|
|
+ "comment TEXT,"
|
|
+ "subprog TEXT,"
|
|
+ "stmt HIDDEN"
|
|
+ ");",
|
|
+
|
|
+ /* Tables_used() schema */
|
|
+ "CREATE TABLE x("
|
|
+ "type TEXT,"
|
|
+ "schema TEXT,"
|
|
+ "name TEXT,"
|
|
+ "wr INT,"
|
|
+ "subprog TEXT,"
|
|
+ "stmt HIDDEN"
|
|
+ ");"
|
|
+ };
|
|
+
|
|
+ rc = sqlite3_declare_vtab(db, azSchema[isTabUsed]);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ pNew = sqlite3_malloc( sizeof(*pNew) );
|
|
+ *ppVtab = (sqlite3_vtab*)pNew;
|
|
+ if( pNew==0 ) return SQLITE_NOMEM;
|
|
+ memset(pNew, 0, sizeof(*pNew));
|
|
+ pNew->db = db;
|
|
+ pNew->bTablesUsed = isTabUsed*2;
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+** This method is the destructor for bytecodevtab objects.
|
|
+*/
|
|
+static int bytecodevtabDisconnect(sqlite3_vtab *pVtab){
|
|
+ bytecodevtab *p = (bytecodevtab*)pVtab;
|
|
+ sqlite3_free(p);
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Constructor for a new bytecodevtab_cursor object.
|
|
+*/
|
|
+static int bytecodevtabOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
|
+ bytecodevtab *pVTab = (bytecodevtab*)p;
|
|
+ bytecodevtab_cursor *pCur;
|
|
+ pCur = sqlite3_malloc( sizeof(*pCur) );
|
|
+ if( pCur==0 ) return SQLITE_NOMEM;
|
|
+ memset(pCur, 0, sizeof(*pCur));
|
|
+ sqlite3VdbeMemInit(&pCur->sub, pVTab->db, 1);
|
|
+ *ppCursor = &pCur->base;
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Clear all internal content from a bytecodevtab cursor.
|
|
+*/
|
|
+static void bytecodevtabCursorClear(bytecodevtab_cursor *pCur){
|
|
+ sqlite3_free(pCur->zP4);
|
|
+ pCur->zP4 = 0;
|
|
+ sqlite3VdbeMemRelease(&pCur->sub);
|
|
+ sqlite3VdbeMemSetNull(&pCur->sub);
|
|
+ if( pCur->needFinalize ){
|
|
+ sqlite3_finalize(pCur->pStmt);
|
|
+ }
|
|
+ pCur->pStmt = 0;
|
|
+ pCur->needFinalize = 0;
|
|
+ pCur->zType = 0;
|
|
+ pCur->zSchema = 0;
|
|
+ pCur->zName = 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Destructor for a bytecodevtab_cursor.
|
|
+*/
|
|
+static int bytecodevtabClose(sqlite3_vtab_cursor *cur){
|
|
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
|
+ bytecodevtabCursorClear(pCur);
|
|
+ sqlite3_free(pCur);
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+** Advance a bytecodevtab_cursor to its next row of output.
|
|
+*/
|
|
+static int bytecodevtabNext(sqlite3_vtab_cursor *cur){
|
|
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
|
+ bytecodevtab *pTab = (bytecodevtab*)cur->pVtab;
|
|
+ int rc;
|
|
+ if( pCur->zP4 ){
|
|
+ sqlite3_free(pCur->zP4);
|
|
+ pCur->zP4 = 0;
|
|
+ }
|
|
+ if( pCur->zName ){
|
|
+ pCur->zName = 0;
|
|
+ pCur->zType = 0;
|
|
+ pCur->zSchema = 0;
|
|
+ }
|
|
+ rc = sqlite3VdbeNextOpcode(
|
|
+ (Vdbe*)pCur->pStmt,
|
|
+ pCur->showSubprograms ? &pCur->sub : 0,
|
|
+ pTab->bTablesUsed,
|
|
+ &pCur->iRowid,
|
|
+ &pCur->iAddr,
|
|
+ &pCur->aOp);
|
|
+ if( rc!=SQLITE_OK ){
|
|
+ sqlite3VdbeMemSetNull(&pCur->sub);
|
|
+ pCur->aOp = 0;
|
|
+ }
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Return TRUE if the cursor has been moved off of the last
|
|
+** row of output.
|
|
+*/
|
|
+static int bytecodevtabEof(sqlite3_vtab_cursor *cur){
|
|
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
|
+ return pCur->aOp==0;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Return values of columns for the row at which the bytecodevtab_cursor
|
|
+** is currently pointing.
|
|
+*/
|
|
+static int bytecodevtabColumn(
|
|
+ sqlite3_vtab_cursor *cur, /* The cursor */
|
|
+ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
|
+ int i /* Which column to return */
|
|
+){
|
|
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
|
+ bytecodevtab *pVTab = (bytecodevtab*)cur->pVtab;
|
|
+ Op *pOp = pCur->aOp + pCur->iAddr;
|
|
+ if( pVTab->bTablesUsed ){
|
|
+ if( i==4 ){
|
|
+ i = 8;
|
|
+ }else{
|
|
+ if( i<=2 && pCur->zType==0 ){
|
|
+ Schema *pSchema;
|
|
+ HashElem *k;
|
|
+ int iDb = pOp->p3;
|
|
+ int iRoot = pOp->p2;
|
|
+ sqlite3 *db = pVTab->db;
|
|
+ pSchema = db->aDb[iDb].pSchema;
|
|
+ pCur->zSchema = db->aDb[iDb].zDbSName;
|
|
+ for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){
|
|
+ Table *pTab = (Table*)sqliteHashData(k);
|
|
+ if( !IsVirtual(pTab) && pTab->tnum==iRoot ){
|
|
+ pCur->zName = pTab->zName;
|
|
+ pCur->zType = "table";
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if( pCur->zName==0 ){
|
|
+ for(k=sqliteHashFirst(&pSchema->idxHash); k; k=sqliteHashNext(k)){
|
|
+ Index *pIdx = (Index*)sqliteHashData(k);
|
|
+ if( pIdx->tnum==iRoot ){
|
|
+ pCur->zName = pIdx->zName;
|
|
+ pCur->zType = "index";
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ i += 10;
|
|
+ }
|
|
+ }
|
|
+ switch( i ){
|
|
+ case 0: /* addr */
|
|
+ sqlite3_result_int(ctx, pCur->iAddr);
|
|
+ break;
|
|
+ case 1: /* opcode */
|
|
+ sqlite3_result_text(ctx, (char*)sqlite3OpcodeName(pOp->opcode),
|
|
+ -1, SQLITE_STATIC);
|
|
+ break;
|
|
+ case 2: /* p1 */
|
|
+ sqlite3_result_int(ctx, pOp->p1);
|
|
+ break;
|
|
+ case 3: /* p2 */
|
|
+ sqlite3_result_int(ctx, pOp->p2);
|
|
+ break;
|
|
+ case 4: /* p3 */
|
|
+ sqlite3_result_int(ctx, pOp->p3);
|
|
+ break;
|
|
+ case 5: /* p4 */
|
|
+ case 7: /* comment */
|
|
+ if( pCur->zP4==0 ){
|
|
+ pCur->zP4 = sqlite3VdbeDisplayP4(pVTab->db, pOp);
|
|
+ }
|
|
+ if( i==5 ){
|
|
+ sqlite3_result_text(ctx, pCur->zP4, -1, SQLITE_STATIC);
|
|
+ }else{
|
|
+#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
|
+ char *zCom = sqlite3VdbeDisplayComment(pVTab->db, pOp, pCur->zP4);
|
|
+ sqlite3_result_text(ctx, zCom, -1, sqlite3_free);
|
|
+#endif
|
|
+ }
|
|
+ break;
|
|
+ case 6: /* p5 */
|
|
+ sqlite3_result_int(ctx, pOp->p5);
|
|
+ break;
|
|
+ case 8: { /* subprog */
|
|
+ Op *aOp = pCur->aOp;
|
|
+ assert( aOp[0].opcode==OP_Init );
|
|
+ assert( aOp[0].p4.z==0 || strncmp(aOp[0].p4.z,"-" "- ",3)==0 );
|
|
+ if( pCur->iRowid==pCur->iAddr+1 ){
|
|
+ break; /* Result is NULL for the main program */
|
|
+ }else if( aOp[0].p4.z!=0 ){
|
|
+ sqlite3_result_text(ctx, aOp[0].p4.z+3, -1, SQLITE_STATIC);
|
|
+ }else{
|
|
+ sqlite3_result_text(ctx, "(FK)", 4, SQLITE_STATIC);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ case 10: /* tables_used.type */
|
|
+ sqlite3_result_text(ctx, pCur->zType, -1, SQLITE_STATIC);
|
|
+ break;
|
|
+ case 11: /* tables_used.schema */
|
|
+ sqlite3_result_text(ctx, pCur->zSchema, -1, SQLITE_STATIC);
|
|
+ break;
|
|
+ case 12: /* tables_used.name */
|
|
+ sqlite3_result_text(ctx, pCur->zName, -1, SQLITE_STATIC);
|
|
+ break;
|
|
+ case 13: /* tables_used.wr */
|
|
+ sqlite3_result_int(ctx, pOp->opcode==OP_OpenWrite);
|
|
+ break;
|
|
+ }
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Return the rowid for the current row. In this implementation, the
|
|
+** rowid is the same as the output value.
|
|
+*/
|
|
+static int bytecodevtabRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
|
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor*)cur;
|
|
+ *pRowid = pCur->iRowid;
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Initialize a cursor.
|
|
+**
|
|
+** idxNum==0 means show all subprograms
|
|
+** idxNum==1 means show only the main bytecode and omit subprograms.
|
|
+*/
|
|
+static int bytecodevtabFilter(
|
|
+ sqlite3_vtab_cursor *pVtabCursor,
|
|
+ int idxNum, const char *idxStr,
|
|
+ int argc, sqlite3_value **argv
|
|
+){
|
|
+ bytecodevtab_cursor *pCur = (bytecodevtab_cursor *)pVtabCursor;
|
|
+ bytecodevtab *pVTab = (bytecodevtab *)pVtabCursor->pVtab;
|
|
+ int rc = SQLITE_OK;
|
|
+
|
|
+ bytecodevtabCursorClear(pCur);
|
|
+ pCur->iRowid = 0;
|
|
+ pCur->iAddr = 0;
|
|
+ pCur->showSubprograms = idxNum==0;
|
|
+ assert( argc==1 );
|
|
+ if( sqlite3_value_type(argv[0])==SQLITE_TEXT ){
|
|
+ const char *zSql = (const char*)sqlite3_value_text(argv[0]);
|
|
+ if( zSql==0 ){
|
|
+ rc = SQLITE_NOMEM;
|
|
+ }else{
|
|
+ rc = sqlite3_prepare_v2(pVTab->db, zSql, -1, &pCur->pStmt, 0);
|
|
+ pCur->needFinalize = 1;
|
|
+ }
|
|
+ }else{
|
|
+ pCur->pStmt = (sqlite3_stmt*)sqlite3_value_pointer(argv[0],"stmt-pointer");
|
|
+ }
|
|
+ if( pCur->pStmt==0 ){
|
|
+ pVTab->base.zErrMsg = sqlite3_mprintf(
|
|
+ "argument to %s() is not a valid SQL statement",
|
|
+ pVTab->bTablesUsed ? "tables_used" : "bytecode"
|
|
+ );
|
|
+ rc = SQLITE_ERROR;
|
|
+ }else{
|
|
+ bytecodevtabNext(pVtabCursor);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+** We must have a single stmt=? constraint that will be passed through
|
|
+** into the xFilter method. If there is no valid stmt=? constraint,
|
|
+** then return an SQLITE_CONSTRAINT error.
|
|
+*/
|
|
+static int bytecodevtabBestIndex(
|
|
+ sqlite3_vtab *tab,
|
|
+ sqlite3_index_info *pIdxInfo
|
|
+){
|
|
+ int i;
|
|
+ int rc = SQLITE_CONSTRAINT;
|
|
+ struct sqlite3_index_constraint *p;
|
|
+ bytecodevtab *pVTab = (bytecodevtab*)tab;
|
|
+ int iBaseCol = pVTab->bTablesUsed ? 4 : 8;
|
|
+ pIdxInfo->estimatedCost = (double)100;
|
|
+ pIdxInfo->estimatedRows = 100;
|
|
+ pIdxInfo->idxNum = 0;
|
|
+ for(i=0, p=pIdxInfo->aConstraint; i<pIdxInfo->nConstraint; i++, p++){
|
|
+ if( p->usable==0 ) continue;
|
|
+ if( p->op==SQLITE_INDEX_CONSTRAINT_EQ && p->iColumn==iBaseCol+1 ){
|
|
+ rc = SQLITE_OK;
|
|
+ pIdxInfo->aConstraintUsage[i].omit = 1;
|
|
+ pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
|
+ }
|
|
+ if( p->op==SQLITE_INDEX_CONSTRAINT_ISNULL && p->iColumn==iBaseCol ){
|
|
+ pIdxInfo->aConstraintUsage[i].omit = 1;
|
|
+ pIdxInfo->idxNum = 1;
|
|
+ }
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+
|
|
+/*
|
|
+** This following structure defines all the methods for the
|
|
+** virtual table.
|
|
+*/
|
|
+static sqlite3_module bytecodevtabModule = {
|
|
+ /* iVersion */ 0,
|
|
+ /* xCreate */ 0,
|
|
+ /* xConnect */ bytecodevtabConnect,
|
|
+ /* xBestIndex */ bytecodevtabBestIndex,
|
|
+ /* xDisconnect */ bytecodevtabDisconnect,
|
|
+ /* xDestroy */ 0,
|
|
+ /* xOpen */ bytecodevtabOpen,
|
|
+ /* xClose */ bytecodevtabClose,
|
|
+ /* xFilter */ bytecodevtabFilter,
|
|
+ /* xNext */ bytecodevtabNext,
|
|
+ /* xEof */ bytecodevtabEof,
|
|
+ /* xColumn */ bytecodevtabColumn,
|
|
+ /* xRowid */ bytecodevtabRowid,
|
|
+ /* xUpdate */ 0,
|
|
+ /* xBegin */ 0,
|
|
+ /* xSync */ 0,
|
|
+ /* xCommit */ 0,
|
|
+ /* xRollback */ 0,
|
|
+ /* xFindMethod */ 0,
|
|
+ /* xRename */ 0,
|
|
+ /* xSavepoint */ 0,
|
|
+ /* xRelease */ 0,
|
|
+ /* xRollbackTo */ 0,
|
|
+ /* xShadowName */ 0
|
|
+};
|
|
+
|
|
+
|
|
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){
|
|
+ int rc;
|
|
+ rc = sqlite3_create_module(db, "bytecode", &bytecodevtabModule, 0);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ rc = sqlite3_create_module(db, "tables_used", &bytecodevtabModule, &db);
|
|
+ }
|
|
+ return rc;
|
|
+}
|
|
+#elif defined(SQLITE_ENABLE_BYTECODE_VTAB)
|
|
+SQLITE_PRIVATE int sqlite3VdbeBytecodeVtabInit(sqlite3 *db){ return SQLITE_OK; }
|
|
+#endif /* SQLITE_ENABLE_BYTECODE_VTAB */
|
|
+
|
|
+/************** End of vdbevtab.c ********************************************/
|
|
/************** Begin file memjournal.c **************************************/
|
|
/*
|
|
** 2008 October 7
|
|
@@ -94883,14 +96943,9 @@
|
|
int iChunkOffset;
|
|
FileChunk *pChunk;
|
|
|
|
-#if defined(SQLITE_ENABLE_ATOMIC_WRITE) \
|
|
- || defined(SQLITE_ENABLE_BATCH_ATOMIC_WRITE)
|
|
if( (iAmt+iOfst)>p->endpoint.iOffset ){
|
|
return SQLITE_IOERR_SHORT_READ;
|
|
}
|
|
-#endif
|
|
-
|
|
- assert( (iAmt+iOfst)<=p->endpoint.iOffset );
|
|
assert( p->readpoint.iOffset==0 || p->readpoint.pChunk!=0 );
|
|
if( p->readpoint.iOffset!=iOfst || iOfst==0 ){
|
|
sqlite3_int64 iOff = 0;
|
|
@@ -95249,9 +97304,22 @@
|
|
static int walkWindowList(Walker *pWalker, Window *pList){
|
|
Window *pWin;
|
|
for(pWin=pList; pWin; pWin=pWin->pNextWin){
|
|
- if( sqlite3WalkExprList(pWalker, pWin->pOrderBy) ) return WRC_Abort;
|
|
- if( sqlite3WalkExprList(pWalker, pWin->pPartition) ) return WRC_Abort;
|
|
- if( sqlite3WalkExpr(pWalker, pWin->pFilter) ) return WRC_Abort;
|
|
+ int rc;
|
|
+ rc = sqlite3WalkExprList(pWalker, pWin->pOrderBy);
|
|
+ if( rc ) return WRC_Abort;
|
|
+ rc = sqlite3WalkExprList(pWalker, pWin->pPartition);
|
|
+ if( rc ) return WRC_Abort;
|
|
+ rc = sqlite3WalkExpr(pWalker, pWin->pFilter);
|
|
+ if( rc ) return WRC_Abort;
|
|
+
|
|
+ /* The next two are purely for calls to sqlite3RenameExprUnmap()
|
|
+ ** within sqlite3WindowOffsetExpr(). Because of constraints imposed
|
|
+ ** by sqlite3WindowOffsetExpr(), they can never fail. The results do
|
|
+ ** not matter anyhow. */
|
|
+ rc = sqlite3WalkExpr(pWalker, pWin->pStart);
|
|
+ if( NEVER(rc) ) return WRC_Abort;
|
|
+ rc = sqlite3WalkExpr(pWalker, pWin->pEnd);
|
|
+ if( NEVER(rc) ) return WRC_Abort;
|
|
}
|
|
return WRC_Continue;
|
|
}
|
|
@@ -95284,21 +97352,25 @@
|
|
rc = pWalker->xExprCallback(pWalker, pExpr);
|
|
if( rc ) return rc & WRC_Abort;
|
|
if( !ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
|
|
+ assert( pExpr->x.pList==0 || pExpr->pRight==0 );
|
|
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
|
- assert( pExpr->x.pList==0 || pExpr->pRight==0 );
|
|
if( pExpr->pRight ){
|
|
+ assert( !ExprHasProperty(pExpr, EP_WinFunc) );
|
|
pExpr = pExpr->pRight;
|
|
continue;
|
|
}else if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
|
+ assert( !ExprHasProperty(pExpr, EP_WinFunc) );
|
|
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
|
|
- }else if( pExpr->x.pList ){
|
|
- if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
|
- }
|
|
+ }else{
|
|
+ if( pExpr->x.pList ){
|
|
+ if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
|
+ }
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
- if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
|
|
- }
|
|
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ if( walkWindowList(pWalker, pExpr->y.pWin) ) return WRC_Abort;
|
|
+ }
|
|
#endif
|
|
+ }
|
|
}
|
|
break;
|
|
}
|
|
@@ -95340,8 +97412,9 @@
|
|
{
|
|
Parse *pParse = pWalker->pParse;
|
|
if( pParse && IN_RENAME_OBJECT ){
|
|
+ /* The following may return WRC_Abort if there are unresolvable
|
|
+ ** symbols (e.g. a table that does not exist) in a window definition. */
|
|
int rc = walkWindowList(pWalker, p->pWinDefn);
|
|
- assert( rc==WRC_Continue );
|
|
return rc;
|
|
}
|
|
}
|
|
@@ -95362,15 +97435,16 @@
|
|
struct SrcList_item *pItem;
|
|
|
|
pSrc = p->pSrc;
|
|
- assert( pSrc!=0 );
|
|
- for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
|
|
- if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
|
|
- return WRC_Abort;
|
|
- }
|
|
- if( pItem->fg.isTabFunc
|
|
- && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
|
|
- ){
|
|
- return WRC_Abort;
|
|
+ if( pSrc ){
|
|
+ for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
|
|
+ if( pItem->pSelect && sqlite3WalkSelect(pWalker, pItem->pSelect) ){
|
|
+ return WRC_Abort;
|
|
+ }
|
|
+ if( pItem->fg.isTabFunc
|
|
+ && sqlite3WalkExprList(pWalker, pItem->u1.pFuncArg)
|
|
+ ){
|
|
+ return WRC_Abort;
|
|
+ }
|
|
}
|
|
}
|
|
return WRC_Continue;
|
|
@@ -95413,6 +97487,43 @@
|
|
return WRC_Continue;
|
|
}
|
|
|
|
+/* Increase the walkerDepth when entering a subquery, and
|
|
+** descrease when leaving the subquery.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3WalkerDepthIncrease(Walker *pWalker, Select *pSelect){
|
|
+ UNUSED_PARAMETER(pSelect);
|
|
+ pWalker->walkerDepth++;
|
|
+ return WRC_Continue;
|
|
+}
|
|
+SQLITE_PRIVATE void sqlite3WalkerDepthDecrease(Walker *pWalker, Select *pSelect){
|
|
+ UNUSED_PARAMETER(pSelect);
|
|
+ pWalker->walkerDepth--;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+** No-op routine for the parse-tree walker.
|
|
+**
|
|
+** When this routine is the Walker.xExprCallback then expression trees
|
|
+** are walked without any actions being taken at each node. Presumably,
|
|
+** when this routine is used for Walker.xExprCallback then
|
|
+** Walker.xSelectCallback is set to do something useful for every
|
|
+** subquery in the parser tree.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
|
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
+ return WRC_Continue;
|
|
+}
|
|
+
|
|
+/*
|
|
+** No-op routine for the parse-tree walker for SELECT statements.
|
|
+** subquery in the parser tree.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
|
|
+ UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
+ return WRC_Continue;
|
|
+}
|
|
+
|
|
/************** End of walker.c **********************************************/
|
|
/************** Begin file resolve.c *****************************************/
|
|
/*
|
|
@@ -95441,6 +97552,8 @@
|
|
**
|
|
** incrAggFunctionDepth(pExpr,n) is the main routine. incrAggDepth(..)
|
|
** is a helper function - a callback for the tree walker.
|
|
+**
|
|
+** See also the sqlite3WindowExtraAggFuncDepth() routine in window.c
|
|
*/
|
|
static int incrAggDepth(Walker *pWalker, Expr *pExpr){
|
|
if( pExpr->op==TK_AGG_FUNCTION ) pExpr->op2 += pWalker->u.n;
|
|
@@ -95513,6 +97626,13 @@
|
|
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
|
pExpr->flags |= EP_MemToken;
|
|
}
|
|
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ if( pExpr->y.pWin!=0 ){
|
|
+ pExpr->y.pWin->pOwner = pExpr;
|
|
+ }else{
|
|
+ assert( db->mallocFailed );
|
|
+ }
|
|
+ }
|
|
sqlite3DbFree(db, pDup);
|
|
}
|
|
ExprSetProperty(pExpr, EP_Alias);
|
|
@@ -95542,13 +97662,16 @@
|
|
** and zCol. If any of zDb, zTab, and zCol are NULL then those fields will
|
|
** match anything.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3MatchSpanName(
|
|
- const char *zSpan,
|
|
+SQLITE_PRIVATE int sqlite3MatchEName(
|
|
+ const struct ExprList_item *pItem,
|
|
const char *zCol,
|
|
const char *zTab,
|
|
const char *zDb
|
|
){
|
|
int n;
|
|
+ const char *zSpan;
|
|
+ if( pItem->eEName!=ENAME_TAB ) return 0;
|
|
+ zSpan = pItem->zEName;
|
|
for(n=0; ALWAYS(zSpan[n]) && zSpan[n]!='.'; n++){}
|
|
if( zDb && (sqlite3StrNICmp(zSpan, zDb, n)!=0 || zDb[n]!=0) ){
|
|
return 0;
|
|
@@ -95582,6 +97705,31 @@
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+** The argument is guaranteed to be a non-NULL Expr node of type TK_COLUMN.
|
|
+** return the appropriate colUsed mask.
|
|
+*/
|
|
+SQLITE_PRIVATE Bitmask sqlite3ExprColUsed(Expr *pExpr){
|
|
+ int n;
|
|
+ Table *pExTab;
|
|
+
|
|
+ n = pExpr->iColumn;
|
|
+ pExTab = pExpr->y.pTab;
|
|
+ assert( pExTab!=0 );
|
|
+ if( (pExTab->tabFlags & TF_HasGenerated)!=0
|
|
+ && (pExTab->aCol[n].colFlags & COLFLAG_GENERATED)!=0
|
|
+ ){
|
|
+ testcase( pExTab->nCol==BMS-1 );
|
|
+ testcase( pExTab->nCol==BMS );
|
|
+ return pExTab->nCol>=BMS ? ALLBITS : MASKBIT(pExTab->nCol)-1;
|
|
+ }else{
|
|
+ testcase( n==BMS-1 );
|
|
+ testcase( n==BMS );
|
|
+ if( n>=BMS ) n = BMS-1;
|
|
+ return ((Bitmask)1)<<n;
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Given the name of a column of the form X.Y.Z or Y.Z or just Z, look up
|
|
** that name in the set of source tables in pSrcList and make the pExpr
|
|
@@ -95659,6 +97807,12 @@
|
|
break;
|
|
}
|
|
}
|
|
+ if( i==db->nDb && sqlite3StrICmp("main", zDb)==0 ){
|
|
+ /* This branch is taken when the main database has been renamed
|
|
+ ** using SQLITE_DBCONFIG_MAINDBNAME. */
|
|
+ pSchema = db->aDb[0].pSchema;
|
|
+ zDb = db->aDb[0].zDbSName;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -95670,6 +97824,7 @@
|
|
|
|
if( pSrcList ){
|
|
for(i=0, pItem=pSrcList->a; i<pSrcList->nSrc; i++, pItem++){
|
|
+ u8 hCol;
|
|
pTab = pItem->pTab;
|
|
assert( pTab!=0 && pTab->zName!=0 );
|
|
assert( pTab->nCol>0 );
|
|
@@ -95677,7 +97832,7 @@
|
|
int hit = 0;
|
|
pEList = pItem->pSelect->pEList;
|
|
for(j=0; j<pEList->nExpr; j++){
|
|
- if( sqlite3MatchSpanName(pEList->a[j].zSpan, zCol, zTab, zDb) ){
|
|
+ if( sqlite3MatchEName(&pEList->a[j], zCol, zTab, zDb) ){
|
|
cnt++;
|
|
cntTab = 2;
|
|
pMatch = pItem;
|
|
@@ -95703,8 +97858,9 @@
|
|
if( 0==(cntTab++) ){
|
|
pMatch = pItem;
|
|
}
|
|
+ hCol = sqlite3StrIHash(zCol);
|
|
for(j=0, pCol=pTab->aCol; j<pTab->nCol; j++, pCol++){
|
|
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
|
+ if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
|
/* If there has been exactly one prior match and this match
|
|
** is for the right-hand table of a NATURAL JOIN or is in a
|
|
** USING clause, then skip this match.
|
|
@@ -95765,10 +97921,11 @@
|
|
|
|
if( pTab ){
|
|
int iCol;
|
|
+ u8 hCol = sqlite3StrIHash(zCol);
|
|
pSchema = pTab->pSchema;
|
|
cntTab++;
|
|
for(iCol=0, pCol=pTab->aCol; iCol<pTab->nCol; iCol++, pCol++){
|
|
- if( sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
|
+ if( pCol->hName==hCol && sqlite3StrICmp(pCol->zName, zCol)==0 ){
|
|
if( iCol==pTab->iPKey ){
|
|
iCol = -1;
|
|
}
|
|
@@ -95798,7 +97955,7 @@
|
|
{
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
if( iCol<0 ){
|
|
- pExpr->affinity = SQLITE_AFF_INTEGER;
|
|
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
|
|
}else if( pExpr->iTable==0 ){
|
|
testcase( iCol==31 );
|
|
testcase( iCol==32 );
|
|
@@ -95824,13 +97981,13 @@
|
|
if( cnt==0
|
|
&& cntTab==1
|
|
&& pMatch
|
|
- && (pNC->ncFlags & NC_IdxExpr)==0
|
|
+ && (pNC->ncFlags & (NC_IdxExpr|NC_GenCol))==0
|
|
&& sqlite3IsRowid(zCol)
|
|
&& VisibleRowid(pMatch->pTab)
|
|
){
|
|
cnt = 1;
|
|
pExpr->iColumn = -1;
|
|
- pExpr->affinity = SQLITE_AFF_INTEGER;
|
|
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
|
|
}
|
|
|
|
/*
|
|
@@ -95858,8 +98015,10 @@
|
|
pEList = pNC->uNC.pEList;
|
|
assert( pEList!=0 );
|
|
for(j=0; j<pEList->nExpr; j++){
|
|
- char *zAs = pEList->a[j].zName;
|
|
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
|
+ char *zAs = pEList->a[j].zEName;
|
|
+ if( pEList->a[j].eEName==ENAME_NAME
|
|
+ && sqlite3_stricmp(zAs, zCol)==0
|
|
+ ){
|
|
Expr *pOrig;
|
|
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
|
assert( pExpr->x.pList==0 );
|
|
@@ -95869,7 +98028,9 @@
|
|
sqlite3ErrorMsg(pParse, "misuse of aliased aggregate %s", zAs);
|
|
return WRC_Abort;
|
|
}
|
|
- if( (pNC->ncFlags&NC_AllowWin)==0 && ExprHasProperty(pOrig, EP_Win) ){
|
|
+ if( ExprHasProperty(pOrig, EP_Win)
|
|
+ && ((pNC->ncFlags&NC_AllowWin)==0 || pNC!=pTopNC )
|
|
+ ){
|
|
sqlite3ErrorMsg(pParse, "misuse of aliased window function %s",zAs);
|
|
return WRC_Abort;
|
|
}
|
|
@@ -95961,18 +98122,20 @@
|
|
|
|
/* If a column from a table in pSrcList is referenced, then record
|
|
** this fact in the pSrcList.a[].colUsed bitmask. Column 0 causes
|
|
- ** bit 0 to be set. Column 1 sets bit 1. And so forth. If the
|
|
- ** column number is greater than the number of bits in the bitmask
|
|
- ** then set the high-order bit of the bitmask.
|
|
+ ** bit 0 to be set. Column 1 sets bit 1. And so forth. Bit 63 is
|
|
+ ** set if the 63rd or any subsequent column is used.
|
|
+ **
|
|
+ ** The colUsed mask is an optimization used to help determine if an
|
|
+ ** index is a covering index. The correct answer is still obtained
|
|
+ ** if the mask contains extra set bits. However, it is important to
|
|
+ ** avoid setting bits beyond the maximum column number of the table.
|
|
+ ** (See ticket [b92e5e8ec2cdbaa1]).
|
|
+ **
|
|
+ ** If a generated column is referenced, set bits for every column
|
|
+ ** of the table.
|
|
*/
|
|
if( pExpr->iColumn>=0 && pMatch!=0 ){
|
|
- int n = pExpr->iColumn;
|
|
- testcase( n==BMS-1 );
|
|
- if( n>=BMS ){
|
|
- n = BMS-1;
|
|
- }
|
|
- assert( pMatch->iCursor==pExpr->iTable );
|
|
- pMatch->colUsed |= ((Bitmask)1)<<n;
|
|
+ pMatch->colUsed |= sqlite3ExprColUsed(pExpr);
|
|
}
|
|
|
|
/* Clean up and return
|
|
@@ -96011,15 +98174,23 @@
|
|
Expr *p = sqlite3ExprAlloc(db, TK_COLUMN, 0, 0);
|
|
if( p ){
|
|
struct SrcList_item *pItem = &pSrc->a[iSrc];
|
|
- p->y.pTab = pItem->pTab;
|
|
+ Table *pTab = p->y.pTab = pItem->pTab;
|
|
p->iTable = pItem->iCursor;
|
|
if( p->y.pTab->iPKey==iCol ){
|
|
p->iColumn = -1;
|
|
}else{
|
|
p->iColumn = (ynVar)iCol;
|
|
- testcase( iCol==BMS );
|
|
- testcase( iCol==BMS-1 );
|
|
- pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
|
|
+ if( (pTab->tabFlags & TF_HasGenerated)!=0
|
|
+ && (pTab->aCol[iCol].colFlags & COLFLAG_GENERATED)!=0
|
|
+ ){
|
|
+ testcase( pTab->nCol==63 );
|
|
+ testcase( pTab->nCol==64 );
|
|
+ pItem->colUsed = pTab->nCol>=64 ? ALLBITS : MASKBIT(pTab->nCol)-1;
|
|
+ }else{
|
|
+ testcase( iCol==BMS );
|
|
+ testcase( iCol==BMS-1 );
|
|
+ pItem->colUsed |= ((Bitmask)1)<<(iCol>=BMS ? BMS-1 : iCol);
|
|
+ }
|
|
}
|
|
}
|
|
return p;
|
|
@@ -96028,23 +98199,39 @@
|
|
/*
|
|
** Report an error that an expression is not valid for some set of
|
|
** pNC->ncFlags values determined by validMask.
|
|
-*/
|
|
-static void notValid(
|
|
- Parse *pParse, /* Leave error message here */
|
|
- NameContext *pNC, /* The name context */
|
|
- const char *zMsg, /* Type of error */
|
|
- int validMask /* Set of contexts for which prohibited */
|
|
-){
|
|
- assert( (validMask&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr))==0 );
|
|
- if( (pNC->ncFlags & validMask)!=0 ){
|
|
- const char *zIn = "partial index WHERE clauses";
|
|
- if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
|
|
+**
|
|
+** static void notValid(
|
|
+** Parse *pParse, // Leave error message here
|
|
+** NameContext *pNC, // The name context
|
|
+** const char *zMsg, // Type of error
|
|
+** int validMask, // Set of contexts for which prohibited
|
|
+** Expr *pExpr // Invalidate this expression on error
|
|
+** ){...}
|
|
+**
|
|
+** As an optimization, since the conditional is almost always false
|
|
+** (because errors are rare), the conditional is moved outside of the
|
|
+** function call using a macro.
|
|
+*/
|
|
+static void notValidImpl(
|
|
+ Parse *pParse, /* Leave error message here */
|
|
+ NameContext *pNC, /* The name context */
|
|
+ const char *zMsg, /* Type of error */
|
|
+ Expr *pExpr /* Invalidate this expression on error */
|
|
+){
|
|
+ const char *zIn = "partial index WHERE clauses";
|
|
+ if( pNC->ncFlags & NC_IdxExpr ) zIn = "index expressions";
|
|
#ifndef SQLITE_OMIT_CHECK
|
|
- else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
|
|
+ else if( pNC->ncFlags & NC_IsCheck ) zIn = "CHECK constraints";
|
|
#endif
|
|
- sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
|
|
- }
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ else if( pNC->ncFlags & NC_GenCol ) zIn = "generated columns";
|
|
+#endif
|
|
+ sqlite3ErrorMsg(pParse, "%s prohibited in %s", zMsg, zIn);
|
|
+ if( pExpr ) pExpr->op = TK_NULL;
|
|
}
|
|
+#define sqlite3ResolveNotValid(P,N,M,X,E) \
|
|
+ assert( ((X)&~(NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol))==0 ); \
|
|
+ if( ((N)->ncFlags & (X))!=0 ) notValidImpl(P,N,M,E);
|
|
|
|
/*
|
|
** Expression p should encode a floating point value between 1.0 and 0.0.
|
|
@@ -96106,7 +98293,7 @@
|
|
pExpr->y.pTab = pItem->pTab;
|
|
pExpr->iTable = pItem->iCursor;
|
|
pExpr->iColumn = -1;
|
|
- pExpr->affinity = SQLITE_AFF_INTEGER;
|
|
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
|
|
break;
|
|
}
|
|
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
|
|
@@ -96133,7 +98320,10 @@
|
|
zColumn = pExpr->u.zToken;
|
|
}else{
|
|
Expr *pLeft = pExpr->pLeft;
|
|
- notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
|
|
+ testcase( pNC->ncFlags & NC_IdxExpr );
|
|
+ testcase( pNC->ncFlags & NC_GenCol );
|
|
+ sqlite3ResolveNotValid(pParse, pNC, "the \".\" operator",
|
|
+ NC_IdxExpr|NC_GenCol, 0);
|
|
pRight = pExpr->pRight;
|
|
if( pRight->op==TK_ID ){
|
|
zDb = 0;
|
|
@@ -96166,7 +98356,9 @@
|
|
FuncDef *pDef; /* Information about the function */
|
|
u8 enc = ENC(pParse->db); /* The database encoding */
|
|
int savedAllowFlags = (pNC->ncFlags & (NC_AllowAgg | NC_AllowWin));
|
|
-
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ Window *pWin = (IsWindowFunc(pExpr) ? pExpr->y.pWin : 0);
|
|
+#endif
|
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
|
zId = pExpr->u.zToken;
|
|
nId = sqlite3Strlen30(zId);
|
|
@@ -96220,24 +98412,39 @@
|
|
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
|
/* For the purposes of the EP_ConstFunc flag, date and time
|
|
** functions and other functions that change slowly are considered
|
|
- ** constant because they are constant for the duration of one query */
|
|
+ ** constant because they are constant for the duration of one query.
|
|
+ ** This allows them to be factored out of inner loops. */
|
|
ExprSetProperty(pExpr,EP_ConstFunc);
|
|
}
|
|
if( (pDef->funcFlags & SQLITE_FUNC_CONSTANT)==0 ){
|
|
- /* Date/time functions that use 'now', and other functions like
|
|
+ /* Clearly non-deterministic functions like random(), but also
|
|
+ ** date/time functions that use 'now', and other functions like
|
|
** sqlite_version() that might change over time cannot be used
|
|
- ** in an index. */
|
|
- notValid(pParse, pNC, "non-deterministic functions",
|
|
- NC_IdxExpr|NC_PartIdx);
|
|
+ ** in an index or generated column. Curiously, they can be used
|
|
+ ** in a CHECK constraint. SQLServer, MySQL, and PostgreSQL all
|
|
+ ** all this. */
|
|
+ sqlite3ResolveNotValid(pParse, pNC, "non-deterministic functions",
|
|
+ NC_IdxExpr|NC_PartIdx|NC_GenCol, 0);
|
|
+ }else{
|
|
+ assert( (NC_SelfRef & 0xff)==NC_SelfRef ); /* Must fit in 8 bits */
|
|
+ pExpr->op2 = pNC->ncFlags & NC_SelfRef;
|
|
+ if( pNC->ncFlags & NC_FromDDL ) ExprSetProperty(pExpr, EP_FromDDL);
|
|
}
|
|
if( (pDef->funcFlags & SQLITE_FUNC_INTERNAL)!=0
|
|
&& pParse->nested==0
|
|
- && sqlite3Config.bInternalFunctions==0
|
|
+ && (pParse->db->mDbFlags & DBFLAG_InternalFunc)==0
|
|
){
|
|
/* Internal-use-only functions are disallowed unless the
|
|
- ** SQL is being compiled using sqlite3NestedParse() */
|
|
+ ** SQL is being compiled using sqlite3NestedParse() or
|
|
+ ** the SQLITE_TESTCTRL_INTERNAL_FUNCTIONS test-control has be
|
|
+ ** used to activate internal functionsn for testing purposes */
|
|
no_such_func = 1;
|
|
pDef = 0;
|
|
+ }else
|
|
+ if( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0
|
|
+ && !IN_RENAME_OBJECT
|
|
+ ){
|
|
+ sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
|
|
}
|
|
}
|
|
|
|
@@ -96247,18 +98454,18 @@
|
|
|| (pDef->xValue==0 && pDef->xInverse==0)
|
|
|| (pDef->xValue && pDef->xInverse && pDef->xSFunc && pDef->xFinalize)
|
|
);
|
|
- if( pDef && pDef->xValue==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ if( pDef && pDef->xValue==0 && pWin ){
|
|
sqlite3ErrorMsg(pParse,
|
|
"%.*s() may not be used as a window function", nId, zId
|
|
);
|
|
pNC->nErr++;
|
|
}else if(
|
|
(is_agg && (pNC->ncFlags & NC_AllowAgg)==0)
|
|
- || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pExpr->y.pWin)
|
|
- || (is_agg && pExpr->y.pWin && (pNC->ncFlags & NC_AllowWin)==0)
|
|
+ || (is_agg && (pDef->funcFlags&SQLITE_FUNC_WINDOW) && !pWin)
|
|
+ || (is_agg && pWin && (pNC->ncFlags & NC_AllowWin)==0)
|
|
){
|
|
const char *zType;
|
|
- if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pExpr->y.pWin ){
|
|
+ if( (pDef->funcFlags & SQLITE_FUNC_WINDOW) || pWin ){
|
|
zType = "window";
|
|
}else{
|
|
zType = "aggregate";
|
|
@@ -96286,34 +98493,44 @@
|
|
nId, zId);
|
|
pNC->nErr++;
|
|
}
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ else if( is_agg==0 && ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ sqlite3ErrorMsg(pParse,
|
|
+ "FILTER may not be used with non-aggregate %.*s()",
|
|
+ nId, zId
|
|
+ );
|
|
+ pNC->nErr++;
|
|
+ }
|
|
+#endif
|
|
if( is_agg ){
|
|
/* Window functions may not be arguments of aggregate functions.
|
|
** Or arguments of other window functions. But aggregate functions
|
|
** may be arguments for window functions. */
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- pNC->ncFlags &= ~(NC_AllowWin | (!pExpr->y.pWin ? NC_AllowAgg : 0));
|
|
+ pNC->ncFlags &= ~(NC_AllowWin | (!pWin ? NC_AllowAgg : 0));
|
|
#else
|
|
pNC->ncFlags &= ~NC_AllowAgg;
|
|
#endif
|
|
}
|
|
}
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ else if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ is_agg = 1;
|
|
+ }
|
|
+#endif
|
|
sqlite3WalkExprList(pWalker, pList);
|
|
if( is_agg ){
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- if( pExpr->y.pWin ){
|
|
+ if( pWin ){
|
|
Select *pSel = pNC->pWinSelect;
|
|
+ assert( pWin==pExpr->y.pWin );
|
|
if( IN_RENAME_OBJECT==0 ){
|
|
- sqlite3WindowUpdate(pParse, pSel->pWinDefn, pExpr->y.pWin, pDef);
|
|
- }
|
|
- sqlite3WalkExprList(pWalker, pExpr->y.pWin->pPartition);
|
|
- sqlite3WalkExprList(pWalker, pExpr->y.pWin->pOrderBy);
|
|
- sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
|
|
- if( 0==pSel->pWin
|
|
- || 0==sqlite3WindowCompare(pParse, pSel->pWin, pExpr->y.pWin)
|
|
- ){
|
|
- pExpr->y.pWin->pNextWin = pSel->pWin;
|
|
- pSel->pWin = pExpr->y.pWin;
|
|
+ sqlite3WindowUpdate(pParse, pSel ? pSel->pWinDefn : 0, pWin, pDef);
|
|
}
|
|
+ sqlite3WalkExprList(pWalker, pWin->pPartition);
|
|
+ sqlite3WalkExprList(pWalker, pWin->pOrderBy);
|
|
+ sqlite3WalkExpr(pWalker, pWin->pFilter);
|
|
+ sqlite3WindowLink(pSel, pWin);
|
|
pNC->ncFlags |= NC_HasWin;
|
|
}else
|
|
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
|
@@ -96321,12 +98538,17 @@
|
|
NameContext *pNC2 = pNC;
|
|
pExpr->op = TK_AGG_FUNCTION;
|
|
pExpr->op2 = 0;
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ sqlite3WalkExpr(pWalker, pExpr->y.pWin->pFilter);
|
|
+ }
|
|
+#endif
|
|
while( pNC2 && !sqlite3FunctionUsesThisSrc(pExpr, pNC2->pSrcList) ){
|
|
pExpr->op2++;
|
|
pNC2 = pNC2->pNext;
|
|
}
|
|
- assert( pDef!=0 );
|
|
- if( pNC2 ){
|
|
+ assert( pDef!=0 || IN_RENAME_OBJECT );
|
|
+ if( pNC2 && pDef ){
|
|
assert( SQLITE_FUNC_MINMAX==NC_MinMaxAgg );
|
|
testcase( (pDef->funcFlags & SQLITE_FUNC_MINMAX)!=0 );
|
|
pNC2->ncFlags |= NC_HasAgg | (pDef->funcFlags & SQLITE_FUNC_MINMAX);
|
|
@@ -96348,7 +98570,12 @@
|
|
testcase( pExpr->op==TK_IN );
|
|
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
|
int nRef = pNC->nRef;
|
|
- notValid(pParse, pNC, "subqueries", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
|
|
+ testcase( pNC->ncFlags & NC_IsCheck );
|
|
+ testcase( pNC->ncFlags & NC_PartIdx );
|
|
+ testcase( pNC->ncFlags & NC_IdxExpr );
|
|
+ testcase( pNC->ncFlags & NC_GenCol );
|
|
+ sqlite3ResolveNotValid(pParse, pNC, "subqueries",
|
|
+ NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
|
|
sqlite3WalkSelect(pWalker, pExpr->x.pSelect);
|
|
assert( pNC->nRef>=nRef );
|
|
if( nRef!=pNC->nRef ){
|
|
@@ -96359,16 +98586,21 @@
|
|
break;
|
|
}
|
|
case TK_VARIABLE: {
|
|
- notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr);
|
|
+ testcase( pNC->ncFlags & NC_IsCheck );
|
|
+ testcase( pNC->ncFlags & NC_PartIdx );
|
|
+ testcase( pNC->ncFlags & NC_IdxExpr );
|
|
+ testcase( pNC->ncFlags & NC_GenCol );
|
|
+ sqlite3ResolveNotValid(pParse, pNC, "parameters",
|
|
+ NC_IsCheck|NC_PartIdx|NC_IdxExpr|NC_GenCol, pExpr);
|
|
break;
|
|
}
|
|
case TK_IS:
|
|
case TK_ISNOT: {
|
|
- Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight);
|
|
+ Expr *pRight = sqlite3ExprSkipCollateAndLikely(pExpr->pRight);
|
|
assert( !ExprHasProperty(pExpr, EP_Reduced) );
|
|
/* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE",
|
|
** and "x IS NOT FALSE". */
|
|
- if( pRight->op==TK_ID ){
|
|
+ if( pRight && pRight->op==TK_ID ){
|
|
int rc = resolveExprStep(pWalker, pRight);
|
|
if( rc==WRC_Abort ) return WRC_Abort;
|
|
if( pRight->op==TK_TRUEFALSE ){
|
|
@@ -96441,8 +98673,9 @@
|
|
if( pE->op==TK_ID ){
|
|
char *zCol = pE->u.zToken;
|
|
for(i=0; i<pEList->nExpr; i++){
|
|
- char *zAs = pEList->a[i].zName;
|
|
- if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){
|
|
+ if( pEList->a[i].eEName==ENAME_NAME
|
|
+ && sqlite3_stricmp(pEList->a[i].zEName, zCol)==0
|
|
+ ){
|
|
return i+1;
|
|
}
|
|
}
|
|
@@ -96493,7 +98726,7 @@
|
|
nc.nErr = 0;
|
|
db = pParse->db;
|
|
savedSuppErr = db->suppressErr;
|
|
- db->suppressErr = 1;
|
|
+ if( IN_RENAME_OBJECT==0 ) db->suppressErr = 1;
|
|
rc = sqlite3ResolveExprNames(&nc, pE);
|
|
db->suppressErr = savedSuppErr;
|
|
if( rc ) return 0;
|
|
@@ -96575,7 +98808,7 @@
|
|
int iCol = -1;
|
|
Expr *pE, *pDup;
|
|
if( pItem->done ) continue;
|
|
- pE = sqlite3ExprSkipCollate(pItem->pExpr);
|
|
+ pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
|
|
if( sqlite3ExprIsInteger(pE, &iCol) ){
|
|
if( iCol<=0 || iCol>pEList->nExpr ){
|
|
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr);
|
|
@@ -96669,7 +98902,7 @@
|
|
ExprList *pEList;
|
|
struct ExprList_item *pItem;
|
|
|
|
- if( pOrderBy==0 || pParse->db->mallocFailed ) return 0;
|
|
+ if( pOrderBy==0 || pParse->db->mallocFailed || IN_RENAME_OBJECT ) return 0;
|
|
if( pOrderBy->nExpr>db->aLimit[SQLITE_LIMIT_COLUMN] ){
|
|
sqlite3ErrorMsg(pParse, "too many terms in %s BY clause", zType);
|
|
return 1;
|
|
@@ -96691,17 +98924,13 @@
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
/*
|
|
-** Walker callback for resolveRemoveWindows().
|
|
+** Walker callback for windowRemoveExprFromSelect().
|
|
*/
|
|
static int resolveRemoveWindowsCb(Walker *pWalker, Expr *pExpr){
|
|
+ UNUSED_PARAMETER(pWalker);
|
|
if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
- Window **pp;
|
|
- for(pp=&pWalker->u.pSelect->pWin; *pp; pp=&(*pp)->pNextWin){
|
|
- if( *pp==pExpr->y.pWin ){
|
|
- *pp = (*pp)->pNextWin;
|
|
- break;
|
|
- }
|
|
- }
|
|
+ Window *pWin = pExpr->y.pWin;
|
|
+ sqlite3WindowUnlinkFromSelect(pWin);
|
|
}
|
|
return WRC_Continue;
|
|
}
|
|
@@ -96710,16 +98939,18 @@
|
|
** Remove any Window objects owned by the expression pExpr from the
|
|
** Select.pWin list of Select object pSelect.
|
|
*/
|
|
-static void resolveRemoveWindows(Select *pSelect, Expr *pExpr){
|
|
- Walker sWalker;
|
|
- memset(&sWalker, 0, sizeof(Walker));
|
|
- sWalker.xExprCallback = resolveRemoveWindowsCb;
|
|
- sWalker.u.pSelect = pSelect;
|
|
- sqlite3WalkExpr(&sWalker, pExpr);
|
|
+static void windowRemoveExprFromSelect(Select *pSelect, Expr *pExpr){
|
|
+ if( pSelect->pWin ){
|
|
+ Walker sWalker;
|
|
+ memset(&sWalker, 0, sizeof(Walker));
|
|
+ sWalker.xExprCallback = resolveRemoveWindowsCb;
|
|
+ sWalker.u.pSelect = pSelect;
|
|
+ sqlite3WalkExpr(&sWalker, pExpr);
|
|
+ }
|
|
}
|
|
#else
|
|
-# define resolveRemoveWindows(x,y)
|
|
-#endif
|
|
+# define windowRemoveExprFromSelect(a, b)
|
|
+#endif /* SQLITE_OMIT_WINDOWFUNC */
|
|
|
|
/*
|
|
** pOrderBy is an ORDER BY or GROUP BY clause in SELECT statement pSelect.
|
|
@@ -96756,7 +98987,7 @@
|
|
pParse = pNC->pParse;
|
|
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
|
|
Expr *pE = pItem->pExpr;
|
|
- Expr *pE2 = sqlite3ExprSkipCollate(pE);
|
|
+ Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pE);
|
|
if( zType[0]!='G' ){
|
|
iCol = resolveAsName(pParse, pSelect->pEList, pE2);
|
|
if( iCol>0 ){
|
|
@@ -96790,7 +99021,7 @@
|
|
/* Since this expresion is being changed into a reference
|
|
** to an identical expression in the result set, remove all Window
|
|
** objects belonging to the expression from the Select.pWin list. */
|
|
- resolveRemoveWindows(pSelect, pE);
|
|
+ windowRemoveExprFromSelect(pSelect, pE);
|
|
pItem->u.x.iOrderByCol = j+1;
|
|
}
|
|
}
|
|
@@ -97130,11 +99361,41 @@
|
|
ExprList *pList /* The expression list to be analyzed. */
|
|
){
|
|
int i;
|
|
- if( pList ){
|
|
- for(i=0; i<pList->nExpr; i++){
|
|
- if( sqlite3ResolveExprNames(pNC, pList->a[i].pExpr) ) return WRC_Abort;
|
|
+ int savedHasAgg = 0;
|
|
+ Walker w;
|
|
+ if( pList==0 ) return WRC_Continue;
|
|
+ w.pParse = pNC->pParse;
|
|
+ w.xExprCallback = resolveExprStep;
|
|
+ w.xSelectCallback = resolveSelectStep;
|
|
+ w.xSelectCallback2 = 0;
|
|
+ w.u.pNC = pNC;
|
|
+ savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
|
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
|
+ for(i=0; i<pList->nExpr; i++){
|
|
+ Expr *pExpr = pList->a[i].pExpr;
|
|
+ if( pExpr==0 ) continue;
|
|
+#if SQLITE_MAX_EXPR_DEPTH>0
|
|
+ w.pParse->nHeight += pExpr->nHeight;
|
|
+ if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
|
|
+ return WRC_Abort;
|
|
+ }
|
|
+#endif
|
|
+ sqlite3WalkExpr(&w, pExpr);
|
|
+#if SQLITE_MAX_EXPR_DEPTH>0
|
|
+ w.pParse->nHeight -= pExpr->nHeight;
|
|
+#endif
|
|
+ assert( EP_Agg==NC_HasAgg );
|
|
+ assert( EP_Win==NC_HasWin );
|
|
+ testcase( pNC->ncFlags & NC_HasAgg );
|
|
+ testcase( pNC->ncFlags & NC_HasWin );
|
|
+ if( pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin) ){
|
|
+ ExprSetProperty(pExpr, pNC->ncFlags & (NC_HasAgg|NC_HasWin) );
|
|
+ savedHasAgg |= pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
|
+ pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg|NC_HasWin);
|
|
}
|
|
+ if( pNC->nErr>0 || w.pParse->nErr>0 ) return WRC_Abort;
|
|
}
|
|
+ pNC->ncFlags |= savedHasAgg;
|
|
return WRC_Continue;
|
|
}
|
|
|
|
@@ -97170,10 +99431,13 @@
|
|
** Resolve names in expressions that can only reference a single table
|
|
** or which cannot reference any tables at all. Examples:
|
|
**
|
|
-** (1) CHECK constraints
|
|
-** (2) WHERE clauses on partial indices
|
|
-** (3) Expressions in indexes on expressions
|
|
-** (4) Expression arguments to VACUUM INTO.
|
|
+** "type" flag
|
|
+** ------------
|
|
+** (1) CHECK constraints NC_IsCheck
|
|
+** (2) WHERE clauses on partial indices NC_PartIdx
|
|
+** (3) Expressions in indexes on expressions NC_IdxExpr
|
|
+** (4) Expression arguments to VACUUM INTO. 0
|
|
+** (5) GENERATED ALWAYS as expressions NC_GenCol
|
|
**
|
|
** In all cases except (4), the Expr.iTable value for Expr.op==TK_COLUMN
|
|
** nodes of the expression is set to -1 and the Expr.iColumn value is
|
|
@@ -97182,18 +99446,19 @@
|
|
** Any errors cause an error message to be set in pParse.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ResolveSelfReference(
|
|
- Parse *pParse, /* Parsing context */
|
|
- Table *pTab, /* The table being referenced, or NULL */
|
|
- int type, /* NC_IsCheck or NC_PartIdx or NC_IdxExpr, or 0 */
|
|
- Expr *pExpr, /* Expression to resolve. May be NULL. */
|
|
- ExprList *pList /* Expression list to resolve. May be NULL. */
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ Table *pTab, /* The table being referenced, or NULL */
|
|
+ int type, /* NC_IsCheck, NC_PartIdx, NC_IdxExpr, NC_GenCol, or 0 */
|
|
+ Expr *pExpr, /* Expression to resolve. May be NULL. */
|
|
+ ExprList *pList /* Expression list to resolve. May be NULL. */
|
|
){
|
|
SrcList sSrc; /* Fake SrcList for pParse->pNewTable */
|
|
NameContext sNC; /* Name context for pParse->pNewTable */
|
|
int rc;
|
|
|
|
assert( type==0 || pTab!=0 );
|
|
- assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr || pTab==0 );
|
|
+ assert( type==NC_IsCheck || type==NC_PartIdx || type==NC_IdxExpr
|
|
+ || type==NC_GenCol || pTab==0 );
|
|
memset(&sNC, 0, sizeof(sNC));
|
|
memset(&sSrc, 0, sizeof(sSrc));
|
|
if( pTab ){
|
|
@@ -97201,6 +99466,11 @@
|
|
sSrc.a[0].zName = pTab->zName;
|
|
sSrc.a[0].pTab = pTab;
|
|
sSrc.a[0].iCursor = -1;
|
|
+ if( pTab->pSchema!=pParse->db->aDb[1].pSchema ){
|
|
+ /* Cause EP_FromDDL to be set on TK_FUNCTION nodes of non-TEMP
|
|
+ ** schema elements */
|
|
+ type |= NC_FromDDL;
|
|
+ }
|
|
}
|
|
sNC.pParse = pParse;
|
|
sNC.pSrcList = &sSrc;
|
|
@@ -97256,11 +99526,10 @@
|
|
** SELECT a AS b FROM t1 WHERE b;
|
|
** SELECT * FROM t1 WHERE (select a from t1);
|
|
*/
|
|
-SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
|
|
+SQLITE_PRIVATE char sqlite3ExprAffinity(const Expr *pExpr){
|
|
int op;
|
|
- if( pExpr->flags & EP_Generic ) return 0;
|
|
while( ExprHasProperty(pExpr, EP_Skip) ){
|
|
- assert( pExpr->op==TK_COLLATE );
|
|
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
|
|
pExpr = pExpr->pLeft;
|
|
assert( pExpr!=0 );
|
|
}
|
|
@@ -97285,7 +99554,10 @@
|
|
pExpr->pLeft->x.pSelect->pEList->a[pExpr->iColumn].pExpr
|
|
);
|
|
}
|
|
- return pExpr->affinity;
|
|
+ if( op==TK_VECTOR ){
|
|
+ return sqlite3ExprAffinity(pExpr->x.pList->a[0].pExpr);
|
|
+ }
|
|
+ return pExpr->affExpr;
|
|
}
|
|
|
|
/*
|
|
@@ -97320,10 +99592,22 @@
|
|
}
|
|
|
|
/*
|
|
-** Skip over any TK_COLLATE operators and any unlikely()
|
|
-** or likelihood() function at the root of an expression.
|
|
+** Skip over any TK_COLLATE operators.
|
|
*/
|
|
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr *pExpr){
|
|
+ while( pExpr && ExprHasProperty(pExpr, EP_Skip) ){
|
|
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
|
|
+ pExpr = pExpr->pLeft;
|
|
+ }
|
|
+ return pExpr;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Skip over any TK_COLLATE operators and/or any unlikely()
|
|
+** or likelihood() or likely() functions at the root of an
|
|
+** expression.
|
|
+*/
|
|
+SQLITE_PRIVATE Expr *sqlite3ExprSkipCollateAndLikely(Expr *pExpr){
|
|
while( pExpr && ExprHasProperty(pExpr, EP_Skip|EP_Unlikely) ){
|
|
if( ExprHasProperty(pExpr, EP_Unlikely) ){
|
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
|
@@ -97331,7 +99615,7 @@
|
|
assert( pExpr->op==TK_FUNCTION );
|
|
pExpr = pExpr->x.pList->a[0].pExpr;
|
|
}else{
|
|
- assert( pExpr->op==TK_COLLATE );
|
|
+ assert( pExpr->op==TK_COLLATE || pExpr->op==TK_IF_NULL_ROW );
|
|
pExpr = pExpr->pLeft;
|
|
}
|
|
}
|
|
@@ -97352,13 +99636,12 @@
|
|
** COLLATE operators take first precedence. Left operands take
|
|
** precedence over right operands.
|
|
*/
|
|
-SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
|
|
+SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
|
|
sqlite3 *db = pParse->db;
|
|
CollSeq *pColl = 0;
|
|
- Expr *p = pExpr;
|
|
+ const Expr *p = pExpr;
|
|
while( p ){
|
|
int op = p->op;
|
|
- if( p->flags & EP_Generic ) break;
|
|
if( op==TK_REGISTER ) op = p->op2;
|
|
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
|
|
&& p->y.pTab!=0
|
|
@@ -97376,6 +99659,10 @@
|
|
p = p->pLeft;
|
|
continue;
|
|
}
|
|
+ if( op==TK_VECTOR ){
|
|
+ p = p->x.pList->a[0].pExpr;
|
|
+ continue;
|
|
+ }
|
|
if( op==TK_COLLATE ){
|
|
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
|
|
break;
|
|
@@ -97387,12 +99674,12 @@
|
|
Expr *pNext = p->pRight;
|
|
/* The Expr.x union is never used at the same time as Expr.pRight */
|
|
assert( p->x.pList==0 || p->pRight==0 );
|
|
- /* p->flags holds EP_Collate and p->pLeft->flags does not. And
|
|
- ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
|
|
- ** least one EP_Collate. Thus the following two ALWAYS. */
|
|
- if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
|
|
+ if( p->x.pList!=0
|
|
+ && !db->mallocFailed
|
|
+ && ALWAYS(!ExprHasProperty(p, EP_xIsSelect))
|
|
+ ){
|
|
int i;
|
|
- for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
|
|
+ for(i=0; i<p->x.pList->nExpr; i++){
|
|
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
|
|
pNext = p->x.pList->a[i].pExpr;
|
|
break;
|
|
@@ -97421,7 +99708,7 @@
|
|
** The sqlite3ExprCollSeq() routine works the same except that it
|
|
** returns NULL if there is no defined collation.
|
|
*/
|
|
-SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, Expr *pExpr){
|
|
+SQLITE_PRIVATE CollSeq *sqlite3ExprNNCollSeq(Parse *pParse, const Expr *pExpr){
|
|
CollSeq *p = sqlite3ExprCollSeq(pParse, pExpr);
|
|
if( p==0 ) p = pParse->db->pDfltColl;
|
|
assert( p!=0 );
|
|
@@ -97431,7 +99718,7 @@
|
|
/*
|
|
** Return TRUE if the two expressions have equivalent collating sequences.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, Expr *pE1, Expr *pE2){
|
|
+SQLITE_PRIVATE int sqlite3ExprCollSeqMatch(Parse *pParse, const Expr *pE1, const Expr *pE2){
|
|
CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pE1);
|
|
CollSeq *pColl2 = sqlite3ExprNNCollSeq(pParse, pE2);
|
|
return sqlite3StrICmp(pColl1->zName, pColl2->zName)==0;
|
|
@@ -97442,9 +99729,9 @@
|
|
** type affinity of the other operand. This routine returns the
|
|
** type affinity that should be used for the comparison operator.
|
|
*/
|
|
-SQLITE_PRIVATE char sqlite3CompareAffinity(Expr *pExpr, char aff2){
|
|
+SQLITE_PRIVATE char sqlite3CompareAffinity(const Expr *pExpr, char aff2){
|
|
char aff1 = sqlite3ExprAffinity(pExpr);
|
|
- if( aff1 && aff2 ){
|
|
+ if( aff1>SQLITE_AFF_NONE && aff2>SQLITE_AFF_NONE ){
|
|
/* Both sides of the comparison are columns. If one has numeric
|
|
** affinity, use that. Otherwise use no affinity.
|
|
*/
|
|
@@ -97453,15 +99740,10 @@
|
|
}else{
|
|
return SQLITE_AFF_BLOB;
|
|
}
|
|
- }else if( !aff1 && !aff2 ){
|
|
- /* Neither side of the comparison is a column. Compare the
|
|
- ** results directly.
|
|
- */
|
|
- return SQLITE_AFF_BLOB;
|
|
}else{
|
|
/* One side is a column, the other is not. Use the columns affinity. */
|
|
- assert( aff1==0 || aff2==0 );
|
|
- return (aff1 + aff2);
|
|
+ assert( aff1<=SQLITE_AFF_NONE || aff2<=SQLITE_AFF_NONE );
|
|
+ return (aff1<=SQLITE_AFF_NONE ? aff2 : aff1) | SQLITE_AFF_NONE;
|
|
}
|
|
}
|
|
|
|
@@ -97469,7 +99751,7 @@
|
|
** pExpr is a comparison operator. Return the type affinity that should
|
|
** be applied to both operands prior to doing the comparison.
|
|
*/
|
|
-static char comparisonAffinity(Expr *pExpr){
|
|
+static char comparisonAffinity(const Expr *pExpr){
|
|
char aff;
|
|
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
|
|
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
|
|
@@ -97492,23 +99774,26 @@
|
|
** if the index with affinity idx_affinity may be used to implement
|
|
** the comparison in pExpr.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity){
|
|
+SQLITE_PRIVATE int sqlite3IndexAffinityOk(const Expr *pExpr, char idx_affinity){
|
|
char aff = comparisonAffinity(pExpr);
|
|
- switch( aff ){
|
|
- case SQLITE_AFF_BLOB:
|
|
- return 1;
|
|
- case SQLITE_AFF_TEXT:
|
|
- return idx_affinity==SQLITE_AFF_TEXT;
|
|
- default:
|
|
- return sqlite3IsNumericAffinity(idx_affinity);
|
|
+ if( aff<SQLITE_AFF_TEXT ){
|
|
+ return 1;
|
|
}
|
|
+ if( aff==SQLITE_AFF_TEXT ){
|
|
+ return idx_affinity==SQLITE_AFF_TEXT;
|
|
+ }
|
|
+ return sqlite3IsNumericAffinity(idx_affinity);
|
|
}
|
|
|
|
/*
|
|
** Return the P5 value that should be used for a binary comparison
|
|
** opcode (OP_Eq, OP_Ge etc.) used to compare pExpr1 and pExpr2.
|
|
*/
|
|
-static u8 binaryCompareP5(Expr *pExpr1, Expr *pExpr2, int jumpIfNull){
|
|
+static u8 binaryCompareP5(
|
|
+ const Expr *pExpr1, /* Left operand */
|
|
+ const Expr *pExpr2, /* Right operand */
|
|
+ int jumpIfNull /* Extra flags added to P5 */
|
|
+){
|
|
u8 aff = (char)sqlite3ExprAffinity(pExpr2);
|
|
aff = (u8)sqlite3CompareAffinity(pExpr1, aff) | (u8)jumpIfNull;
|
|
return aff;
|
|
@@ -97528,8 +99813,8 @@
|
|
*/
|
|
SQLITE_PRIVATE CollSeq *sqlite3BinaryCompareCollSeq(
|
|
Parse *pParse,
|
|
- Expr *pLeft,
|
|
- Expr *pRight
|
|
+ const Expr *pLeft,
|
|
+ const Expr *pRight
|
|
){
|
|
CollSeq *pColl;
|
|
assert( pLeft );
|
|
@@ -97546,6 +99831,22 @@
|
|
return pColl;
|
|
}
|
|
|
|
+/* Expresssion p is a comparison operator. Return a collation sequence
|
|
+** appropriate for the comparison operator.
|
|
+**
|
|
+** This is normally just a wrapper around sqlite3BinaryCompareCollSeq().
|
|
+** However, if the OP_Commuted flag is set, then the order of the operands
|
|
+** is reversed in the sqlite3BinaryCompareCollSeq() call so that the
|
|
+** correct collating sequence is found.
|
|
+*/
|
|
+SQLITE_PRIVATE CollSeq *sqlite3ExprCompareCollSeq(Parse *pParse, const Expr *p){
|
|
+ if( ExprHasProperty(p, EP_Commuted) ){
|
|
+ return sqlite3BinaryCompareCollSeq(pParse, p->pRight, p->pLeft);
|
|
+ }else{
|
|
+ return sqlite3BinaryCompareCollSeq(pParse, p->pLeft, p->pRight);
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Generate code for a comparison operator.
|
|
*/
|
|
@@ -97556,13 +99857,19 @@
|
|
int opcode, /* The comparison opcode */
|
|
int in1, int in2, /* Register holding operands */
|
|
int dest, /* Jump here if true. */
|
|
- int jumpIfNull /* If true, jump if either operand is NULL */
|
|
+ int jumpIfNull, /* If true, jump if either operand is NULL */
|
|
+ int isCommuted /* The comparison has been commuted */
|
|
){
|
|
int p5;
|
|
int addr;
|
|
CollSeq *p4;
|
|
|
|
- p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
|
|
+ if( pParse->nErr ) return 0;
|
|
+ if( isCommuted ){
|
|
+ p4 = sqlite3BinaryCompareCollSeq(pParse, pRight, pLeft);
|
|
+ }else{
|
|
+ p4 = sqlite3BinaryCompareCollSeq(pParse, pLeft, pRight);
|
|
+ }
|
|
p5 = binaryCompareP5(pLeft, pRight, jumpIfNull);
|
|
addr = sqlite3VdbeAddOp4(pParse->pVdbe, opcode, in2, dest, in1,
|
|
(void*)p4, P4_COLLSEQ);
|
|
@@ -97773,7 +100080,10 @@
|
|
int regRight = 0;
|
|
u8 opx = op;
|
|
int addrDone = sqlite3VdbeMakeLabel(pParse);
|
|
+ int isCommuted = ExprHasProperty(pExpr,EP_Commuted);
|
|
|
|
+ assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
|
+ if( pParse->nErr ) return;
|
|
if( nLeft!=sqlite3ExprVectorSize(pRight) ){
|
|
sqlite3ErrorMsg(pParse, "row value misused");
|
|
return;
|
|
@@ -97802,7 +100112,7 @@
|
|
assert( i>=0 && i<nLeft );
|
|
r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1);
|
|
r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2);
|
|
- codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5);
|
|
+ codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5, isCommuted);
|
|
testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
|
testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
|
testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
|
@@ -98112,10 +100422,12 @@
|
|
return pRight;
|
|
}else if( pRight==0 ){
|
|
return pLeft;
|
|
- }else if( ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight) ){
|
|
- sqlite3ExprUnmapAndDelete(pParse, pLeft);
|
|
- sqlite3ExprUnmapAndDelete(pParse, pRight);
|
|
- return sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0);
|
|
+ }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight))
|
|
+ && !IN_RENAME_OBJECT
|
|
+ ){
|
|
+ sqlite3ExprDelete(db, pLeft);
|
|
+ sqlite3ExprDelete(db, pRight);
|
|
+ return sqlite3Expr(db, TK_INTEGER, "0");
|
|
}else{
|
|
return sqlite3PExpr(pParse, TK_AND, pLeft, pRight);
|
|
}
|
|
@@ -98150,6 +100462,40 @@
|
|
return pNew;
|
|
}
|
|
|
|
+/*
|
|
+** Check to see if a function is usable according to current access
|
|
+** rules:
|
|
+**
|
|
+** SQLITE_FUNC_DIRECT - Only usable from top-level SQL
|
|
+**
|
|
+** SQLITE_FUNC_UNSAFE - Usable if TRUSTED_SCHEMA or from
|
|
+** top-level SQL
|
|
+**
|
|
+** If the function is not usable, create an error.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3ExprFunctionUsable(
|
|
+ Parse *pParse, /* Parsing and code generating context */
|
|
+ Expr *pExpr, /* The function invocation */
|
|
+ FuncDef *pDef /* The function being invoked */
|
|
+){
|
|
+ assert( !IN_RENAME_OBJECT );
|
|
+ assert( (pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE))!=0 );
|
|
+ if( ExprHasProperty(pExpr, EP_FromDDL) ){
|
|
+ if( (pDef->funcFlags & SQLITE_FUNC_DIRECT)!=0
|
|
+ || (pParse->db->flags & SQLITE_TrustedSchema)==0
|
|
+ ){
|
|
+ /* Functions prohibited in triggers and views if:
|
|
+ ** (1) tagged with SQLITE_DIRECTONLY
|
|
+ ** (2) not tagged with SQLITE_INNOCUOUS (which means it
|
|
+ ** is tagged with SQLITE_FUNC_UNSAFE) and
|
|
+ ** SQLITE_DBCONFIG_TRUSTED_SCHEMA is off (meaning
|
|
+ ** that the schema is possibly tainted).
|
|
+ */
|
|
+ sqlite3ErrorMsg(pParse, "unsafe use of %s()", pDef->zName);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Assign a variable number to an expression that encodes a wildcard
|
|
** in the original SQL statement.
|
|
@@ -98254,15 +100600,18 @@
|
|
assert( p->x.pList==0 || p->pRight==0 );
|
|
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
|
|
if( p->pRight ){
|
|
+ assert( !ExprHasProperty(p, EP_WinFunc) );
|
|
sqlite3ExprDeleteNN(db, p->pRight);
|
|
}else if( ExprHasProperty(p, EP_xIsSelect) ){
|
|
+ assert( !ExprHasProperty(p, EP_WinFunc) );
|
|
sqlite3SelectDelete(db, p->x.pSelect);
|
|
}else{
|
|
sqlite3ExprListDelete(db, p->x.pList);
|
|
- }
|
|
- if( ExprHasProperty(p, EP_WinFunc) ){
|
|
- assert( p->op==TK_FUNCTION );
|
|
- sqlite3WindowDelete(db, p->y.pWin);
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ if( ExprHasProperty(p, EP_WinFunc) ){
|
|
+ sqlite3WindowDelete(db, p->y.pWin);
|
|
+ }
|
|
+#endif
|
|
}
|
|
}
|
|
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
|
|
@@ -98297,16 +100646,6 @@
|
|
return EXPR_FULLSIZE;
|
|
}
|
|
|
|
-/*
|
|
-** Copy the complete content of an Expr node, taking care not to read
|
|
-** past the end of the structure for a reduced-size version of the source
|
|
-** Expr.
|
|
-*/
|
|
-static void exprNodeCopy(Expr *pDest, Expr *pSrc){
|
|
- memset(pDest, 0, sizeof(Expr));
|
|
- memcpy(pDest, pSrc, exprStructSize(pSrc));
|
|
-}
|
|
-
|
|
/*
|
|
** The dupedExpr*Size() routines each return the number of bytes required
|
|
** to store a copy of an expression or expression tree. They differ in
|
|
@@ -98356,7 +100695,7 @@
|
|
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
|
assert( !ExprHasProperty(p, EP_FromJoin) );
|
|
assert( !ExprHasProperty(p, EP_MemToken) );
|
|
- assert( !ExprHasProperty(p, EP_NoReduce) );
|
|
+ assert( !ExprHasVVAProperty(p, EP_NoReduce) );
|
|
if( p->pLeft || p->x.pList ){
|
|
nSize = EXPR_REDUCEDSIZE | EP_Reduced;
|
|
}else{
|
|
@@ -98461,6 +100800,10 @@
|
|
pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static|EP_MemToken);
|
|
pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly);
|
|
pNew->flags |= staticFlag;
|
|
+ ExprClearVVAProperties(pNew);
|
|
+ if( dupFlags ){
|
|
+ ExprSetVVAProperty(pNew, EP_Immutable);
|
|
+ }
|
|
|
|
/* Copy the p->u.zToken string, if any. */
|
|
if( nToken ){
|
|
@@ -98546,10 +100889,13 @@
|
|
** objects found there, assembling them onto the linked list at Select->pWin.
|
|
*/
|
|
static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
|
|
- if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
|
|
- assert( ExprHasProperty(pExpr, EP_WinFunc) );
|
|
- pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
|
|
- pWalker->u.pSelect->pWin = pExpr->y.pWin;
|
|
+ if( pExpr->op==TK_FUNCTION && ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ Select *pSelect = pWalker->u.pSelect;
|
|
+ Window *pWin = pExpr->y.pWin;
|
|
+ assert( pWin );
|
|
+ assert( IsWindowFunc(pExpr) );
|
|
+ assert( pWin->ppThis==0 );
|
|
+ sqlite3WindowLink(pSelect, pWin);
|
|
}
|
|
return WRC_Continue;
|
|
}
|
|
@@ -98621,11 +100967,11 @@
|
|
pNewExpr->pLeft = pPriorSelectCol;
|
|
}
|
|
}
|
|
- pItem->zName = sqlite3DbStrDup(db, pOldItem->zName);
|
|
- pItem->zSpan = sqlite3DbStrDup(db, pOldItem->zSpan);
|
|
- pItem->sortOrder = pOldItem->sortOrder;
|
|
+ pItem->zEName = sqlite3DbStrDup(db, pOldItem->zEName);
|
|
+ pItem->sortFlags = pOldItem->sortFlags;
|
|
+ pItem->eEName = pOldItem->eEName;
|
|
pItem->done = 0;
|
|
- pItem->bSpanIsTab = pOldItem->bSpanIsTab;
|
|
+ pItem->bNulls = pOldItem->bNulls;
|
|
pItem->bSorterRef = pOldItem->bSorterRef;
|
|
pItem->u = pOldItem->u;
|
|
}
|
|
@@ -98735,7 +101081,7 @@
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
pNew->pWin = 0;
|
|
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
|
|
- if( p->pWin ) gatherSelectWindows(pNew);
|
|
+ if( p->pWin && db->mallocFailed==0 ) gatherSelectWindows(pNew);
|
|
#endif
|
|
pNew->selId = p->selId;
|
|
*pp = pNew;
|
|
@@ -98792,9 +101138,9 @@
|
|
pList = pNew;
|
|
}
|
|
pItem = &pList->a[pList->nExpr++];
|
|
- assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
|
|
+ assert( offsetof(struct ExprList_item,zEName)==sizeof(pItem->pExpr) );
|
|
assert( offsetof(struct ExprList_item,pExpr)==0 );
|
|
- memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
|
|
+ memset(&pItem->zEName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zEName));
|
|
pItem->pExpr = pExpr;
|
|
return pList;
|
|
|
|
@@ -98844,10 +101190,14 @@
|
|
|
|
for(i=0; i<pColumns->nId; i++){
|
|
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
|
|
+ assert( pSubExpr!=0 || db->mallocFailed );
|
|
+ assert( pSubExpr==0 || pSubExpr->iTable==0 );
|
|
+ if( pSubExpr==0 ) continue;
|
|
+ pSubExpr->iTable = pColumns->nId;
|
|
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
|
|
if( pList ){
|
|
assert( pList->nExpr==iFirst+i+1 );
|
|
- pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
|
|
+ pList->a[pList->nExpr-1].zEName = pColumns->a[i].zName;
|
|
pColumns->a[i].zName = 0;
|
|
}
|
|
}
|
|
@@ -98876,19 +101226,38 @@
|
|
/*
|
|
** Set the sort order for the last element on the given ExprList.
|
|
*/
|
|
-SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder){
|
|
+SQLITE_PRIVATE void sqlite3ExprListSetSortOrder(ExprList *p, int iSortOrder, int eNulls){
|
|
+ struct ExprList_item *pItem;
|
|
if( p==0 ) return;
|
|
- assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC>=0 && SQLITE_SO_DESC>0 );
|
|
assert( p->nExpr>0 );
|
|
- if( iSortOrder<0 ){
|
|
- assert( p->a[p->nExpr-1].sortOrder==SQLITE_SO_ASC );
|
|
- return;
|
|
+
|
|
+ assert( SQLITE_SO_UNDEFINED<0 && SQLITE_SO_ASC==0 && SQLITE_SO_DESC>0 );
|
|
+ assert( iSortOrder==SQLITE_SO_UNDEFINED
|
|
+ || iSortOrder==SQLITE_SO_ASC
|
|
+ || iSortOrder==SQLITE_SO_DESC
|
|
+ );
|
|
+ assert( eNulls==SQLITE_SO_UNDEFINED
|
|
+ || eNulls==SQLITE_SO_ASC
|
|
+ || eNulls==SQLITE_SO_DESC
|
|
+ );
|
|
+
|
|
+ pItem = &p->a[p->nExpr-1];
|
|
+ assert( pItem->bNulls==0 );
|
|
+ if( iSortOrder==SQLITE_SO_UNDEFINED ){
|
|
+ iSortOrder = SQLITE_SO_ASC;
|
|
+ }
|
|
+ pItem->sortFlags = (u8)iSortOrder;
|
|
+
|
|
+ if( eNulls!=SQLITE_SO_UNDEFINED ){
|
|
+ pItem->bNulls = 1;
|
|
+ if( iSortOrder!=eNulls ){
|
|
+ pItem->sortFlags |= KEYINFO_ORDER_BIGNULL;
|
|
+ }
|
|
}
|
|
- p->a[p->nExpr-1].sortOrder = (u8)iSortOrder;
|
|
}
|
|
|
|
/*
|
|
-** Set the ExprList.a[].zName element of the most recently added item
|
|
+** Set the ExprList.a[].zEName element of the most recently added item
|
|
** on the expression list.
|
|
**
|
|
** pList might be NULL following an OOM error. But pName should never be
|
|
@@ -98902,15 +101271,22 @@
|
|
int dequote /* True to cause the name to be dequoted */
|
|
){
|
|
assert( pList!=0 || pParse->db->mallocFailed!=0 );
|
|
+ assert( pParse->eParseMode!=PARSE_MODE_UNMAP || dequote==0 );
|
|
if( pList ){
|
|
struct ExprList_item *pItem;
|
|
assert( pList->nExpr>0 );
|
|
pItem = &pList->a[pList->nExpr-1];
|
|
- assert( pItem->zName==0 );
|
|
- pItem->zName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
|
|
- if( dequote ) sqlite3Dequote(pItem->zName);
|
|
- if( IN_RENAME_OBJECT ){
|
|
- sqlite3RenameTokenMap(pParse, (void*)pItem->zName, pName);
|
|
+ assert( pItem->zEName==0 );
|
|
+ assert( pItem->eEName==ENAME_NAME );
|
|
+ pItem->zEName = sqlite3DbStrNDup(pParse->db, pName->z, pName->n);
|
|
+ if( dequote ){
|
|
+ /* If dequote==0, then pName->z does not point to part of a DDL
|
|
+ ** statement handled by the parser. And so no token need be added
|
|
+ ** to the token-map. */
|
|
+ sqlite3Dequote(pItem->zEName);
|
|
+ if( IN_RENAME_OBJECT ){
|
|
+ sqlite3RenameTokenMap(pParse, (void*)pItem->zEName, pName);
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -98934,8 +101310,10 @@
|
|
if( pList ){
|
|
struct ExprList_item *pItem = &pList->a[pList->nExpr-1];
|
|
assert( pList->nExpr>0 );
|
|
- sqlite3DbFree(db, pItem->zSpan);
|
|
- pItem->zSpan = sqlite3DbSpanDup(db, zStart, zEnd);
|
|
+ if( pItem->zEName==0 ){
|
|
+ pItem->zEName = sqlite3DbSpanDup(db, zStart, zEnd);
|
|
+ pItem->eEName = ENAME_SPAN;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -98965,8 +101343,7 @@
|
|
assert( pList->nExpr>0 );
|
|
do{
|
|
sqlite3ExprDelete(db, pItem->pExpr);
|
|
- sqlite3DbFree(db, pItem->zName);
|
|
- sqlite3DbFree(db, pItem->zSpan);
|
|
+ sqlite3DbFree(db, pItem->zEName);
|
|
pItem++;
|
|
}while( --i>0 );
|
|
sqlite3DbFreeNN(db, pList);
|
|
@@ -99004,19 +101381,34 @@
|
|
return WRC_Abort;
|
|
}
|
|
|
|
+/*
|
|
+** Check the input string to see if it is "true" or "false" (in any case).
|
|
+**
|
|
+** If the string is.... Return
|
|
+** "true" EP_IsTrue
|
|
+** "false" EP_IsFalse
|
|
+** anything else 0
|
|
+*/
|
|
+SQLITE_PRIVATE u32 sqlite3IsTrueOrFalse(const char *zIn){
|
|
+ if( sqlite3StrICmp(zIn, "true")==0 ) return EP_IsTrue;
|
|
+ if( sqlite3StrICmp(zIn, "false")==0 ) return EP_IsFalse;
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
** If the input expression is an ID with the name "true" or "false"
|
|
** then convert it into an TK_TRUEFALSE term. Return non-zero if
|
|
** the conversion happened, and zero if the expression is unaltered.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ExprIdToTrueFalse(Expr *pExpr){
|
|
+ u32 v;
|
|
assert( pExpr->op==TK_ID || pExpr->op==TK_STRING );
|
|
if( !ExprHasProperty(pExpr, EP_Quoted)
|
|
- && (sqlite3StrICmp(pExpr->u.zToken, "true")==0
|
|
- || sqlite3StrICmp(pExpr->u.zToken, "false")==0)
|
|
+ && (v = sqlite3IsTrueOrFalse(pExpr->u.zToken))!=0
|
|
){
|
|
pExpr->op = TK_TRUEFALSE;
|
|
- ExprSetProperty(pExpr, pExpr->u.zToken[4]==0 ? EP_IsTrue : EP_IsFalse);
|
|
+ ExprSetProperty(pExpr, v);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
@@ -99078,10 +101470,11 @@
|
|
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
|
|
** is found to not be a constant.
|
|
**
|
|
-** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
|
|
-** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
|
|
-** an existing schema and 4 when processing a new statement. A bound
|
|
-** parameter raises an error for new statements, but is silently converted
|
|
+** The sqlite3ExprIsConstantOrFunction() is used for evaluating DEFAULT
|
|
+** expressions in a CREATE TABLE statement. The Walker.eCode value is 5
|
|
+** when parsing an existing schema out of the sqlite_master table and 4
|
|
+** when processing a new CREATE TABLE statement. A bound parameter raises
|
|
+** an error for new statements, but is silently converted
|
|
** to NULL for existing schemas. This allows sqlite_master tables that
|
|
** contain a bound parameter because they were generated by older versions
|
|
** of SQLite to be parsed by newer versions of SQLite without raising a
|
|
@@ -99102,7 +101495,10 @@
|
|
** and either pWalker->eCode==4 or 5 or the function has the
|
|
** SQLITE_FUNC_CONST flag. */
|
|
case TK_FUNCTION:
|
|
- if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
|
|
+ if( (pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc))
|
|
+ && !ExprHasProperty(pExpr, EP_WinFunc)
|
|
+ ){
|
|
+ if( pWalker->eCode==5 ) ExprSetProperty(pExpr, EP_FromDDL);
|
|
return WRC_Continue;
|
|
}else{
|
|
pWalker->eCode = 0;
|
|
@@ -99190,7 +101586,7 @@
|
|
**
|
|
** When this routine returns true, it indicates that the expression
|
|
** can be added to the pParse->pConstExpr list and evaluated once when
|
|
-** the prepared statement starts up. See sqlite3ExprCodeAtInit().
|
|
+** the prepared statement starts up. See sqlite3ExprCodeRunJustOnce().
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr *p){
|
|
return exprIsConst(p, 2, 0);
|
|
@@ -99266,9 +101662,21 @@
|
|
}
|
|
|
|
/*
|
|
-** Walk an expression tree. Return non-zero if the expression is constant
|
|
-** or a function call with constant arguments. Return and 0 if there
|
|
-** are any variables.
|
|
+** Walk an expression tree for the DEFAULT field of a column definition
|
|
+** in a CREATE TABLE statement. Return non-zero if the expression is
|
|
+** acceptable for use as a DEFAULT. That is to say, return non-zero if
|
|
+** the expression is constant or a function call with constant arguments.
|
|
+** Return and 0 if there are any variables.
|
|
+**
|
|
+** isInit is true when parsing from sqlite_master. isInit is false when
|
|
+** processing a new CREATE TABLE statement. When isInit is true, parameters
|
|
+** (such as ? or $abc) in the expression are converted into NULL. When
|
|
+** isInit is false, parameters raise an error. Parameters should not be
|
|
+** allowed in a CREATE TABLE statement, but some legacy versions of SQLite
|
|
+** allowed it, so we need to support it when reading sqlite_master for
|
|
+** backwards compatibility.
|
|
+**
|
|
+** If isInit is true, set EP_FromDDL on every TK_FUNCTION node.
|
|
**
|
|
** For the purposes of this function, a double-quoted string (ex: "abc")
|
|
** is considered a variable but a single-quoted string (ex: 'abc') is
|
|
@@ -99365,7 +101773,9 @@
|
|
case TK_COLUMN:
|
|
return ExprHasProperty(p, EP_CanBeNull) ||
|
|
p->y.pTab==0 || /* Reference to column of index on expression */
|
|
- (p->iColumn>=0 && p->y.pTab->aCol[p->iColumn].notNull==0);
|
|
+ (p->iColumn>=0
|
|
+ && ALWAYS(p->y.pTab->aCol!=0) /* Defense against OOM problems */
|
|
+ && p->y.pTab->aCol[p->iColumn].notNull==0);
|
|
default:
|
|
return 1;
|
|
}
|
|
@@ -99383,27 +101793,30 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr *p, char aff){
|
|
u8 op;
|
|
+ int unaryMinus = 0;
|
|
if( aff==SQLITE_AFF_BLOB ) return 1;
|
|
- while( p->op==TK_UPLUS || p->op==TK_UMINUS ){ p = p->pLeft; }
|
|
+ while( p->op==TK_UPLUS || p->op==TK_UMINUS ){
|
|
+ if( p->op==TK_UMINUS ) unaryMinus = 1;
|
|
+ p = p->pLeft;
|
|
+ }
|
|
op = p->op;
|
|
if( op==TK_REGISTER ) op = p->op2;
|
|
switch( op ){
|
|
case TK_INTEGER: {
|
|
- return aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC;
|
|
+ return aff>=SQLITE_AFF_NUMERIC;
|
|
}
|
|
case TK_FLOAT: {
|
|
- return aff==SQLITE_AFF_REAL || aff==SQLITE_AFF_NUMERIC;
|
|
+ return aff>=SQLITE_AFF_NUMERIC;
|
|
}
|
|
case TK_STRING: {
|
|
- return aff==SQLITE_AFF_TEXT;
|
|
+ return !unaryMinus && aff==SQLITE_AFF_TEXT;
|
|
}
|
|
case TK_BLOB: {
|
|
- return 1;
|
|
+ return !unaryMinus;
|
|
}
|
|
case TK_COLUMN: {
|
|
assert( p->iTable>=0 ); /* p cannot be part of a CHECK constraint */
|
|
- return p->iColumn<0
|
|
- && (aff==SQLITE_AFF_INTEGER || aff==SQLITE_AFF_NUMERIC);
|
|
+ return aff>=SQLITE_AFF_NUMERIC && p->iColumn<0;
|
|
}
|
|
default: {
|
|
return 0;
|
|
@@ -99586,7 +101999,7 @@
|
|
#ifndef SQLITE_OMIT_SUBQUERY
|
|
SQLITE_PRIVATE int sqlite3FindInIndex(
|
|
Parse *pParse, /* Parsing context */
|
|
- Expr *pX, /* The right-hand side (RHS) of the IN operator */
|
|
+ Expr *pX, /* The IN expression */
|
|
u32 inFlags, /* IN_INDEX_LOOP, _MEMBERSHIP, and/or _NOOP_OK */
|
|
int *prRhsHasNull, /* Register holding NULL status. See notes */
|
|
int *aiMap, /* Mapping from Index fields to RHS fields */
|
|
@@ -99839,8 +102252,10 @@
|
|
** "sub-select returns N columns - expected M"
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3SubselectError(Parse *pParse, int nActual, int nExpect){
|
|
- const char *zFmt = "sub-select returns %d columns - expected %d";
|
|
- sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
|
|
+ if( pParse->nErr==0 ){
|
|
+ const char *zFmt = "sub-select returns %d columns - expected %d";
|
|
+ sqlite3ErrorMsg(pParse, zFmt, nActual, nExpect);
|
|
+ }
|
|
}
|
|
#endif
|
|
|
|
@@ -99934,6 +102349,7 @@
|
|
|
|
/* Begin coding the subroutine */
|
|
ExprSetProperty(pExpr, EP_Subrtn);
|
|
+ assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) );
|
|
pExpr->y.sub.regReturn = ++pParse->nMem;
|
|
pExpr->y.sub.iAddr =
|
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, pExpr->y.sub.regReturn) + 1;
|
|
@@ -100011,10 +102427,12 @@
|
|
int i;
|
|
ExprList *pList = pExpr->x.pList;
|
|
struct ExprList_item *pItem;
|
|
- int r1, r2, r3;
|
|
+ int r1, r2;
|
|
affinity = sqlite3ExprAffinity(pLeft);
|
|
- if( !affinity ){
|
|
+ if( affinity<=SQLITE_AFF_NONE ){
|
|
affinity = SQLITE_AFF_BLOB;
|
|
+ }else if( affinity==SQLITE_AFF_REAL ){
|
|
+ affinity = SQLITE_AFF_NUMERIC;
|
|
}
|
|
if( pKeyInfo ){
|
|
assert( sqlite3KeyInfoIsWriteable(pKeyInfo) );
|
|
@@ -100039,9 +102457,9 @@
|
|
}
|
|
|
|
/* Evaluate the expression and insert it into the temp table */
|
|
- r3 = sqlite3ExprCodeTarget(pParse, pE2, r1);
|
|
- sqlite3VdbeAddOp4(v, OP_MakeRecord, r3, 1, r2, &affinity, 1);
|
|
- sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r3, 1);
|
|
+ sqlite3ExprCode(pParse, pE2, r1);
|
|
+ sqlite3VdbeAddOp4(v, OP_MakeRecord, r1, 1, r2, &affinity, 1);
|
|
+ sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iTab, r2, r1, 1);
|
|
}
|
|
sqlite3ReleaseTempReg(pParse, r1);
|
|
sqlite3ReleaseTempReg(pParse, r2);
|
|
@@ -100054,6 +102472,7 @@
|
|
/* Subroutine return */
|
|
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
|
|
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
|
|
+ sqlite3ClearTempRegCache(pParse);
|
|
}
|
|
}
|
|
#endif /* SQLITE_OMIT_SUBQUERY */
|
|
@@ -100067,7 +102486,7 @@
|
|
**
|
|
** The pExpr parameter is the SELECT or EXISTS operator to be coded.
|
|
**
|
|
-** The register that holds the result. For a multi-column SELECT,
|
|
+** Return the register that holds the result. For a multi-column SELECT,
|
|
** the result is stored in a contiguous array of registers and the
|
|
** return value is the register of the left-most result column.
|
|
** Return 0 if an error occurs.
|
|
@@ -100145,11 +102564,21 @@
|
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iSDParm);
|
|
VdbeComment((v, "Init EXISTS result"));
|
|
}
|
|
- pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[1], 0);
|
|
if( pSel->pLimit ){
|
|
- sqlite3ExprDelete(pParse->db, pSel->pLimit->pLeft);
|
|
+ /* The subquery already has a limit. If the pre-existing limit is X
|
|
+ ** then make the new limit X<>0 so that the new limit is either 1 or 0 */
|
|
+ sqlite3 *db = pParse->db;
|
|
+ pLimit = sqlite3Expr(db, TK_INTEGER, "0");
|
|
+ if( pLimit ){
|
|
+ pLimit->affExpr = SQLITE_AFF_NUMERIC;
|
|
+ pLimit = sqlite3PExpr(pParse, TK_NE,
|
|
+ sqlite3ExprDup(db, pSel->pLimit->pLeft, 0), pLimit);
|
|
+ }
|
|
+ sqlite3ExprDelete(db, pSel->pLimit->pLeft);
|
|
pSel->pLimit->pLeft = pLimit;
|
|
}else{
|
|
+ /* If there is no pre-existing limit add a limit of 1 */
|
|
+ pLimit = sqlite3Expr(pParse->db, TK_INTEGER, "1");
|
|
pSel->pLimit = sqlite3PExpr(pParse, TK_LIMIT, pLimit, 0);
|
|
}
|
|
pSel->iLimit = 0;
|
|
@@ -100164,6 +102593,7 @@
|
|
/* Subroutine return */
|
|
sqlite3VdbeAddOp1(v, OP_Return, pExpr->y.sub.regReturn);
|
|
sqlite3VdbeChangeP1(v, pExpr->y.sub.iAddr-1, sqlite3VdbeCurrentAddr(v)-1);
|
|
+ sqlite3ClearTempRegCache(pParse);
|
|
}
|
|
|
|
return rReg;
|
|
@@ -100241,7 +102671,9 @@
|
|
int destNotNull; /* Jump here if a comparison is not true in step 6 */
|
|
int addrTop; /* Top of the step-6 loop */
|
|
int iTab = 0; /* Index to use */
|
|
+ u8 okConstFactor = pParse->okConstFactor;
|
|
|
|
+ assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
|
pLeft = pExpr->pLeft;
|
|
if( sqlite3ExprCheckIN(pParse, pExpr) ) return;
|
|
zAff = exprINAffinity(pParse, pExpr);
|
|
@@ -100284,8 +102716,14 @@
|
|
** so that the fields are in the same order as an existing index. The
|
|
** aiMap[] array contains a mapping from the original LHS field order to
|
|
** the field order that matches the RHS index.
|
|
- */
|
|
+ **
|
|
+ ** Avoid factoring the LHS of the IN(...) expression out of the loop,
|
|
+ ** even if it is constant, as OP_Affinity may be used on the register
|
|
+ ** by code generated below. */
|
|
+ assert( pParse->okConstFactor==okConstFactor );
|
|
+ pParse->okConstFactor = 0;
|
|
rLhsOrig = exprCodeVector(pParse, pLeft, &iDummy);
|
|
+ pParse->okConstFactor = okConstFactor;
|
|
for(i=0; i<nVector && aiMap[i]==i; i++){} /* Are LHS fields reordered? */
|
|
if( i==nVector ){
|
|
/* LHS fields are not reordered */
|
|
@@ -100321,19 +102759,25 @@
|
|
if( regCkNull && sqlite3ExprCanBeNull(pList->a[ii].pExpr) ){
|
|
sqlite3VdbeAddOp3(v, OP_BitAnd, regCkNull, r2, regCkNull);
|
|
}
|
|
+ sqlite3ReleaseTempReg(pParse, regToFree);
|
|
if( ii<pList->nExpr-1 || destIfNull!=destIfFalse ){
|
|
- sqlite3VdbeAddOp4(v, OP_Eq, rLhs, labelOk, r2,
|
|
+ int op = rLhs!=r2 ? OP_Eq : OP_NotNull;
|
|
+ sqlite3VdbeAddOp4(v, op, rLhs, labelOk, r2,
|
|
(void*)pColl, P4_COLLSEQ);
|
|
- VdbeCoverageIf(v, ii<pList->nExpr-1);
|
|
- VdbeCoverageIf(v, ii==pList->nExpr-1);
|
|
+ VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_Eq);
|
|
+ VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_Eq);
|
|
+ VdbeCoverageIf(v, ii<pList->nExpr-1 && op==OP_NotNull);
|
|
+ VdbeCoverageIf(v, ii==pList->nExpr-1 && op==OP_NotNull);
|
|
sqlite3VdbeChangeP5(v, zAff[0]);
|
|
}else{
|
|
+ int op = rLhs!=r2 ? OP_Ne : OP_IsNull;
|
|
assert( destIfNull==destIfFalse );
|
|
- sqlite3VdbeAddOp4(v, OP_Ne, rLhs, destIfFalse, r2,
|
|
- (void*)pColl, P4_COLLSEQ); VdbeCoverage(v);
|
|
+ sqlite3VdbeAddOp4(v, op, rLhs, destIfFalse, r2,
|
|
+ (void*)pColl, P4_COLLSEQ);
|
|
+ VdbeCoverageIf(v, op==OP_Ne);
|
|
+ VdbeCoverageIf(v, op==OP_IsNull);
|
|
sqlite3VdbeChangeP5(v, zAff[0] | SQLITE_JUMPIFNULL);
|
|
}
|
|
- sqlite3ReleaseTempReg(pParse, regToFree);
|
|
}
|
|
if( regCkNull ){
|
|
sqlite3VdbeAddOp2(v, OP_IsNull, regCkNull, destIfNull); VdbeCoverage(v);
|
|
@@ -100353,6 +102797,7 @@
|
|
}else{
|
|
destStep2 = destStep6 = sqlite3VdbeMakeLabel(pParse);
|
|
}
|
|
+ if( pParse->nErr ) goto sqlite3ExprCodeIN_finished;
|
|
for(i=0; i<nVector; i++){
|
|
Expr *p = sqlite3VectorFieldSubexpr(pExpr->pLeft, i);
|
|
if( sqlite3ExprCanBeNull(p) ){
|
|
@@ -100534,16 +102979,45 @@
|
|
}
|
|
}
|
|
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+/*
|
|
+** Generate code that will compute the value of generated column pCol
|
|
+** and store the result in register regOut
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3ExprCodeGeneratedColumn(
|
|
+ Parse *pParse,
|
|
+ Column *pCol,
|
|
+ int regOut
|
|
+){
|
|
+ int iAddr;
|
|
+ Vdbe *v = pParse->pVdbe;
|
|
+ assert( v!=0 );
|
|
+ assert( pParse->iSelfTab!=0 );
|
|
+ if( pParse->iSelfTab>0 ){
|
|
+ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut);
|
|
+ }else{
|
|
+ iAddr = 0;
|
|
+ }
|
|
+ sqlite3ExprCodeCopy(pParse, pCol->pDflt, regOut);
|
|
+ if( pCol->affinity>=SQLITE_AFF_TEXT ){
|
|
+ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1);
|
|
+ }
|
|
+ if( iAddr ) sqlite3VdbeJumpHere(v, iAddr);
|
|
+}
|
|
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
|
+
|
|
/*
|
|
** Generate code to extract the value of the iCol-th column of a table.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ExprCodeGetColumnOfTable(
|
|
- Vdbe *v, /* The VDBE under construction */
|
|
+ Vdbe *v, /* Parsing context */
|
|
Table *pTab, /* The table containing the value */
|
|
int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */
|
|
int iCol, /* Index of the column to extract */
|
|
int regOut /* Extract the value into this register */
|
|
){
|
|
+ Column *pCol;
|
|
+ assert( v!=0 );
|
|
if( pTab==0 ){
|
|
sqlite3VdbeAddOp3(v, OP_Column, iTabCur, iCol, regOut);
|
|
return;
|
|
@@ -100551,14 +103025,36 @@
|
|
if( iCol<0 || iCol==pTab->iPKey ){
|
|
sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut);
|
|
}else{
|
|
- int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
|
|
- int x = iCol;
|
|
- if( !HasRowid(pTab) && !IsVirtual(pTab) ){
|
|
- x = sqlite3ColumnOfIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
|
|
+ int op;
|
|
+ int x;
|
|
+ if( IsVirtual(pTab) ){
|
|
+ op = OP_VColumn;
|
|
+ x = iCol;
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ }else if( (pCol = &pTab->aCol[iCol])->colFlags & COLFLAG_VIRTUAL ){
|
|
+ Parse *pParse = sqlite3VdbeParser(v);
|
|
+ if( pCol->colFlags & COLFLAG_BUSY ){
|
|
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pCol->zName);
|
|
+ }else{
|
|
+ int savedSelfTab = pParse->iSelfTab;
|
|
+ pCol->colFlags |= COLFLAG_BUSY;
|
|
+ pParse->iSelfTab = iTabCur+1;
|
|
+ sqlite3ExprCodeGeneratedColumn(pParse, pCol, regOut);
|
|
+ pParse->iSelfTab = savedSelfTab;
|
|
+ pCol->colFlags &= ~COLFLAG_BUSY;
|
|
+ }
|
|
+ return;
|
|
+#endif
|
|
+ }else if( !HasRowid(pTab) ){
|
|
+ testcase( iCol!=sqlite3TableColumnToStorage(pTab, iCol) );
|
|
+ x = sqlite3TableColumnToIndex(sqlite3PrimaryKeyIndex(pTab), iCol);
|
|
+ op = OP_Column;
|
|
+ }else{
|
|
+ x = sqlite3TableColumnToStorage(pTab,iCol);
|
|
+ testcase( x!=iCol );
|
|
+ op = OP_Column;
|
|
}
|
|
sqlite3VdbeAddOp3(v, op, iTabCur, x, regOut);
|
|
- }
|
|
- if( iCol>=0 ){
|
|
sqlite3ColumnDefault(v, pTab, iCol, regOut);
|
|
}
|
|
}
|
|
@@ -100578,11 +103074,11 @@
|
|
int iReg, /* Store results here */
|
|
u8 p5 /* P5 value for OP_Column + FLAGS */
|
|
){
|
|
- Vdbe *v = pParse->pVdbe;
|
|
- assert( v!=0 );
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iTable, iColumn, iReg);
|
|
+ assert( pParse->pVdbe!=0 );
|
|
+ sqlite3ExprCodeGetColumnOfTable(pParse->pVdbe, pTab, iTable, iColumn, iReg);
|
|
if( p5 ){
|
|
- sqlite3VdbeChangeP5(v, p5);
|
|
+ VdbeOp *pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1);
|
|
+ if( pOp->opcode==OP_Column ) pOp->p5 = p5;
|
|
}
|
|
return iReg;
|
|
}
|
|
@@ -100592,7 +103088,6 @@
|
|
** over to iTo..iTo+nReg-1.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
|
- assert( iFrom>=iTo+nReg || iFrom+nReg<=iTo );
|
|
sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
|
|
}
|
|
|
|
@@ -100602,7 +103097,7 @@
|
|
** the correct value for the expression.
|
|
*/
|
|
static void exprToRegister(Expr *pExpr, int iReg){
|
|
- Expr *p = sqlite3ExprSkipCollate(pExpr);
|
|
+ Expr *p = sqlite3ExprSkipCollateAndLikely(pExpr);
|
|
p->op2 = p->op;
|
|
p->op = TK_REGISTER;
|
|
p->iTable = iReg;
|
|
@@ -100644,6 +103139,124 @@
|
|
return iResult;
|
|
}
|
|
|
|
+/*
|
|
+** If the last opcode is a OP_Copy, then set the do-not-merge flag (p5)
|
|
+** so that a subsequent copy will not be merged into this one.
|
|
+*/
|
|
+static void setDoNotMergeFlagOnCopy(Vdbe *v){
|
|
+ if( sqlite3VdbeGetOp(v, -1)->opcode==OP_Copy ){
|
|
+ sqlite3VdbeChangeP5(v, 1); /* Tag trailing OP_Copy as not mergable */
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+** Generate code to implement special SQL functions that are implemented
|
|
+** in-line rather than by using the usual callbacks.
|
|
+*/
|
|
+static int exprCodeInlineFunction(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ ExprList *pFarg, /* List of function arguments */
|
|
+ int iFuncId, /* Function ID. One of the INTFUNC_... values */
|
|
+ int target /* Store function result in this register */
|
|
+){
|
|
+ int nFarg;
|
|
+ Vdbe *v = pParse->pVdbe;
|
|
+ assert( v!=0 );
|
|
+ assert( pFarg!=0 );
|
|
+ nFarg = pFarg->nExpr;
|
|
+ assert( nFarg>0 ); /* All in-line functions have at least one argument */
|
|
+ switch( iFuncId ){
|
|
+ case INLINEFUNC_coalesce: {
|
|
+ /* Attempt a direct implementation of the built-in COALESCE() and
|
|
+ ** IFNULL() functions. This avoids unnecessary evaluation of
|
|
+ ** arguments past the first non-NULL argument.
|
|
+ */
|
|
+ int endCoalesce = sqlite3VdbeMakeLabel(pParse);
|
|
+ int i;
|
|
+ assert( nFarg>=2 );
|
|
+ sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
|
+ for(i=1; i<nFarg; i++){
|
|
+ sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
|
|
+ VdbeCoverage(v);
|
|
+ sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
|
|
+ }
|
|
+ setDoNotMergeFlagOnCopy(v);
|
|
+ sqlite3VdbeResolveLabel(v, endCoalesce);
|
|
+ break;
|
|
+ }
|
|
+ case INLINEFUNC_iif: {
|
|
+ Expr caseExpr;
|
|
+ memset(&caseExpr, 0, sizeof(caseExpr));
|
|
+ caseExpr.op = TK_CASE;
|
|
+ caseExpr.x.pList = pFarg;
|
|
+ return sqlite3ExprCodeTarget(pParse, &caseExpr, target);
|
|
+ }
|
|
+
|
|
+ default: {
|
|
+ /* The UNLIKELY() function is a no-op. The result is the value
|
|
+ ** of the first argument.
|
|
+ */
|
|
+ assert( nFarg==1 || nFarg==2 );
|
|
+ target = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /***********************************************************************
|
|
+ ** Test-only SQL functions that are only usable if enabled
|
|
+ ** via SQLITE_TESTCTRL_INTERNAL_FUNCTIONS
|
|
+ */
|
|
+ case INLINEFUNC_expr_compare: {
|
|
+ /* Compare two expressions using sqlite3ExprCompare() */
|
|
+ assert( nFarg==2 );
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer,
|
|
+ sqlite3ExprCompare(0,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1),
|
|
+ target);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case INLINEFUNC_expr_implies_expr: {
|
|
+ /* Compare two expressions using sqlite3ExprImpliesExpr() */
|
|
+ assert( nFarg==2 );
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer,
|
|
+ sqlite3ExprImpliesExpr(pParse,pFarg->a[0].pExpr, pFarg->a[1].pExpr,-1),
|
|
+ target);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ case INLINEFUNC_implies_nonnull_row: {
|
|
+ /* REsult of sqlite3ExprImpliesNonNullRow() */
|
|
+ Expr *pA1;
|
|
+ assert( nFarg==2 );
|
|
+ pA1 = pFarg->a[1].pExpr;
|
|
+ if( pA1->op==TK_COLUMN ){
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer,
|
|
+ sqlite3ExprImpliesNonNullRow(pFarg->a[0].pExpr,pA1->iTable),
|
|
+ target);
|
|
+ }else{
|
|
+ sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+
|
|
+#ifdef SQLITE_DEBUG
|
|
+ case INLINEFUNC_affinity: {
|
|
+ /* The AFFINITY() function evaluates to a string that describes
|
|
+ ** the type affinity of the argument. This is used for testing of
|
|
+ ** the SQLite type logic.
|
|
+ */
|
|
+ const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
|
|
+ char aff;
|
|
+ assert( nFarg==1 );
|
|
+ aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
|
|
+ sqlite3VdbeLoadString(v, target,
|
|
+ (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]);
|
|
+ break;
|
|
+ }
|
|
+#endif
|
|
+ }
|
|
+ return target;
|
|
+}
|
|
+
|
|
|
|
/*
|
|
** Generate code into the current Vdbe to evaluate the given
|
|
@@ -100676,24 +103289,38 @@
|
|
if( pExpr==0 ){
|
|
op = TK_NULL;
|
|
}else{
|
|
+ assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
|
op = pExpr->op;
|
|
}
|
|
switch( op ){
|
|
case TK_AGG_COLUMN: {
|
|
AggInfo *pAggInfo = pExpr->pAggInfo;
|
|
- struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
|
|
+ struct AggInfo_col *pCol;
|
|
+ assert( pAggInfo!=0 );
|
|
+ assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn );
|
|
+ pCol = &pAggInfo->aCol[pExpr->iAgg];
|
|
if( !pAggInfo->directMode ){
|
|
assert( pCol->iMem>0 );
|
|
return pCol->iMem;
|
|
}else if( pAggInfo->useSortingIdx ){
|
|
+ Table *pTab = pCol->pTab;
|
|
sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
|
|
pCol->iSorterColumn, target);
|
|
+ if( pCol->iColumn<0 ){
|
|
+ VdbeComment((v,"%s.rowid",pTab->zName));
|
|
+ }else{
|
|
+ VdbeComment((v,"%s.%s",pTab->zName,pTab->aCol[pCol->iColumn].zName));
|
|
+ if( pTab->aCol[pCol->iColumn].affinity==SQLITE_AFF_REAL ){
|
|
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
|
|
+ }
|
|
+ }
|
|
return target;
|
|
}
|
|
/* Otherwise, fall thru into the TK_COLUMN case */
|
|
}
|
|
case TK_COLUMN: {
|
|
int iTab = pExpr->iTable;
|
|
+ int iReg;
|
|
if( ExprHasProperty(pExpr, EP_FixedCol) ){
|
|
/* This COLUMN expression is really a constant due to WHERE clause
|
|
** constraints, and that constant is coded by the pExpr->pLeft
|
|
@@ -100701,16 +103328,17 @@
|
|
** datatype by applying the Affinity of the table column to the
|
|
** constant.
|
|
*/
|
|
- int iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
|
|
- int aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
|
- if( aff!=SQLITE_AFF_BLOB ){
|
|
+ int aff;
|
|
+ iReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft,target);
|
|
+ if( pExpr->y.pTab ){
|
|
+ aff = sqlite3TableColumnAffinity(pExpr->y.pTab, pExpr->iColumn);
|
|
+ }else{
|
|
+ aff = pExpr->affExpr;
|
|
+ }
|
|
+ if( aff>SQLITE_AFF_BLOB ){
|
|
static const char zAff[] = "B\000C\000D\000E";
|
|
assert( SQLITE_AFF_BLOB=='A' );
|
|
assert( SQLITE_AFF_TEXT=='B' );
|
|
- if( iReg!=target ){
|
|
- sqlite3VdbeAddOp2(v, OP_SCopy, iReg, target);
|
|
- iReg = target;
|
|
- }
|
|
sqlite3VdbeAddOp4(v, OP_Affinity, iReg, 1, 0,
|
|
&zAff[(aff-'B')*2], P4_STATIC);
|
|
}
|
|
@@ -100718,17 +103346,60 @@
|
|
}
|
|
if( iTab<0 ){
|
|
if( pParse->iSelfTab<0 ){
|
|
- /* Generating CHECK constraints or inserting into partial index */
|
|
- return pExpr->iColumn - pParse->iSelfTab;
|
|
+ /* Other columns in the same row for CHECK constraints or
|
|
+ ** generated columns or for inserting into partial index.
|
|
+ ** The row is unpacked into registers beginning at
|
|
+ ** 0-(pParse->iSelfTab). The rowid (if any) is in a register
|
|
+ ** immediately prior to the first column.
|
|
+ */
|
|
+ Column *pCol;
|
|
+ Table *pTab = pExpr->y.pTab;
|
|
+ int iSrc;
|
|
+ int iCol = pExpr->iColumn;
|
|
+ assert( pTab!=0 );
|
|
+ assert( iCol>=XN_ROWID );
|
|
+ assert( iCol<pTab->nCol );
|
|
+ if( iCol<0 ){
|
|
+ return -1-pParse->iSelfTab;
|
|
+ }
|
|
+ pCol = pTab->aCol + iCol;
|
|
+ testcase( iCol!=sqlite3TableColumnToStorage(pTab,iCol) );
|
|
+ iSrc = sqlite3TableColumnToStorage(pTab, iCol) - pParse->iSelfTab;
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( pCol->colFlags & COLFLAG_GENERATED ){
|
|
+ if( pCol->colFlags & COLFLAG_BUSY ){
|
|
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"",
|
|
+ pCol->zName);
|
|
+ return 0;
|
|
+ }
|
|
+ pCol->colFlags |= COLFLAG_BUSY;
|
|
+ if( pCol->colFlags & COLFLAG_NOTAVAIL ){
|
|
+ sqlite3ExprCodeGeneratedColumn(pParse, pCol, iSrc);
|
|
+ }
|
|
+ pCol->colFlags &= ~(COLFLAG_BUSY|COLFLAG_NOTAVAIL);
|
|
+ return iSrc;
|
|
+ }else
|
|
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
|
+ if( pCol->affinity==SQLITE_AFF_REAL ){
|
|
+ sqlite3VdbeAddOp2(v, OP_SCopy, iSrc, target);
|
|
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
|
|
+ return target;
|
|
+ }else{
|
|
+ return iSrc;
|
|
+ }
|
|
}else{
|
|
/* Coding an expression that is part of an index where column names
|
|
** in the index refer to the table to which the index belongs */
|
|
iTab = pParse->iSelfTab - 1;
|
|
}
|
|
}
|
|
- return sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
|
|
+ iReg = sqlite3ExprCodeGetColumn(pParse, pExpr->y.pTab,
|
|
pExpr->iColumn, iTab, target,
|
|
pExpr->op2);
|
|
+ if( pExpr->y.pTab==0 && pExpr->affExpr==SQLITE_AFF_REAL ){
|
|
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
|
|
+ }
|
|
+ return iReg;
|
|
}
|
|
case TK_INTEGER: {
|
|
codeInteger(pParse, pExpr, 0, target);
|
|
@@ -100750,7 +103421,12 @@
|
|
sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
|
|
return target;
|
|
}
|
|
- case TK_NULL: {
|
|
+ default: {
|
|
+ /* Make NULL the default case so that if a bug causes an illegal
|
|
+ ** Expr node to be passed into this function, it will be handled
|
|
+ ** sanely and not crash. But keep the assert() to bring the problem
|
|
+ ** to the attention of the developers. */
|
|
+ assert( op==TK_NULL );
|
|
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
|
return target;
|
|
}
|
|
@@ -100777,7 +103453,7 @@
|
|
sqlite3VdbeAddOp2(v, OP_Variable, pExpr->iColumn, target);
|
|
if( pExpr->u.zToken[1]!=0 ){
|
|
const char *z = sqlite3VListNumToName(pParse->pVList, pExpr->iColumn);
|
|
- assert( pExpr->u.zToken[0]=='?' || strcmp(pExpr->u.zToken, z)==0 );
|
|
+ assert( pExpr->u.zToken[0]=='?' || (z && !strcmp(pExpr->u.zToken, z)) );
|
|
pParse->pVList[0] = 0; /* Indicate VList may no longer be enlarged */
|
|
sqlite3VdbeAppendP4(v, (char*)z, P4_STATIC);
|
|
}
|
|
@@ -100817,7 +103493,8 @@
|
|
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
|
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
|
codeCompare(pParse, pLeft, pExpr->pRight, op,
|
|
- r1, r2, inReg, SQLITE_STOREP2 | p5);
|
|
+ r1, r2, inReg, SQLITE_STOREP2 | p5,
|
|
+ ExprHasProperty(pExpr,EP_Commuted));
|
|
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
|
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
|
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
|
@@ -100875,6 +103552,7 @@
|
|
tempX.op = TK_INTEGER;
|
|
tempX.flags = EP_IntValue|EP_TokenOnly;
|
|
tempX.u.iValue = 0;
|
|
+ ExprClearVVAProperties(&tempX);
|
|
r1 = sqlite3ExprCodeTemp(pParse, &tempX, ®Free1);
|
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free2);
|
|
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
|
|
@@ -100920,7 +103598,10 @@
|
|
}
|
|
case TK_AGG_FUNCTION: {
|
|
AggInfo *pInfo = pExpr->pAggInfo;
|
|
- if( pInfo==0 ){
|
|
+ if( pInfo==0
|
|
+ || NEVER(pExpr->iAgg<0)
|
|
+ || NEVER(pExpr->iAgg>=pInfo->nFunc)
|
|
+ ){
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
|
|
}else{
|
|
@@ -100946,16 +103627,13 @@
|
|
#endif
|
|
|
|
if( ConstFactorOk(pParse) && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
|
- /* SQL functions can be expensive. So try to move constant functions
|
|
- ** out of the inner loop, even if that means an extra OP_Copy. */
|
|
- return sqlite3ExprCodeAtInit(pParse, pExpr, -1);
|
|
+ /* SQL functions can be expensive. So try to avoid running them
|
|
+ ** multiple times if we know they always give the same result */
|
|
+ return sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
|
}
|
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
|
- if( ExprHasProperty(pExpr, EP_TokenOnly) ){
|
|
- pFarg = 0;
|
|
- }else{
|
|
- pFarg = pExpr->x.pList;
|
|
- }
|
|
+ assert( !ExprHasProperty(pExpr, EP_TokenOnly) );
|
|
+ pFarg = pExpr->x.pList;
|
|
nFarg = pFarg ? pFarg->nExpr : 0;
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
zId = pExpr->u.zToken;
|
|
@@ -100969,48 +103647,15 @@
|
|
sqlite3ErrorMsg(pParse, "unknown function: %s()", zId);
|
|
break;
|
|
}
|
|
-
|
|
- /* Attempt a direct implementation of the built-in COALESCE() and
|
|
- ** IFNULL() functions. This avoids unnecessary evaluation of
|
|
- ** arguments past the first non-NULL argument.
|
|
- */
|
|
- if( pDef->funcFlags & SQLITE_FUNC_COALESCE ){
|
|
- int endCoalesce = sqlite3VdbeMakeLabel(pParse);
|
|
- assert( nFarg>=2 );
|
|
- sqlite3ExprCode(pParse, pFarg->a[0].pExpr, target);
|
|
- for(i=1; i<nFarg; i++){
|
|
- sqlite3VdbeAddOp2(v, OP_NotNull, target, endCoalesce);
|
|
- VdbeCoverage(v);
|
|
- sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
|
|
- }
|
|
- sqlite3VdbeResolveLabel(v, endCoalesce);
|
|
- break;
|
|
+ if( pDef->funcFlags & SQLITE_FUNC_INLINE ){
|
|
+ assert( (pDef->funcFlags & SQLITE_FUNC_UNSAFE)==0 );
|
|
+ assert( (pDef->funcFlags & SQLITE_FUNC_DIRECT)==0 );
|
|
+ return exprCodeInlineFunction(pParse, pFarg,
|
|
+ SQLITE_PTR_TO_INT(pDef->pUserData), target);
|
|
+ }else if( pDef->funcFlags & (SQLITE_FUNC_DIRECT|SQLITE_FUNC_UNSAFE) ){
|
|
+ sqlite3ExprFunctionUsable(pParse, pExpr, pDef);
|
|
}
|
|
|
|
- /* The UNLIKELY() function is a no-op. The result is the value
|
|
- ** of the first argument.
|
|
- */
|
|
- if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
|
- assert( nFarg>=1 );
|
|
- return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
|
|
- }
|
|
-
|
|
-#ifdef SQLITE_DEBUG
|
|
- /* The AFFINITY() function evaluates to a string that describes
|
|
- ** the type affinity of the argument. This is used for testing of
|
|
- ** the SQLite type logic.
|
|
- */
|
|
- if( pDef->funcFlags & SQLITE_FUNC_AFFINITY ){
|
|
- const char *azAff[] = { "blob", "text", "numeric", "integer", "real" };
|
|
- char aff;
|
|
- assert( nFarg==1 );
|
|
- aff = sqlite3ExprAffinity(pFarg->a[0].pExpr);
|
|
- sqlite3VdbeLoadString(v, target,
|
|
- aff ? azAff[aff-SQLITE_AFF_BLOB] : "none");
|
|
- return target;
|
|
- }
|
|
-#endif
|
|
-
|
|
for(i=0; i<nFarg; i++){
|
|
if( i<32 && sqlite3ExprIsConstant(pFarg->a[i].pExpr) ){
|
|
testcase( i==31 );
|
|
@@ -101086,12 +103731,15 @@
|
|
}else
|
|
#endif
|
|
{
|
|
- sqlite3VdbeAddOp4(v, pParse->iSelfTab ? OP_PureFunc0 : OP_Function0,
|
|
- constMask, r1, target, (char*)pDef, P4_FUNCDEF);
|
|
- sqlite3VdbeChangeP5(v, (u8)nFarg);
|
|
+ sqlite3VdbeAddFunctionCall(pParse, constMask, r1, target, nFarg,
|
|
+ pDef, pExpr->op2);
|
|
}
|
|
- if( nFarg && constMask==0 ){
|
|
- sqlite3ReleaseTempRange(pParse, r1, nFarg);
|
|
+ if( nFarg ){
|
|
+ if( constMask==0 ){
|
|
+ sqlite3ReleaseTempRange(pParse, r1, nFarg);
|
|
+ }else{
|
|
+ sqlite3VdbeReleaseRegisters(pParse, r1, nFarg, constMask, 1);
|
|
+ }
|
|
}
|
|
return target;
|
|
}
|
|
@@ -101114,8 +103762,8 @@
|
|
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
|
|
}
|
|
assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
|
|
- if( pExpr->iTable
|
|
- && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
|
|
+ if( pExpr->iTable!=0
|
|
+ && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
|
|
){
|
|
sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
|
|
pExpr->iTable, n);
|
|
@@ -101185,17 +103833,19 @@
|
|
** p1==2 -> old.b p1==5 -> new.b
|
|
*/
|
|
Table *pTab = pExpr->y.pTab;
|
|
- int p1 = pExpr->iTable * (pTab->nCol+1) + 1 + pExpr->iColumn;
|
|
+ int iCol = pExpr->iColumn;
|
|
+ int p1 = pExpr->iTable * (pTab->nCol+1) + 1
|
|
+ + sqlite3TableColumnToStorage(pTab, iCol);
|
|
|
|
assert( pExpr->iTable==0 || pExpr->iTable==1 );
|
|
- assert( pExpr->iColumn>=-1 && pExpr->iColumn<pTab->nCol );
|
|
- assert( pTab->iPKey<0 || pExpr->iColumn!=pTab->iPKey );
|
|
+ assert( iCol>=-1 && iCol<pTab->nCol );
|
|
+ assert( pTab->iPKey<0 || iCol!=pTab->iPKey );
|
|
assert( p1>=0 && p1<(pTab->nCol*2+2) );
|
|
|
|
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
|
|
VdbeComment((v, "r[%d]=%s.%s", target,
|
|
(pExpr->iTable ? "new" : "old"),
|
|
- (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[pExpr->iColumn].zName)
|
|
+ (pExpr->iColumn<0 ? "rowid" : pExpr->y.pTab->aCol[iCol].zName)
|
|
));
|
|
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
@@ -101204,9 +103854,7 @@
|
|
**
|
|
** EVIDENCE-OF: R-60985-57662 SQLite will convert the value back to
|
|
** floating point when extracting it from the record. */
|
|
- if( pExpr->iColumn>=0
|
|
- && pTab->aCol[pExpr->iColumn].affinity==SQLITE_AFF_REAL
|
|
- ){
|
|
+ if( iCol>=0 && pTab->aCol[iCol].affinity==SQLITE_AFF_REAL ){
|
|
sqlite3VdbeAddOp1(v, OP_RealAffinity, target);
|
|
}
|
|
#endif
|
|
@@ -101218,10 +103866,23 @@
|
|
break;
|
|
}
|
|
|
|
+ /* TK_IF_NULL_ROW Expr nodes are inserted ahead of expressions
|
|
+ ** that derive from the right-hand table of a LEFT JOIN. The
|
|
+ ** Expr.iTable value is the table number for the right-hand table.
|
|
+ ** The expression is only evaluated if that table is not currently
|
|
+ ** on a LEFT JOIN NULL row.
|
|
+ */
|
|
case TK_IF_NULL_ROW: {
|
|
int addrINR;
|
|
+ u8 okConstFactor = pParse->okConstFactor;
|
|
addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
|
|
+ /* Temporarily disable factoring of constant expressions, since
|
|
+ ** even though expressions may appear to be constant, they are not
|
|
+ ** really constant because they originate from the right-hand side
|
|
+ ** of a LEFT JOIN. */
|
|
+ pParse->okConstFactor = 0;
|
|
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
|
+ pParse->okConstFactor = okConstFactor;
|
|
sqlite3VdbeJumpHere(v, addrINR);
|
|
sqlite3VdbeChangeP3(v, addrINR, inReg);
|
|
break;
|
|
@@ -101248,7 +103909,7 @@
|
|
** or if there is no matching Ei, the ELSE term Y, or if there is
|
|
** no ELSE term, NULL.
|
|
*/
|
|
- default: assert( op==TK_CASE ); {
|
|
+ case TK_CASE: {
|
|
int endLabel; /* GOTO label for end of CASE stmt */
|
|
int nextCase; /* GOTO label for next WHEN clause */
|
|
int nExpr; /* 2x number of WHEN terms */
|
|
@@ -101258,6 +103919,8 @@
|
|
Expr opCompare; /* The X==Ei expression */
|
|
Expr *pX; /* The X expression */
|
|
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
|
|
+ Expr *pDel = 0;
|
|
+ sqlite3 *db = pParse->db;
|
|
|
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) && pExpr->x.pList );
|
|
assert(pExpr->x.pList->nExpr > 0);
|
|
@@ -101266,13 +103929,17 @@
|
|
nExpr = pEList->nExpr;
|
|
endLabel = sqlite3VdbeMakeLabel(pParse);
|
|
if( (pX = pExpr->pLeft)!=0 ){
|
|
- exprNodeCopy(&tempX, pX);
|
|
+ pDel = sqlite3ExprDup(db, pX, 0);
|
|
+ if( db->mallocFailed ){
|
|
+ sqlite3ExprDelete(db, pDel);
|
|
+ break;
|
|
+ }
|
|
testcase( pX->op==TK_COLUMN );
|
|
- exprToRegister(&tempX, exprCodeVector(pParse, &tempX, ®Free1));
|
|
+ exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
|
testcase( regFree1==0 );
|
|
memset(&opCompare, 0, sizeof(opCompare));
|
|
opCompare.op = TK_EQ;
|
|
- opCompare.pLeft = &tempX;
|
|
+ opCompare.pLeft = pDel;
|
|
pTest = &opCompare;
|
|
/* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
|
|
** The value in regFree1 might get SCopy-ed into the file result.
|
|
@@ -101300,32 +103967,35 @@
|
|
}else{
|
|
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
|
}
|
|
+ sqlite3ExprDelete(db, pDel);
|
|
+ setDoNotMergeFlagOnCopy(v);
|
|
sqlite3VdbeResolveLabel(v, endLabel);
|
|
break;
|
|
}
|
|
#ifndef SQLITE_OMIT_TRIGGER
|
|
case TK_RAISE: {
|
|
- assert( pExpr->affinity==OE_Rollback
|
|
- || pExpr->affinity==OE_Abort
|
|
- || pExpr->affinity==OE_Fail
|
|
- || pExpr->affinity==OE_Ignore
|
|
+ assert( pExpr->affExpr==OE_Rollback
|
|
+ || pExpr->affExpr==OE_Abort
|
|
+ || pExpr->affExpr==OE_Fail
|
|
+ || pExpr->affExpr==OE_Ignore
|
|
);
|
|
- if( !pParse->pTriggerTab ){
|
|
+ if( !pParse->pTriggerTab && !pParse->nested ){
|
|
sqlite3ErrorMsg(pParse,
|
|
"RAISE() may only be used within a trigger-program");
|
|
return 0;
|
|
}
|
|
- if( pExpr->affinity==OE_Abort ){
|
|
+ if( pExpr->affExpr==OE_Abort ){
|
|
sqlite3MayAbort(pParse);
|
|
}
|
|
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
|
- if( pExpr->affinity==OE_Ignore ){
|
|
+ if( pExpr->affExpr==OE_Ignore ){
|
|
sqlite3VdbeAddOp4(
|
|
v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0);
|
|
VdbeCoverage(v);
|
|
}else{
|
|
- sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER,
|
|
- pExpr->affinity, pExpr->u.zToken, 0, 0);
|
|
+ sqlite3HaltConstraint(pParse,
|
|
+ pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR,
|
|
+ pExpr->affExpr, pExpr->u.zToken, 0, 0);
|
|
}
|
|
|
|
break;
|
|
@@ -101338,15 +104008,23 @@
|
|
}
|
|
|
|
/*
|
|
-** Factor out the code of the given expression to initialization time.
|
|
+** Generate code that will evaluate expression pExpr just one time
|
|
+** per prepared statement execution.
|
|
+**
|
|
+** If the expression uses functions (that might throw an exception) then
|
|
+** guard them with an OP_Once opcode to ensure that the code is only executed
|
|
+** once. If no functions are involved, then factor the code out and put it at
|
|
+** the end of the prepared statement in the initialization section.
|
|
**
|
|
** If regDest>=0 then the result is always stored in that register and the
|
|
** result is not reusable. If regDest<0 then this routine is free to
|
|
** store the value whereever it wants. The register where the expression
|
|
-** is stored is returned. When regDest<0, two identical expressions will
|
|
-** code to the same register.
|
|
+** is stored is returned. When regDest<0, two identical expressions might
|
|
+** code to the same register, if they do not contain function calls and hence
|
|
+** are factored out into the initialization section at the end of the
|
|
+** prepared statement.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3ExprCodeAtInit(
|
|
+SQLITE_PRIVATE int sqlite3ExprCodeRunJustOnce(
|
|
Parse *pParse, /* Parsing context */
|
|
Expr *pExpr, /* The expression to code when the VDBE initializes */
|
|
int regDest /* Store the value in this register */
|
|
@@ -101364,14 +104042,29 @@
|
|
}
|
|
}
|
|
pExpr = sqlite3ExprDup(pParse->db, pExpr, 0);
|
|
- p = sqlite3ExprListAppend(pParse, p, pExpr);
|
|
- if( p ){
|
|
- struct ExprList_item *pItem = &p->a[p->nExpr-1];
|
|
- pItem->reusable = regDest<0;
|
|
- if( regDest<0 ) regDest = ++pParse->nMem;
|
|
- pItem->u.iConstExprReg = regDest;
|
|
+ if( pExpr!=0 && ExprHasProperty(pExpr, EP_HasFunc) ){
|
|
+ Vdbe *v = pParse->pVdbe;
|
|
+ int addr;
|
|
+ assert( v );
|
|
+ addr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
|
+ pParse->okConstFactor = 0;
|
|
+ if( !pParse->db->mallocFailed ){
|
|
+ if( regDest<0 ) regDest = ++pParse->nMem;
|
|
+ sqlite3ExprCode(pParse, pExpr, regDest);
|
|
+ }
|
|
+ pParse->okConstFactor = 1;
|
|
+ sqlite3ExprDelete(pParse->db, pExpr);
|
|
+ sqlite3VdbeJumpHere(v, addr);
|
|
+ }else{
|
|
+ p = sqlite3ExprListAppend(pParse, p, pExpr);
|
|
+ if( p ){
|
|
+ struct ExprList_item *pItem = &p->a[p->nExpr-1];
|
|
+ pItem->reusable = regDest<0;
|
|
+ if( regDest<0 ) regDest = ++pParse->nMem;
|
|
+ pItem->u.iConstExprReg = regDest;
|
|
+ }
|
|
+ pParse->pConstExpr = p;
|
|
}
|
|
- pParse->pConstExpr = p;
|
|
return regDest;
|
|
}
|
|
|
|
@@ -101390,13 +104083,13 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
|
int r2;
|
|
- pExpr = sqlite3ExprSkipCollate(pExpr);
|
|
+ pExpr = sqlite3ExprSkipCollateAndLikely(pExpr);
|
|
if( ConstFactorOk(pParse)
|
|
&& pExpr->op!=TK_REGISTER
|
|
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
|
){
|
|
*pReg = 0;
|
|
- r2 = sqlite3ExprCodeAtInit(pParse, pExpr, -1);
|
|
+ r2 = sqlite3ExprCodeRunJustOnce(pParse, pExpr, -1);
|
|
}else{
|
|
int r1 = sqlite3GetTempReg(pParse);
|
|
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
|
|
@@ -101418,15 +104111,18 @@
|
|
SQLITE_PRIVATE void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
|
|
int inReg;
|
|
|
|
+ assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
|
assert( target>0 && target<=pParse->nMem );
|
|
- if( pExpr && pExpr->op==TK_REGISTER ){
|
|
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, pExpr->iTable, target);
|
|
- }else{
|
|
- inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
|
|
- assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
|
|
- if( inReg!=target && pParse->pVdbe ){
|
|
- sqlite3VdbeAddOp2(pParse->pVdbe, OP_SCopy, inReg, target);
|
|
+ inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
|
|
+ assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
|
|
+ if( inReg!=target && pParse->pVdbe ){
|
|
+ u8 op;
|
|
+ if( ExprHasProperty(pExpr,EP_Subquery) ){
|
|
+ op = OP_Copy;
|
|
+ }else{
|
|
+ op = OP_SCopy;
|
|
}
|
|
+ sqlite3VdbeAddOp2(pParse->pVdbe, op, inReg, target);
|
|
}
|
|
}
|
|
|
|
@@ -101450,36 +104146,12 @@
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ExprCodeFactorable(Parse *pParse, Expr *pExpr, int target){
|
|
if( pParse->okConstFactor && sqlite3ExprIsConstantNotJoin(pExpr) ){
|
|
- sqlite3ExprCodeAtInit(pParse, pExpr, target);
|
|
+ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target);
|
|
}else{
|
|
- sqlite3ExprCode(pParse, pExpr, target);
|
|
+ sqlite3ExprCodeCopy(pParse, pExpr, target);
|
|
}
|
|
}
|
|
|
|
-/*
|
|
-** Generate code that evaluates the given expression and puts the result
|
|
-** in register target.
|
|
-**
|
|
-** Also make a copy of the expression results into another "cache" register
|
|
-** and modify the expression so that the next time it is evaluated,
|
|
-** the result is a copy of the cache register.
|
|
-**
|
|
-** This routine is used for expressions that are used multiple
|
|
-** times. They are evaluated once and the results of the expression
|
|
-** are reused.
|
|
-*/
|
|
-SQLITE_PRIVATE void sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
|
- Vdbe *v = pParse->pVdbe;
|
|
- int iMem;
|
|
-
|
|
- assert( target>0 );
|
|
- assert( pExpr->op!=TK_REGISTER );
|
|
- sqlite3ExprCode(pParse, pExpr, target);
|
|
- iMem = ++pParse->nMem;
|
|
- sqlite3VdbeAddOp2(v, OP_Copy, target, iMem);
|
|
- exprToRegister(pExpr, iMem);
|
|
-}
|
|
-
|
|
/*
|
|
** Generate code that pushes the value of every element of the given
|
|
** expression list into a sequence of registers beginning at target.
|
|
@@ -101534,7 +104206,7 @@
|
|
}else if( (flags & SQLITE_ECEL_FACTOR)!=0
|
|
&& sqlite3ExprIsConstantNotJoin(pExpr)
|
|
){
|
|
- sqlite3ExprCodeAtInit(pParse, pExpr, target+i);
|
|
+ sqlite3ExprCodeRunJustOnce(pParse, pExpr, target+i);
|
|
}else{
|
|
int inReg = sqlite3ExprCodeTarget(pParse, pExpr, target+i);
|
|
if( inReg!=target+i ){
|
|
@@ -101543,6 +104215,7 @@
|
|
&& (pOp=sqlite3VdbeGetOp(v, -1))->opcode==OP_Copy
|
|
&& pOp->p1+pOp->p3+1==inReg
|
|
&& pOp->p2+pOp->p3+1==target+i
|
|
+ && pOp->p5==0 /* The do-not-merge flag must be clear */
|
|
){
|
|
pOp->p3++;
|
|
}else{
|
|
@@ -101581,40 +104254,44 @@
|
|
void (*xJump)(Parse*,Expr*,int,int), /* Action to take */
|
|
int jumpIfNull /* Take the jump if the BETWEEN is NULL */
|
|
){
|
|
- Expr exprAnd; /* The AND operator in x>=y AND x<=z */
|
|
+ Expr exprAnd; /* The AND operator in x>=y AND x<=z */
|
|
Expr compLeft; /* The x>=y term */
|
|
Expr compRight; /* The x<=z term */
|
|
- Expr exprX; /* The x subexpression */
|
|
int regFree1 = 0; /* Temporary use register */
|
|
+ Expr *pDel = 0;
|
|
+ sqlite3 *db = pParse->db;
|
|
|
|
memset(&compLeft, 0, sizeof(Expr));
|
|
memset(&compRight, 0, sizeof(Expr));
|
|
memset(&exprAnd, 0, sizeof(Expr));
|
|
|
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
|
- exprNodeCopy(&exprX, pExpr->pLeft);
|
|
- exprAnd.op = TK_AND;
|
|
- exprAnd.pLeft = &compLeft;
|
|
- exprAnd.pRight = &compRight;
|
|
- compLeft.op = TK_GE;
|
|
- compLeft.pLeft = &exprX;
|
|
- compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
|
- compRight.op = TK_LE;
|
|
- compRight.pLeft = &exprX;
|
|
- compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
|
- exprToRegister(&exprX, exprCodeVector(pParse, &exprX, ®Free1));
|
|
- if( xJump ){
|
|
- xJump(pParse, &exprAnd, dest, jumpIfNull);
|
|
- }else{
|
|
- /* Mark the expression is being from the ON or USING clause of a join
|
|
- ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
|
|
- ** it into the Parse.pConstExpr list. We should use a new bit for this,
|
|
- ** for clarity, but we are out of bits in the Expr.flags field so we
|
|
- ** have to reuse the EP_FromJoin bit. Bummer. */
|
|
- exprX.flags |= EP_FromJoin;
|
|
- sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
|
|
+ pDel = sqlite3ExprDup(db, pExpr->pLeft, 0);
|
|
+ if( db->mallocFailed==0 ){
|
|
+ exprAnd.op = TK_AND;
|
|
+ exprAnd.pLeft = &compLeft;
|
|
+ exprAnd.pRight = &compRight;
|
|
+ compLeft.op = TK_GE;
|
|
+ compLeft.pLeft = pDel;
|
|
+ compLeft.pRight = pExpr->x.pList->a[0].pExpr;
|
|
+ compRight.op = TK_LE;
|
|
+ compRight.pLeft = pDel;
|
|
+ compRight.pRight = pExpr->x.pList->a[1].pExpr;
|
|
+ exprToRegister(pDel, exprCodeVector(pParse, pDel, ®Free1));
|
|
+ if( xJump ){
|
|
+ xJump(pParse, &exprAnd, dest, jumpIfNull);
|
|
+ }else{
|
|
+ /* Mark the expression is being from the ON or USING clause of a join
|
|
+ ** so that the sqlite3ExprCodeTarget() routine will not attempt to move
|
|
+ ** it into the Parse.pConstExpr list. We should use a new bit for this,
|
|
+ ** for clarity, but we are out of bits in the Expr.flags field so we
|
|
+ ** have to reuse the EP_FromJoin bit. Bummer. */
|
|
+ pDel->flags |= EP_FromJoin;
|
|
+ sqlite3ExprCodeTarget(pParse, &exprAnd, dest);
|
|
+ }
|
|
+ sqlite3ReleaseTempReg(pParse, regFree1);
|
|
}
|
|
- sqlite3ReleaseTempReg(pParse, regFree1);
|
|
+ sqlite3ExprDelete(db, pDel);
|
|
|
|
/* Ensure adequate test coverage */
|
|
testcase( xJump==sqlite3ExprIfTrue && jumpIfNull==0 && regFree1==0 );
|
|
@@ -101652,6 +104329,7 @@
|
|
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
|
if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
|
if( NEVER(pExpr==0) ) return; /* No way this can happen */
|
|
+ assert( !ExprHasVVAProperty(pExpr, EP_Immutable) );
|
|
op = pExpr->op;
|
|
switch( op ){
|
|
case TK_AND:
|
|
@@ -101713,7 +104391,7 @@
|
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
|
- r1, r2, dest, jumpIfNull);
|
|
+ r1, r2, dest, jumpIfNull, ExprHasProperty(pExpr,EP_Commuted));
|
|
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
|
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
|
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
|
@@ -101793,6 +104471,7 @@
|
|
assert( jumpIfNull==SQLITE_JUMPIFNULL || jumpIfNull==0 );
|
|
if( NEVER(v==0) ) return; /* Existence of VDBE checked by caller */
|
|
if( pExpr==0 ) return;
|
|
+ assert( !ExprHasVVAProperty(pExpr,EP_Immutable) );
|
|
|
|
/* The value of pExpr->op and op are related as follows:
|
|
**
|
|
@@ -101888,7 +104567,7 @@
|
|
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
|
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pRight, ®Free2);
|
|
codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
|
|
- r1, r2, dest, jumpIfNull);
|
|
+ r1, r2, dest, jumpIfNull,ExprHasProperty(pExpr,EP_Commuted));
|
|
assert(TK_LT==OP_Lt); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt);
|
|
assert(TK_LE==OP_Le); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le);
|
|
assert(TK_GT==OP_Gt); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt);
|
|
@@ -102053,20 +104732,17 @@
|
|
return 2;
|
|
}
|
|
if( pA->op!=TK_COLUMN && pA->op!=TK_AGG_COLUMN && pA->u.zToken ){
|
|
- if( pA->op==TK_FUNCTION ){
|
|
+ if( pA->op==TK_FUNCTION || pA->op==TK_AGG_FUNCTION ){
|
|
if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ) return 2;
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- /* Justification for the assert():
|
|
- ** window functions have p->op==TK_FUNCTION but aggregate functions
|
|
- ** have p->op==TK_AGG_FUNCTION. So any comparison between an aggregate
|
|
- ** function and a window function should have failed before reaching
|
|
- ** this point. And, it is not possible to have a window function and
|
|
- ** a scalar function with the same name and number of arguments. So
|
|
- ** if we reach this point, either A and B both window functions or
|
|
- ** neither are a window functions. */
|
|
- assert( ExprHasProperty(pA,EP_WinFunc)==ExprHasProperty(pB,EP_WinFunc) );
|
|
+ assert( pA->op==pB->op );
|
|
+ if( ExprHasProperty(pA,EP_WinFunc)!=ExprHasProperty(pB,EP_WinFunc) ){
|
|
+ return 2;
|
|
+ }
|
|
if( ExprHasProperty(pA,EP_WinFunc) ){
|
|
- if( sqlite3WindowCompare(pParse,pA->y.pWin,pB->y.pWin)!=0 ) return 2;
|
|
+ if( sqlite3WindowCompare(pParse, pA->y.pWin, pB->y.pWin, 1)!=0 ){
|
|
+ return 2;
|
|
+ }
|
|
}
|
|
#endif
|
|
}else if( pA->op==TK_NULL ){
|
|
@@ -102077,8 +104753,9 @@
|
|
return 2;
|
|
}
|
|
}
|
|
- if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
|
|
- if( (combinedFlags & EP_TokenOnly)==0 ){
|
|
+ if( (pA->flags & (EP_Distinct|EP_Commuted))
|
|
+ != (pB->flags & (EP_Distinct|EP_Commuted)) ) return 2;
|
|
+ if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
|
|
if( combinedFlags & EP_xIsSelect ) return 2;
|
|
if( (combinedFlags & EP_FixedCol)==0
|
|
&& sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
|
|
@@ -102086,20 +104763,22 @@
|
|
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
|
if( pA->op!=TK_STRING
|
|
&& pA->op!=TK_TRUEFALSE
|
|
- && (combinedFlags & EP_Reduced)==0
|
|
+ && ALWAYS((combinedFlags & EP_Reduced)==0)
|
|
){
|
|
if( pA->iColumn!=pB->iColumn ) return 2;
|
|
- if( pA->op2!=pB->op2 ) return 2;
|
|
- if( pA->iTable!=pB->iTable
|
|
- && (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
|
|
+ if( pA->op2!=pB->op2 && pA->op==TK_TRUTH ) return 2;
|
|
+ if( pA->op!=TK_IN && pA->iTable!=pB->iTable && pA->iTable!=iTab ){
|
|
+ return 2;
|
|
+ }
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
-** Compare two ExprList objects. Return 0 if they are identical and
|
|
-** non-zero if they differ in any way.
|
|
+** Compare two ExprList objects. Return 0 if they are identical, 1
|
|
+** if they are certainly different, or 2 if it is not possible to
|
|
+** determine if they are identical or not.
|
|
**
|
|
** If any subelement of pB has Expr.iTable==(-1) then it is allowed
|
|
** to compare equal to an equivalent element in pA with Expr.iTable==iTab.
|
|
@@ -102118,10 +104797,11 @@
|
|
if( pA==0 || pB==0 ) return 1;
|
|
if( pA->nExpr!=pB->nExpr ) return 1;
|
|
for(i=0; i<pA->nExpr; i++){
|
|
+ int res;
|
|
Expr *pExprA = pA->a[i].pExpr;
|
|
Expr *pExprB = pB->a[i].pExpr;
|
|
- if( pA->a[i].sortOrder!=pB->a[i].sortOrder ) return 1;
|
|
- if( sqlite3ExprCompare(0, pExprA, pExprB, iTab) ) return 1;
|
|
+ if( pA->a[i].sortFlags!=pB->a[i].sortFlags ) return 1;
|
|
+ if( (res = sqlite3ExprCompare(0, pExprA, pExprB, iTab)) ) return res;
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -102132,42 +104812,47 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ExprCompareSkip(Expr *pA, Expr *pB, int iTab){
|
|
return sqlite3ExprCompare(0,
|
|
- sqlite3ExprSkipCollate(pA),
|
|
- sqlite3ExprSkipCollate(pB),
|
|
+ sqlite3ExprSkipCollateAndLikely(pA),
|
|
+ sqlite3ExprSkipCollateAndLikely(pB),
|
|
iTab);
|
|
}
|
|
|
|
/*
|
|
** Return non-zero if Expr p can only be true if pNN is not NULL.
|
|
+**
|
|
+** Or if seenNot is true, return non-zero if Expr p can only be
|
|
+** non-NULL if pNN is not NULL
|
|
*/
|
|
static int exprImpliesNotNull(
|
|
Parse *pParse, /* Parsing context */
|
|
Expr *p, /* The expression to be checked */
|
|
Expr *pNN, /* The expression that is NOT NULL */
|
|
int iTab, /* Table being evaluated */
|
|
- int seenNot /* True if p is an operand of NOT */
|
|
+ int seenNot /* Return true only if p can be any non-NULL value */
|
|
){
|
|
assert( p );
|
|
assert( pNN );
|
|
- if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ) return 1;
|
|
+ if( sqlite3ExprCompare(pParse, p, pNN, iTab)==0 ){
|
|
+ return pNN->op!=TK_NULL;
|
|
+ }
|
|
switch( p->op ){
|
|
case TK_IN: {
|
|
if( seenNot && ExprHasProperty(p, EP_xIsSelect) ) return 0;
|
|
assert( ExprHasProperty(p,EP_xIsSelect)
|
|
|| (p->x.pList!=0 && p->x.pList->nExpr>0) );
|
|
- return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
|
|
+ return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
|
|
}
|
|
case TK_BETWEEN: {
|
|
ExprList *pList = p->x.pList;
|
|
assert( pList!=0 );
|
|
assert( pList->nExpr==2 );
|
|
if( seenNot ) return 0;
|
|
- if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, seenNot)
|
|
- || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, seenNot)
|
|
+ if( exprImpliesNotNull(pParse, pList->a[0].pExpr, pNN, iTab, 1)
|
|
+ || exprImpliesNotNull(pParse, pList->a[1].pExpr, pNN, iTab, 1)
|
|
){
|
|
return 1;
|
|
}
|
|
- return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
|
|
+ return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
|
|
}
|
|
case TK_EQ:
|
|
case TK_NE:
|
|
@@ -102177,20 +104862,21 @@
|
|
case TK_GE:
|
|
case TK_PLUS:
|
|
case TK_MINUS:
|
|
- case TK_STAR:
|
|
- case TK_REM:
|
|
- case TK_BITAND:
|
|
case TK_BITOR:
|
|
- case TK_SLASH:
|
|
case TK_LSHIFT:
|
|
case TK_RSHIFT:
|
|
- case TK_CONCAT: {
|
|
+ case TK_CONCAT:
|
|
+ seenNot = 1;
|
|
+ /* Fall thru */
|
|
+ case TK_STAR:
|
|
+ case TK_REM:
|
|
+ case TK_BITAND:
|
|
+ case TK_SLASH: {
|
|
if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1;
|
|
/* Fall thru into the next case */
|
|
}
|
|
case TK_SPAN:
|
|
case TK_COLLATE:
|
|
- case TK_BITNOT:
|
|
case TK_UPLUS:
|
|
case TK_UMINUS: {
|
|
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
|
|
@@ -102198,8 +104884,9 @@
|
|
case TK_TRUTH: {
|
|
if( seenNot ) return 0;
|
|
if( p->op2!=TK_IS ) return 0;
|
|
- return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, seenNot);
|
|
+ return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
|
|
}
|
|
+ case TK_BITNOT:
|
|
case TK_NOT: {
|
|
return exprImpliesNotNull(pParse, p->pLeft, pNN, iTab, 1);
|
|
}
|
|
@@ -102251,7 +104938,7 @@
|
|
}
|
|
|
|
/*
|
|
-** This is the Expr node callback for sqlite3ExprImpliesNotNullRow().
|
|
+** This is the Expr node callback for sqlite3ExprImpliesNonNullRow().
|
|
** If the expression node requires that the table at pWalker->iCur
|
|
** have one or more non-NULL column, then set pWalker->eCode to 1 and abort.
|
|
**
|
|
@@ -102265,23 +104952,25 @@
|
|
if( ExprHasProperty(pExpr, EP_FromJoin) ) return WRC_Prune;
|
|
switch( pExpr->op ){
|
|
case TK_ISNOT:
|
|
- case TK_NOT:
|
|
case TK_ISNULL:
|
|
case TK_NOTNULL:
|
|
case TK_IS:
|
|
case TK_OR:
|
|
+ case TK_VECTOR:
|
|
case TK_CASE:
|
|
case TK_IN:
|
|
case TK_FUNCTION:
|
|
+ case TK_TRUTH:
|
|
testcase( pExpr->op==TK_ISNOT );
|
|
- testcase( pExpr->op==TK_NOT );
|
|
testcase( pExpr->op==TK_ISNULL );
|
|
testcase( pExpr->op==TK_NOTNULL );
|
|
testcase( pExpr->op==TK_IS );
|
|
testcase( pExpr->op==TK_OR );
|
|
+ testcase( pExpr->op==TK_VECTOR );
|
|
testcase( pExpr->op==TK_CASE );
|
|
testcase( pExpr->op==TK_IN );
|
|
testcase( pExpr->op==TK_FUNCTION );
|
|
+ testcase( pExpr->op==TK_TRUTH );
|
|
return WRC_Prune;
|
|
case TK_COLUMN:
|
|
if( pWalker->u.iCur==pExpr->iTable ){
|
|
@@ -102290,6 +104979,23 @@
|
|
}
|
|
return WRC_Prune;
|
|
|
|
+ case TK_AND:
|
|
+ if( pWalker->eCode==0 ){
|
|
+ sqlite3WalkExpr(pWalker, pExpr->pLeft);
|
|
+ if( pWalker->eCode ){
|
|
+ pWalker->eCode = 0;
|
|
+ sqlite3WalkExpr(pWalker, pExpr->pRight);
|
|
+ }
|
|
+ }
|
|
+ return WRC_Prune;
|
|
+
|
|
+ case TK_BETWEEN:
|
|
+ if( sqlite3WalkExpr(pWalker, pExpr->pLeft)==WRC_Abort ){
|
|
+ assert( pWalker->eCode );
|
|
+ return WRC_Abort;
|
|
+ }
|
|
+ return WRC_Prune;
|
|
+
|
|
/* Virtual tables are allowed to use constraints like x=NULL. So
|
|
** a term of the form x=y does not prove that y is not null if x
|
|
** is the column of a virtual table */
|
|
@@ -102298,18 +105004,25 @@
|
|
case TK_LT:
|
|
case TK_LE:
|
|
case TK_GT:
|
|
- case TK_GE:
|
|
+ case TK_GE: {
|
|
+ Expr *pLeft = pExpr->pLeft;
|
|
+ Expr *pRight = pExpr->pRight;
|
|
testcase( pExpr->op==TK_EQ );
|
|
testcase( pExpr->op==TK_NE );
|
|
testcase( pExpr->op==TK_LT );
|
|
testcase( pExpr->op==TK_LE );
|
|
testcase( pExpr->op==TK_GT );
|
|
testcase( pExpr->op==TK_GE );
|
|
- if( (pExpr->pLeft->op==TK_COLUMN && IsVirtual(pExpr->pLeft->y.pTab))
|
|
- || (pExpr->pRight->op==TK_COLUMN && IsVirtual(pExpr->pRight->y.pTab))
|
|
+ /* The y.pTab=0 assignment in wherecode.c always happens after the
|
|
+ ** impliesNotNullRow() test */
|
|
+ if( (pLeft->op==TK_COLUMN && ALWAYS(pLeft->y.pTab!=0)
|
|
+ && IsVirtual(pLeft->y.pTab))
|
|
+ || (pRight->op==TK_COLUMN && ALWAYS(pRight->y.pTab!=0)
|
|
+ && IsVirtual(pRight->y.pTab))
|
|
){
|
|
- return WRC_Prune;
|
|
+ return WRC_Prune;
|
|
}
|
|
+ }
|
|
default:
|
|
return WRC_Continue;
|
|
}
|
|
@@ -102339,15 +105052,14 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ExprImpliesNonNullRow(Expr *p, int iTab){
|
|
Walker w;
|
|
- p = sqlite3ExprSkipCollate(p);
|
|
- while( p ){
|
|
- if( p->op==TK_NOTNULL ){
|
|
- p = p->pLeft;
|
|
- }else if( p->op==TK_AND ){
|
|
+ p = sqlite3ExprSkipCollateAndLikely(p);
|
|
+ if( p==0 ) return 0;
|
|
+ if( p->op==TK_NOTNULL ){
|
|
+ p = p->pLeft;
|
|
+ }else{
|
|
+ while( p->op==TK_AND ){
|
|
if( sqlite3ExprImpliesNonNullRow(p->pLeft, iTab) ) return 1;
|
|
p = p->pRight;
|
|
- }else{
|
|
- break;
|
|
}
|
|
}
|
|
w.xExprCallback = impliesNotNullRow;
|
|
@@ -102379,7 +105091,7 @@
|
|
static int exprIdxCover(Walker *pWalker, Expr *pExpr){
|
|
if( pExpr->op==TK_COLUMN
|
|
&& pExpr->iTable==pWalker->u.pIdxCover->iCur
|
|
- && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
|
|
+ && sqlite3TableColumnToIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
|
|
){
|
|
pWalker->eCode = 1;
|
|
return WRC_Abort;
|
|
@@ -102430,12 +105142,13 @@
|
|
** Count the number of references to columns.
|
|
*/
|
|
static int exprSrcCount(Walker *pWalker, Expr *pExpr){
|
|
- /* The NEVER() on the second term is because sqlite3FunctionUsesThisSrc()
|
|
- ** is always called before sqlite3ExprAnalyzeAggregates() and so the
|
|
- ** TK_COLUMNs have not yet been converted into TK_AGG_COLUMN. If
|
|
- ** sqlite3FunctionUsesThisSrc() is used differently in the future, the
|
|
- ** NEVER() will need to be removed. */
|
|
- if( pExpr->op==TK_COLUMN || NEVER(pExpr->op==TK_AGG_COLUMN) ){
|
|
+ /* There was once a NEVER() on the second term on the grounds that
|
|
+ ** sqlite3FunctionUsesThisSrc() was always called before
|
|
+ ** sqlite3ExprAnalyzeAggregates() and so the TK_COLUMNs have not yet
|
|
+ ** been converted into TK_AGG_COLUMN. But this is no longer true due
|
|
+ ** to window functions - sqlite3WindowRewrite() may now indirectly call
|
|
+ ** FunctionUsesThisSrc() when creating a new sub-select. */
|
|
+ if( pExpr->op==TK_COLUMN || pExpr->op==TK_AGG_COLUMN ){
|
|
int i;
|
|
struct SrcCount *p = pWalker->u.pSrcCount;
|
|
SrcList *pSrc = p->pSrc;
|
|
@@ -102445,7 +105158,10 @@
|
|
}
|
|
if( i<nSrc ){
|
|
p->nThis++;
|
|
- }else{
|
|
+ }else if( nSrc==0 || pExpr->iTable<pSrc->a[0].iCursor ){
|
|
+ /* In a well-formed parse tree (no name resolution errors),
|
|
+ ** TK_COLUMN nodes with smaller Expr.iTable values are in an
|
|
+ ** outer context. Those are the only ones to count as "other" */
|
|
p->nOther++;
|
|
}
|
|
}
|
|
@@ -102462,13 +105178,19 @@
|
|
Walker w;
|
|
struct SrcCount cnt;
|
|
assert( pExpr->op==TK_AGG_FUNCTION );
|
|
+ memset(&w, 0, sizeof(w));
|
|
w.xExprCallback = exprSrcCount;
|
|
- w.xSelectCallback = 0;
|
|
+ w.xSelectCallback = sqlite3SelectWalkNoop;
|
|
w.u.pSrcCount = &cnt;
|
|
cnt.pSrc = pSrcList;
|
|
cnt.nThis = 0;
|
|
cnt.nOther = 0;
|
|
sqlite3WalkExprList(&w, pExpr->x.pList);
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ sqlite3WalkExpr(&w, pExpr->y.pWin->pFilter);
|
|
+ }
|
|
+#endif
|
|
return cnt.nThis>0 || cnt.nOther==0;
|
|
}
|
|
|
|
@@ -102635,15 +105357,6 @@
|
|
}
|
|
return WRC_Continue;
|
|
}
|
|
-static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
|
|
- UNUSED_PARAMETER(pSelect);
|
|
- pWalker->walkerDepth++;
|
|
- return WRC_Continue;
|
|
-}
|
|
-static void analyzeAggregatesInSelectEnd(Walker *pWalker, Select *pSelect){
|
|
- UNUSED_PARAMETER(pSelect);
|
|
- pWalker->walkerDepth--;
|
|
-}
|
|
|
|
/*
|
|
** Analyze the pExpr expression looking for aggregate functions and
|
|
@@ -102657,8 +105370,8 @@
|
|
SQLITE_PRIVATE void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
|
|
Walker w;
|
|
w.xExprCallback = analyzeAggregate;
|
|
- w.xSelectCallback = analyzeAggregatesInSelect;
|
|
- w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
|
|
+ w.xSelectCallback = sqlite3WalkerDepthIncrease;
|
|
+ w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
|
|
w.walkerDepth = 0;
|
|
w.u.pNC = pNC;
|
|
w.pParse = 0;
|
|
@@ -102697,8 +105410,11 @@
|
|
** purpose.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
|
|
- if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
|
- pParse->aTempReg[pParse->nTempReg++] = iReg;
|
|
+ if( iReg ){
|
|
+ sqlite3VdbeReleaseRegisters(pParse, iReg, 1, 0, 0);
|
|
+ if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
|
+ pParse->aTempReg[pParse->nTempReg++] = iReg;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -102724,6 +105440,7 @@
|
|
sqlite3ReleaseTempReg(pParse, iReg);
|
|
return;
|
|
}
|
|
+ sqlite3VdbeReleaseRegisters(pParse, iReg, nReg, 0, 0);
|
|
if( nReg>pParse->nRangeReg ){
|
|
pParse->nRangeReg = nReg;
|
|
pParse->iRangeReg = iReg;
|
|
@@ -102732,6 +105449,11 @@
|
|
|
|
/*
|
|
** Mark all temporary registers as being unavailable for reuse.
|
|
+**
|
|
+** Always invoke this procedure after coding a subroutine or co-routine
|
|
+** that might be invoked from other parts of the code, to ensure that
|
|
+** the sub/co-routine does not use registers in common with the code that
|
|
+** invokes the sub/co-routine.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ClearTempRegCache(Parse *pParse){
|
|
pParse->nTempReg = 0;
|
|
@@ -102796,9 +105518,8 @@
|
|
static int isAlterableTable(Parse *pParse, Table *pTab){
|
|
if( 0==sqlite3StrNICmp(pTab->zName, "sqlite_", 7)
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
- || ( (pTab->tabFlags & TF_Shadow)
|
|
- && (pParse->db->flags & SQLITE_Defensive)
|
|
- && pParse->db->nVdbeExec==0
|
|
+ || ( (pTab->tabFlags & TF_Shadow)!=0
|
|
+ && sqlite3ReadOnlyShadowTables(pParse->db)
|
|
)
|
|
#endif
|
|
){
|
|
@@ -102889,7 +105610,10 @@
|
|
/* Check that a table or index named 'zName' does not already exist
|
|
** in database iDb. If so, this is an error.
|
|
*/
|
|
- if( sqlite3FindTable(db, zName, zDb) || sqlite3FindIndex(db, zName, zDb) ){
|
|
+ if( sqlite3FindTable(db, zName, zDb)
|
|
+ || sqlite3FindIndex(db, zName, zDb)
|
|
+ || sqlite3IsShadowTableOf(db, pTab, zName)
|
|
+ ){
|
|
sqlite3ErrorMsg(pParse,
|
|
"there is already another table or index with this name: %s", zName);
|
|
goto exit_rename_table;
|
|
@@ -102901,8 +105625,8 @@
|
|
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
|
|
goto exit_rename_table;
|
|
}
|
|
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){ goto
|
|
- exit_rename_table;
|
|
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse,zName,"table",zName) ){
|
|
+ goto exit_rename_table;
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_VIEW
|
|
@@ -103021,6 +105745,22 @@
|
|
db->mDbFlags = savedDbFlags;
|
|
}
|
|
|
|
+/*
|
|
+** Write code that will raise an error if the table described by
|
|
+** zDb and zTab is not empty.
|
|
+*/
|
|
+static void sqlite3ErrorIfNotEmpty(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ const char *zDb, /* Schema holding the table */
|
|
+ const char *zTab, /* Table to check for empty */
|
|
+ const char *zErr /* Error message text */
|
|
+){
|
|
+ sqlite3NestedParse(pParse,
|
|
+ "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"",
|
|
+ zErr, zDb, zTab
|
|
+ );
|
|
+}
|
|
+
|
|
/*
|
|
** This function is called after an "ALTER TABLE ... ADD" statement
|
|
** has been parsed. Argument pColDef contains the text of the new
|
|
@@ -103063,14 +105803,6 @@
|
|
}
|
|
#endif
|
|
|
|
- /* If the default value for the new column was specified with a
|
|
- ** literal NULL, then set pDflt to 0. This simplifies checking
|
|
- ** for an SQL NULL default below.
|
|
- */
|
|
- assert( pDflt==0 || pDflt->op==TK_SPAN );
|
|
- if( pDflt && pDflt->pLeft->op==TK_NULL ){
|
|
- pDflt = 0;
|
|
- }
|
|
|
|
/* Check that the new column is not specified as PRIMARY KEY or UNIQUE.
|
|
** If there is a NOT NULL constraint, then the default value for the
|
|
@@ -103081,39 +105813,52 @@
|
|
return;
|
|
}
|
|
if( pNew->pIndex ){
|
|
- sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column");
|
|
- return;
|
|
- }
|
|
- if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
|
|
- sqlite3ErrorMsg(pParse,
|
|
- "Cannot add a REFERENCES column with non-NULL default value");
|
|
- return;
|
|
- }
|
|
- if( pCol->notNull && !pDflt ){
|
|
- sqlite3ErrorMsg(pParse,
|
|
- "Cannot add a NOT NULL column with default value NULL");
|
|
+ sqlite3ErrorMsg(pParse,
|
|
+ "Cannot add a UNIQUE column");
|
|
return;
|
|
}
|
|
-
|
|
- /* Ensure the default expression is something that sqlite3ValueFromExpr()
|
|
- ** can handle (i.e. not CURRENT_TIME etc.)
|
|
- */
|
|
- if( pDflt ){
|
|
- sqlite3_value *pVal = 0;
|
|
- int rc;
|
|
- rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
|
|
- assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
|
- if( rc!=SQLITE_OK ){
|
|
- assert( db->mallocFailed == 1 );
|
|
- return;
|
|
+ if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){
|
|
+ /* If the default value for the new column was specified with a
|
|
+ ** literal NULL, then set pDflt to 0. This simplifies checking
|
|
+ ** for an SQL NULL default below.
|
|
+ */
|
|
+ assert( pDflt==0 || pDflt->op==TK_SPAN );
|
|
+ if( pDflt && pDflt->pLeft->op==TK_NULL ){
|
|
+ pDflt = 0;
|
|
}
|
|
- if( !pVal ){
|
|
- sqlite3ErrorMsg(pParse, "Cannot add a column with non-constant default");
|
|
- return;
|
|
+ if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){
|
|
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
|
|
+ "Cannot add a REFERENCES column with non-NULL default value");
|
|
+ }
|
|
+ if( pCol->notNull && !pDflt ){
|
|
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
|
|
+ "Cannot add a NOT NULL column with default value NULL");
|
|
}
|
|
- sqlite3ValueFree(pVal);
|
|
+
|
|
+
|
|
+ /* Ensure the default expression is something that sqlite3ValueFromExpr()
|
|
+ ** can handle (i.e. not CURRENT_TIME etc.)
|
|
+ */
|
|
+ if( pDflt ){
|
|
+ sqlite3_value *pVal = 0;
|
|
+ int rc;
|
|
+ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_BLOB, &pVal);
|
|
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
|
|
+ if( rc!=SQLITE_OK ){
|
|
+ assert( db->mallocFailed == 1 );
|
|
+ return;
|
|
+ }
|
|
+ if( !pVal ){
|
|
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab,
|
|
+ "Cannot add a column with non-constant default");
|
|
+ }
|
|
+ sqlite3ValueFree(pVal);
|
|
+ }
|
|
+ }else if( pCol->colFlags & COLFLAG_STORED ){
|
|
+ sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column");
|
|
}
|
|
|
|
+
|
|
/* Modify the CREATE TABLE statement. */
|
|
zCol = sqlite3DbStrNDup(db, (char*)pColDef->z, pColDef->n);
|
|
if( zCol ){
|
|
@@ -103200,6 +105945,7 @@
|
|
goto exit_begin_add_column;
|
|
}
|
|
|
|
+ sqlite3MayAbort(pParse);
|
|
assert( pTab->addColOffset>0 );
|
|
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
|
|
|
@@ -103228,6 +105974,7 @@
|
|
for(i=0; i<pNew->nCol; i++){
|
|
Column *pCol = &pNew->aCol[i];
|
|
pCol->zName = sqlite3DbStrDup(db, pCol->zName);
|
|
+ pCol->hName = sqlite3StrIHash(pCol->zName);
|
|
pCol->zColl = 0;
|
|
pCol->pDflt = 0;
|
|
}
|
|
@@ -103456,12 +106203,14 @@
|
|
RenameToken *pNew;
|
|
assert( pPtr || pParse->db->mallocFailed );
|
|
renameTokenCheckAll(pParse, pPtr);
|
|
- pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
|
|
- if( pNew ){
|
|
- pNew->p = pPtr;
|
|
- pNew->t = *pToken;
|
|
- pNew->pNext = pParse->pRename;
|
|
- pParse->pRename = pNew;
|
|
+ if( ALWAYS(pParse->eParseMode!=PARSE_MODE_UNMAP) ){
|
|
+ pNew = sqlite3DbMallocZero(pParse->db, sizeof(RenameToken));
|
|
+ if( pNew ){
|
|
+ pNew->p = pPtr;
|
|
+ pNew->t = *pToken;
|
|
+ pNew->pNext = pParse->pRename;
|
|
+ pParse->pRename = pNew;
|
|
+ }
|
|
}
|
|
|
|
return pPtr;
|
|
@@ -103492,17 +106241,54 @@
|
|
return WRC_Continue;
|
|
}
|
|
|
|
+/*
|
|
+** Iterate through the Select objects that are part of WITH clauses attached
|
|
+** to select statement pSelect.
|
|
+*/
|
|
+static void renameWalkWith(Walker *pWalker, Select *pSelect){
|
|
+ With *pWith = pSelect->pWith;
|
|
+ if( pWith ){
|
|
+ int i;
|
|
+ for(i=0; i<pWith->nCte; i++){
|
|
+ Select *p = pWith->a[i].pSelect;
|
|
+ NameContext sNC;
|
|
+ memset(&sNC, 0, sizeof(sNC));
|
|
+ sNC.pParse = pWalker->pParse;
|
|
+ sqlite3SelectPrep(sNC.pParse, p, &sNC);
|
|
+ sqlite3WalkSelect(pWalker, p);
|
|
+ sqlite3RenameExprlistUnmap(pWalker->pParse, pWith->a[i].pCols);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+** Unmap all tokens in the IdList object passed as the second argument.
|
|
+*/
|
|
+static void unmapColumnIdlistNames(
|
|
+ Parse *pParse,
|
|
+ IdList *pIdList
|
|
+){
|
|
+ if( pIdList ){
|
|
+ int ii;
|
|
+ for(ii=0; ii<pIdList->nId; ii++){
|
|
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pIdList->a[ii].zName);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Walker callback used by sqlite3RenameExprUnmap().
|
|
*/
|
|
static int renameUnmapSelectCb(Walker *pWalker, Select *p){
|
|
Parse *pParse = pWalker->pParse;
|
|
int i;
|
|
+ if( pParse->nErr ) return WRC_Abort;
|
|
+ if( NEVER(p->selFlags & SF_View) ) return WRC_Prune;
|
|
if( ALWAYS(p->pEList) ){
|
|
ExprList *pList = p->pEList;
|
|
for(i=0; i<pList->nExpr; i++){
|
|
- if( pList->a[i].zName ){
|
|
- sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zName);
|
|
+ if( pList->a[i].zEName && pList->a[i].eEName==ENAME_NAME ){
|
|
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pList->a[i].zEName);
|
|
}
|
|
}
|
|
}
|
|
@@ -103510,8 +106296,12 @@
|
|
SrcList *pSrc = p->pSrc;
|
|
for(i=0; i<pSrc->nSrc; i++){
|
|
sqlite3RenameTokenRemap(pParse, 0, (void*)pSrc->a[i].zName);
|
|
+ if( sqlite3WalkExpr(pWalker, pSrc->a[i].pOn) ) return WRC_Abort;
|
|
+ unmapColumnIdlistNames(pParse, pSrc->a[i].pUsing);
|
|
}
|
|
}
|
|
+
|
|
+ renameWalkWith(pWalker, p);
|
|
return WRC_Continue;
|
|
}
|
|
|
|
@@ -103519,12 +106309,15 @@
|
|
** Remove all nodes that are part of expression pExpr from the rename list.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3RenameExprUnmap(Parse *pParse, Expr *pExpr){
|
|
+ u8 eMode = pParse->eParseMode;
|
|
Walker sWalker;
|
|
memset(&sWalker, 0, sizeof(Walker));
|
|
sWalker.pParse = pParse;
|
|
sWalker.xExprCallback = renameUnmapExprCb;
|
|
sWalker.xSelectCallback = renameUnmapSelectCb;
|
|
+ pParse->eParseMode = PARSE_MODE_UNMAP;
|
|
sqlite3WalkExpr(&sWalker, pExpr);
|
|
+ pParse->eParseMode = eMode;
|
|
}
|
|
|
|
/*
|
|
@@ -103540,7 +106333,9 @@
|
|
sWalker.xExprCallback = renameUnmapExprCb;
|
|
sqlite3WalkExprList(&sWalker, pEList);
|
|
for(i=0; i<pEList->nExpr; i++){
|
|
- sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zName);
|
|
+ if( ALWAYS(pEList->a[i].eEName==ENAME_NAME) ){
|
|
+ sqlite3RenameTokenRemap(pParse, 0, (void*)pEList->a[i].zEName);
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -103578,30 +106373,13 @@
|
|
}
|
|
}
|
|
|
|
-/*
|
|
-** Iterate through the Select objects that are part of WITH clauses attached
|
|
-** to select statement pSelect.
|
|
-*/
|
|
-static void renameWalkWith(Walker *pWalker, Select *pSelect){
|
|
- if( pSelect->pWith ){
|
|
- int i;
|
|
- for(i=0; i<pSelect->pWith->nCte; i++){
|
|
- Select *p = pSelect->pWith->a[i].pSelect;
|
|
- NameContext sNC;
|
|
- memset(&sNC, 0, sizeof(sNC));
|
|
- sNC.pParse = pWalker->pParse;
|
|
- sqlite3SelectPrep(sNC.pParse, p, &sNC);
|
|
- sqlite3WalkSelect(pWalker, p);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
/*
|
|
** This is a Walker select callback. It does nothing. It is only required
|
|
** because without a dummy callback, sqlite3WalkExpr() and similar do not
|
|
** descend into sub-select statements.
|
|
*/
|
|
static int renameColumnSelectCb(Walker *pWalker, Select *p){
|
|
+ if( p->selFlags & SF_View ) return WRC_Prune;
|
|
renameWalkWith(pWalker, p);
|
|
return WRC_Continue;
|
|
}
|
|
@@ -103695,8 +106473,11 @@
|
|
if( pEList ){
|
|
int i;
|
|
for(i=0; i<pEList->nExpr; i++){
|
|
- char *zName = pEList->a[i].zName;
|
|
- if( 0==sqlite3_stricmp(zName, zOld) ){
|
|
+ char *zName = pEList->a[i].zEName;
|
|
+ if( ALWAYS(pEList->a[i].eEName==ENAME_NAME)
|
|
+ && ALWAYS(zName!=0)
|
|
+ && 0==sqlite3_stricmp(zName, zOld)
|
|
+ ){
|
|
renameTokenFind(pParse, pCtx, (void*)zName);
|
|
}
|
|
}
|
|
@@ -103725,6 +106506,7 @@
|
|
}
|
|
}
|
|
|
|
+
|
|
/*
|
|
** Parse the SQL statement zSql using Parse object (*p). The Parse object
|
|
** is initialized by this function before it is used.
|
|
@@ -103732,7 +106514,6 @@
|
|
static int renameParseSql(
|
|
Parse *p, /* Memory to use for Parse object */
|
|
const char *zDb, /* Name of schema SQL belongs to */
|
|
- int bTable, /* 1 -> RENAME TABLE, 0 -> RENAME COLUMN */
|
|
sqlite3 *db, /* Database handle */
|
|
const char *zSql, /* SQL to parse */
|
|
int bTemp /* True if SQL is from temp schema */
|
|
@@ -103746,7 +106527,7 @@
|
|
** occurs and the parse does not result in a new table, index or
|
|
** trigger object, the database must be corrupt. */
|
|
memset(p, 0, sizeof(Parse));
|
|
- p->eParseMode = (bTable ? PARSE_MODE_RENAME_TABLE : PARSE_MODE_RENAME_COLUMN);
|
|
+ p->eParseMode = PARSE_MODE_RENAME;
|
|
p->db = db;
|
|
p->nQueryLoop = 1;
|
|
rc = sqlite3RunParser(p, zSql, &zErr);
|
|
@@ -104053,7 +106834,7 @@
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
db->xAuth = 0;
|
|
#endif
|
|
- rc = renameParseSql(&sParse, zDb, 0, db, zSql, bTemp);
|
|
+ rc = renameParseSql(&sParse, zDb, db, zSql, bTemp);
|
|
|
|
/* Find tokens that need to be replaced. */
|
|
memset(&sWalker, 0, sizeof(Walker));
|
|
@@ -104067,8 +106848,9 @@
|
|
if( sParse.pNewTable ){
|
|
Select *pSelect = sParse.pNewTable->pSelect;
|
|
if( pSelect ){
|
|
+ pSelect->selFlags &= ~SF_View;
|
|
sParse.rc = SQLITE_OK;
|
|
- sqlite3SelectPrep(&sParse, sParse.pNewTable->pSelect, 0);
|
|
+ sqlite3SelectPrep(&sParse, pSelect, 0);
|
|
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3WalkSelect(&sWalker, pSelect);
|
|
@@ -104095,6 +106877,11 @@
|
|
sqlite3WalkExprList(&sWalker, pIdx->aColExpr);
|
|
}
|
|
}
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ for(i=0; i<sParse.pNewTable->nCol; i++){
|
|
+ sqlite3WalkExpr(&sWalker, sParse.pNewTable->aCol[i].pDflt);
|
|
+ }
|
|
+#endif
|
|
|
|
for(pFKey=sParse.pNewTable->pFKey; pFKey; pFKey=pFKey->pNextFrom){
|
|
for(i=0; i<pFKey->nCol; i++){
|
|
@@ -104180,6 +106967,7 @@
|
|
int i;
|
|
RenameCtx *p = pWalker->u.pRename;
|
|
SrcList *pSrc = pSelect->pSrc;
|
|
+ if( pSelect->selFlags & SF_View ) return WRC_Prune;
|
|
if( pSrc==0 ){
|
|
assert( pWalker->pParse->db->mallocFailed );
|
|
return WRC_Abort;
|
|
@@ -104250,7 +107038,7 @@
|
|
sWalker.xSelectCallback = renameTableSelectCb;
|
|
sWalker.u.pRename = &sCtx;
|
|
|
|
- rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
|
|
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
|
|
|
|
if( rc==SQLITE_OK ){
|
|
int isLegacy = (db->flags & SQLITE_LegacyAlter);
|
|
@@ -104259,13 +107047,19 @@
|
|
|
|
if( pTab->pSelect ){
|
|
if( isLegacy==0 ){
|
|
+ Select *pSelect = pTab->pSelect;
|
|
NameContext sNC;
|
|
memset(&sNC, 0, sizeof(sNC));
|
|
sNC.pParse = &sParse;
|
|
|
|
+ assert( pSelect->selFlags & SF_View );
|
|
+ pSelect->selFlags &= ~SF_View;
|
|
sqlite3SelectPrep(&sParse, pTab->pSelect, &sNC);
|
|
- if( sParse.nErr ) rc = sParse.rc;
|
|
- sqlite3WalkSelect(&sWalker, pTab->pSelect);
|
|
+ if( sParse.nErr ){
|
|
+ rc = sParse.rc;
|
|
+ }else{
|
|
+ sqlite3WalkSelect(&sWalker, pTab->pSelect);
|
|
+ }
|
|
}
|
|
}else{
|
|
/* Modify any FK definitions to point to the new table. */
|
|
@@ -104386,7 +107180,7 @@
|
|
if( zDb && zInput ){
|
|
int rc;
|
|
Parse sParse;
|
|
- rc = renameParseSql(&sParse, zDb, 1, db, zInput, bTemp);
|
|
+ rc = renameParseSql(&sParse, zDb, db, zInput, bTemp);
|
|
if( rc==SQLITE_OK ){
|
|
if( isLegacy==0 && sParse.pNewTable && sParse.pNewTable->pSelect ){
|
|
NameContext sNC;
|
|
@@ -104463,13 +107257,13 @@
|
|
** is between 3.6.18 and 3.7.8, inclusive, and unless SQLite is compiled
|
|
** with SQLITE_ENABLE_STAT2. The sqlite_stat2 table is deprecated.
|
|
** The sqlite_stat2 table is superseded by sqlite_stat3, which is only
|
|
-** created and used by SQLite versions 3.7.9 and later and with
|
|
+** created and used by SQLite versions 3.7.9 through 3.29.0 when
|
|
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
|
|
-** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
|
|
-** version of sqlite_stat3 and is only available when compiled with
|
|
-** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
|
|
-** not possible to enable both STAT3 and STAT4 at the same time. If they
|
|
-** are both enabled, then STAT4 takes precedence.
|
|
+** is a superset of sqlite_stat2 and is also now deprecated. The
|
|
+** sqlite_stat4 is an enhanced version of sqlite_stat3 and is only
|
|
+** available when compiled with SQLITE_ENABLE_STAT4 and in SQLite
|
|
+** versions 3.8.1 and later. STAT4 is the only variant that is still
|
|
+** supported.
|
|
**
|
|
** For most applications, sqlite_stat1 provides all the statistics required
|
|
** for the query planner to make good choices.
|
|
@@ -104580,17 +107374,11 @@
|
|
|
|
#if defined(SQLITE_ENABLE_STAT4)
|
|
# define IsStat4 1
|
|
-# define IsStat3 0
|
|
-#elif defined(SQLITE_ENABLE_STAT3)
|
|
-# define IsStat4 0
|
|
-# define IsStat3 1
|
|
#else
|
|
# define IsStat4 0
|
|
-# define IsStat3 0
|
|
# undef SQLITE_STAT4_SAMPLES
|
|
# define SQLITE_STAT4_SAMPLES 1
|
|
#endif
|
|
-#define IsStat34 (IsStat3+IsStat4) /* 1 for STAT3 or STAT4. 0 otherwise */
|
|
|
|
/*
|
|
** This routine generates code that opens the sqlite_statN tables.
|
|
@@ -104619,14 +107407,10 @@
|
|
{ "sqlite_stat1", "tbl,idx,stat" },
|
|
#if defined(SQLITE_ENABLE_STAT4)
|
|
{ "sqlite_stat4", "tbl,idx,neq,nlt,ndlt,sample" },
|
|
- { "sqlite_stat3", 0 },
|
|
-#elif defined(SQLITE_ENABLE_STAT3)
|
|
- { "sqlite_stat3", "tbl,idx,neq,nlt,ndlt,sample" },
|
|
- { "sqlite_stat4", 0 },
|
|
#else
|
|
- { "sqlite_stat3", 0 },
|
|
{ "sqlite_stat4", 0 },
|
|
#endif
|
|
+ { "sqlite_stat3", 0 },
|
|
};
|
|
int i;
|
|
sqlite3 *db = pParse->db;
|
|
@@ -104634,6 +107418,11 @@
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
int aRoot[ArraySize(aTable)];
|
|
u8 aCreateTbl[ArraySize(aTable)];
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
|
|
+#else
|
|
+ const int nToOpen = 1;
|
|
+#endif
|
|
|
|
if( v==0 ) return;
|
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
|
@@ -104646,8 +107435,9 @@
|
|
for(i=0; i<ArraySize(aTable); i++){
|
|
const char *zTab = aTable[i].zName;
|
|
Table *pStat;
|
|
+ aCreateTbl[i] = 0;
|
|
if( (pStat = sqlite3FindTable(db, zTab, pDb->zDbSName))==0 ){
|
|
- if( aTable[i].zCols ){
|
|
+ if( i<nToOpen ){
|
|
/* The sqlite_statN table does not exist. Create it. Note that a
|
|
** side-effect of the CREATE TABLE statement is to leave the rootpage
|
|
** of the new table in register pParse->regRoot. This is important
|
|
@@ -104663,7 +107453,6 @@
|
|
** associated with the table zWhere. If zWhere is NULL, delete the
|
|
** entire contents of the table. */
|
|
aRoot[i] = pStat->tnum;
|
|
- aCreateTbl[i] = 0;
|
|
sqlite3TableLock(pParse, iDb, aRoot[i], 1, zTab);
|
|
if( zWhere ){
|
|
sqlite3NestedParse(pParse,
|
|
@@ -104682,7 +107471,7 @@
|
|
}
|
|
|
|
/* Open the sqlite_stat[134] tables for writing. */
|
|
- for(i=0; aTable[i].zCols; i++){
|
|
+ for(i=0; i<nToOpen; i++){
|
|
assert( i<ArraySize(aTable) );
|
|
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
|
|
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
|
|
@@ -104702,12 +107491,12 @@
|
|
** share an instance of the following structure to hold their state
|
|
** information.
|
|
*/
|
|
-typedef struct Stat4Accum Stat4Accum;
|
|
-typedef struct Stat4Sample Stat4Sample;
|
|
-struct Stat4Sample {
|
|
+typedef struct StatAccum StatAccum;
|
|
+typedef struct StatSample StatSample;
|
|
+struct StatSample {
|
|
tRowcnt *anEq; /* sqlite_stat4.nEq */
|
|
tRowcnt *anDLt; /* sqlite_stat4.nDLt */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
tRowcnt *anLt; /* sqlite_stat4.nLt */
|
|
union {
|
|
i64 iRowid; /* Rowid in main table of the key */
|
|
@@ -104719,27 +107508,32 @@
|
|
u32 iHash; /* Tiebreaker hash */
|
|
#endif
|
|
};
|
|
-struct Stat4Accum {
|
|
- tRowcnt nRow; /* Number of rows in the entire table */
|
|
- tRowcnt nPSample; /* How often to do a periodic sample */
|
|
+struct StatAccum {
|
|
+ sqlite3 *db; /* Database connection, for malloc() */
|
|
+ tRowcnt nEst; /* Estimated number of rows */
|
|
+ tRowcnt nRow; /* Number of rows visited so far */
|
|
+ int nLimit; /* Analysis row-scan limit */
|
|
int nCol; /* Number of columns in index + pk/rowid */
|
|
int nKeyCol; /* Number of index columns w/o the pk/rowid */
|
|
+ u8 nSkipAhead; /* Number of times of skip-ahead */
|
|
+ StatSample current; /* Current row as a StatSample */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ tRowcnt nPSample; /* How often to do a periodic sample */
|
|
int mxSample; /* Maximum number of samples to accumulate */
|
|
- Stat4Sample current; /* Current row as a Stat4Sample */
|
|
u32 iPrn; /* Pseudo-random number used for sampling */
|
|
- Stat4Sample *aBest; /* Array of nCol best samples */
|
|
+ StatSample *aBest; /* Array of nCol best samples */
|
|
int iMin; /* Index in a[] of entry with minimum score */
|
|
int nSample; /* Current number of samples */
|
|
int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
|
|
int iGet; /* Index of current sample accessed by stat_get() */
|
|
- Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
|
|
- sqlite3 *db; /* Database connection, for malloc() */
|
|
+ StatSample *a; /* Array of mxSample StatSample objects */
|
|
+#endif
|
|
};
|
|
|
|
-/* Reclaim memory used by a Stat4Sample
|
|
+/* Reclaim memory used by a StatSample
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-static void sampleClear(sqlite3 *db, Stat4Sample *p){
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+static void sampleClear(sqlite3 *db, StatSample *p){
|
|
assert( db!=0 );
|
|
if( p->nRowid ){
|
|
sqlite3DbFree(db, p->u.aRowid);
|
|
@@ -104750,8 +107544,8 @@
|
|
|
|
/* Initialize the BLOB value of a ROWID
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-static void sampleSetRowid(sqlite3 *db, Stat4Sample *p, int n, const u8 *pData){
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+static void sampleSetRowid(sqlite3 *db, StatSample *p, int n, const u8 *pData){
|
|
assert( db!=0 );
|
|
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
|
|
p->u.aRowid = sqlite3DbMallocRawNN(db, n);
|
|
@@ -104766,8 +107560,8 @@
|
|
|
|
/* Initialize the INTEGER value of a ROWID.
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-static void sampleSetRowidInt64(sqlite3 *db, Stat4Sample *p, i64 iRowid){
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+static void sampleSetRowidInt64(sqlite3 *db, StatSample *p, i64 iRowid){
|
|
assert( db!=0 );
|
|
if( p->nRowid ) sqlite3DbFree(db, p->u.aRowid);
|
|
p->nRowid = 0;
|
|
@@ -104779,8 +107573,8 @@
|
|
/*
|
|
** Copy the contents of object (*pFrom) into (*pTo).
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+static void sampleCopy(StatAccum *p, StatSample *pTo, StatSample *pFrom){
|
|
pTo->isPSample = pFrom->isPSample;
|
|
pTo->iCol = pFrom->iCol;
|
|
pTo->iHash = pFrom->iHash;
|
|
@@ -104796,40 +107590,41 @@
|
|
#endif
|
|
|
|
/*
|
|
-** Reclaim all memory of a Stat4Accum structure.
|
|
+** Reclaim all memory of a StatAccum structure.
|
|
*/
|
|
-static void stat4Destructor(void *pOld){
|
|
- Stat4Accum *p = (Stat4Accum*)pOld;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- int i;
|
|
- for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
|
|
- for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
|
|
- sampleClear(p->db, &p->current);
|
|
+static void statAccumDestructor(void *pOld){
|
|
+ StatAccum *p = (StatAccum*)pOld;
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( p->mxSample ){
|
|
+ int i;
|
|
+ for(i=0; i<p->nCol; i++) sampleClear(p->db, p->aBest+i);
|
|
+ for(i=0; i<p->mxSample; i++) sampleClear(p->db, p->a+i);
|
|
+ sampleClear(p->db, &p->current);
|
|
+ }
|
|
#endif
|
|
sqlite3DbFree(p->db, p);
|
|
}
|
|
|
|
/*
|
|
-** Implementation of the stat_init(N,K,C) SQL function. The three parameters
|
|
+** Implementation of the stat_init(N,K,C,L) SQL function. The four parameters
|
|
** are:
|
|
** N: The number of columns in the index including the rowid/pk (note 1)
|
|
** K: The number of columns in the index excluding the rowid/pk.
|
|
-** C: The number of rows in the index (note 2)
|
|
+** C: Estimated number of rows in the index
|
|
+** L: A limit on the number of rows to scan, or 0 for no-limit
|
|
**
|
|
** Note 1: In the special case of the covering index that implements a
|
|
** WITHOUT ROWID table, N is the number of PRIMARY KEY columns, not the
|
|
** total number of columns in the table.
|
|
**
|
|
-** Note 2: C is only used for STAT3 and STAT4.
|
|
-**
|
|
** For indexes on ordinary rowid tables, N==K+1. But for indexes on
|
|
** WITHOUT ROWID tables, N=K+P where P is the number of columns in the
|
|
** PRIMARY KEY of the table. The covering index that implements the
|
|
** original WITHOUT ROWID table as N==K as a special case.
|
|
**
|
|
-** This routine allocates the Stat4Accum object in heap memory. The return
|
|
-** value is a pointer to the Stat4Accum object. The datatype of the
|
|
-** return value is BLOB, but it is really just a pointer to the Stat4Accum
|
|
+** This routine allocates the StatAccum object in heap memory. The return
|
|
+** value is a pointer to the StatAccum object. The datatype of the
|
|
+** return value is BLOB, but it is really just a pointer to the StatAccum
|
|
** object.
|
|
*/
|
|
static void statInit(
|
|
@@ -104837,14 +107632,15 @@
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
- Stat4Accum *p;
|
|
+ StatAccum *p;
|
|
int nCol; /* Number of columns in index being sampled */
|
|
int nKeyCol; /* Number of key columns */
|
|
int nColUp; /* nCol rounded up for alignment */
|
|
int n; /* Bytes of space to allocate */
|
|
- sqlite3 *db; /* Database connection */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- int mxSample = SQLITE_STAT4_SAMPLES;
|
|
+ sqlite3 *db = sqlite3_context_db_handle(context); /* Database connection */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ /* Maximum number of samples. 0 if STAT4 data is not collected */
|
|
+ int mxSample = OptimizationEnabled(db,SQLITE_Stat4) ?SQLITE_STAT4_SAMPLES :0;
|
|
#endif
|
|
|
|
/* Decode the three function arguments */
|
|
@@ -104856,16 +107652,17 @@
|
|
assert( nKeyCol<=nCol );
|
|
assert( nKeyCol>0 );
|
|
|
|
- /* Allocate the space required for the Stat4Accum object */
|
|
+ /* Allocate the space required for the StatAccum object */
|
|
n = sizeof(*p)
|
|
- + sizeof(tRowcnt)*nColUp /* Stat4Accum.anEq */
|
|
- + sizeof(tRowcnt)*nColUp /* Stat4Accum.anDLt */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- + sizeof(tRowcnt)*nColUp /* Stat4Accum.anLt */
|
|
- + sizeof(Stat4Sample)*(nCol+mxSample) /* Stat4Accum.aBest[], a[] */
|
|
- + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample)
|
|
-#endif
|
|
- ;
|
|
+ + sizeof(tRowcnt)*nColUp /* StatAccum.anEq */
|
|
+ + sizeof(tRowcnt)*nColUp; /* StatAccum.anDLt */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( mxSample ){
|
|
+ n += sizeof(tRowcnt)*nColUp /* StatAccum.anLt */
|
|
+ + sizeof(StatSample)*(nCol+mxSample) /* StatAccum.aBest[], a[] */
|
|
+ + sizeof(tRowcnt)*3*nColUp*(nCol+mxSample);
|
|
+ }
|
|
+#endif
|
|
db = sqlite3_context_db_handle(context);
|
|
p = sqlite3DbMallocZero(db, n);
|
|
if( p==0 ){
|
|
@@ -104874,25 +107671,28 @@
|
|
}
|
|
|
|
p->db = db;
|
|
+ p->nEst = sqlite3_value_int64(argv[2]);
|
|
p->nRow = 0;
|
|
+ p->nLimit = sqlite3_value_int64(argv[3]);
|
|
p->nCol = nCol;
|
|
p->nKeyCol = nKeyCol;
|
|
+ p->nSkipAhead = 0;
|
|
p->current.anDLt = (tRowcnt*)&p[1];
|
|
p->current.anEq = &p->current.anDLt[nColUp];
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- {
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ p->mxSample = p->nLimit==0 ? mxSample : 0;
|
|
+ if( mxSample ){
|
|
u8 *pSpace; /* Allocated space not yet assigned */
|
|
int i; /* Used to iterate through p->aSample[] */
|
|
|
|
p->iGet = -1;
|
|
- p->mxSample = mxSample;
|
|
- p->nPSample = (tRowcnt)(sqlite3_value_int64(argv[2])/(mxSample/3+1) + 1);
|
|
+ p->nPSample = (tRowcnt)(p->nEst/(mxSample/3+1) + 1);
|
|
p->current.anLt = &p->current.anEq[nColUp];
|
|
p->iPrn = 0x689e962d*(u32)nCol ^ 0xd0944565*(u32)sqlite3_value_int(argv[2]);
|
|
|
|
- /* Set up the Stat4Accum.a[] and aBest[] arrays */
|
|
- p->a = (struct Stat4Sample*)&p->current.anLt[nColUp];
|
|
+ /* Set up the StatAccum.a[] and aBest[] arrays */
|
|
+ p->a = (struct StatSample*)&p->current.anLt[nColUp];
|
|
p->aBest = &p->a[mxSample];
|
|
pSpace = (u8*)(&p->a[mxSample+nCol]);
|
|
for(i=0; i<(mxSample+nCol); i++){
|
|
@@ -104912,10 +107712,10 @@
|
|
** only the pointer (the 2nd parameter) matters. The size of the object
|
|
** (given by the 3rd parameter) is never used and can be any positive
|
|
** value. */
|
|
- sqlite3_result_blob(context, p, sizeof(*p), stat4Destructor);
|
|
+ sqlite3_result_blob(context, p, sizeof(*p), statAccumDestructor);
|
|
}
|
|
static const FuncDef statInitFuncdef = {
|
|
- 2+IsStat34, /* nArg */
|
|
+ 4, /* nArg */
|
|
SQLITE_UTF8, /* funcFlags */
|
|
0, /* pUserData */
|
|
0, /* pNext */
|
|
@@ -104939,9 +107739,9 @@
|
|
** the anEq[] array from pSample->anEq[pSample->iCol+1] onwards are valid.
|
|
*/
|
|
static int sampleIsBetterPost(
|
|
- Stat4Accum *pAccum,
|
|
- Stat4Sample *pNew,
|
|
- Stat4Sample *pOld
|
|
+ StatAccum *pAccum,
|
|
+ StatSample *pNew,
|
|
+ StatSample *pOld
|
|
){
|
|
int nCol = pAccum->nCol;
|
|
int i;
|
|
@@ -104955,7 +107755,7 @@
|
|
}
|
|
#endif
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Return true if pNew is to be preferred over pOld.
|
|
**
|
|
@@ -104963,9 +107763,9 @@
|
|
** the anEq[] array from pSample->anEq[pSample->iCol] onwards are valid.
|
|
*/
|
|
static int sampleIsBetter(
|
|
- Stat4Accum *pAccum,
|
|
- Stat4Sample *pNew,
|
|
- Stat4Sample *pOld
|
|
+ StatAccum *pAccum,
|
|
+ StatSample *pNew,
|
|
+ StatSample *pOld
|
|
){
|
|
tRowcnt nEqNew = pNew->anEq[pNew->iCol];
|
|
tRowcnt nEqOld = pOld->anEq[pOld->iCol];
|
|
@@ -104974,37 +107774,32 @@
|
|
assert( IsStat4 || (pNew->iCol==0 && pOld->iCol==0) );
|
|
|
|
if( (nEqNew>nEqOld) ) return 1;
|
|
-#ifdef SQLITE_ENABLE_STAT4
|
|
if( nEqNew==nEqOld ){
|
|
if( pNew->iCol<pOld->iCol ) return 1;
|
|
return (pNew->iCol==pOld->iCol && sampleIsBetterPost(pAccum, pNew, pOld));
|
|
}
|
|
return 0;
|
|
-#else
|
|
- return (nEqNew==nEqOld && pNew->iHash>pOld->iHash);
|
|
-#endif
|
|
}
|
|
|
|
/*
|
|
** Copy the contents of sample *pNew into the p->a[] array. If necessary,
|
|
** remove the least desirable sample from p->a[] to make room.
|
|
*/
|
|
-static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
|
|
- Stat4Sample *pSample = 0;
|
|
+static void sampleInsert(StatAccum *p, StatSample *pNew, int nEqZero){
|
|
+ StatSample *pSample = 0;
|
|
int i;
|
|
|
|
assert( IsStat4 || nEqZero==0 );
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT4
|
|
- /* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
|
|
- ** values in the anEq[] array of any sample in Stat4Accum.a[]. In
|
|
+ /* StatAccum.nMaxEqZero is set to the maximum number of leading 0
|
|
+ ** values in the anEq[] array of any sample in StatAccum.a[]. In
|
|
** other words, if nMaxEqZero is n, then it is guaranteed that there
|
|
- ** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
|
|
+ ** are no samples with StatSample.anEq[m]==0 for (m>=n). */
|
|
if( nEqZero>p->nMaxEqZero ){
|
|
p->nMaxEqZero = nEqZero;
|
|
}
|
|
if( pNew->isPSample==0 ){
|
|
- Stat4Sample *pUpgrade = 0;
|
|
+ StatSample *pUpgrade = 0;
|
|
assert( pNew->anEq[pNew->iCol]>0 );
|
|
|
|
/* This sample is being added because the prefix that ends in column
|
|
@@ -105013,7 +107808,7 @@
|
|
** this one. Instead, upgrade the priority of the highest priority
|
|
** existing sample that shares this prefix. */
|
|
for(i=p->nSample-1; i>=0; i--){
|
|
- Stat4Sample *pOld = &p->a[i];
|
|
+ StatSample *pOld = &p->a[i];
|
|
if( pOld->anEq[pNew->iCol]==0 ){
|
|
if( pOld->isPSample ) return;
|
|
assert( pOld->iCol>pNew->iCol );
|
|
@@ -105029,11 +107824,10 @@
|
|
goto find_new_min;
|
|
}
|
|
}
|
|
-#endif
|
|
|
|
/* If necessary, remove sample iMin to make room for the new sample. */
|
|
if( p->nSample>=p->mxSample ){
|
|
- Stat4Sample *pMin = &p->a[p->iMin];
|
|
+ StatSample *pMin = &p->a[p->iMin];
|
|
tRowcnt *anEq = pMin->anEq;
|
|
tRowcnt *anLt = pMin->anLt;
|
|
tRowcnt *anDLt = pMin->anDLt;
|
|
@@ -105050,10 +107844,8 @@
|
|
/* The "rows less-than" for the rowid column must be greater than that
|
|
** for the last sample in the p->a[] array. Otherwise, the samples would
|
|
** be out of order. */
|
|
-#ifdef SQLITE_ENABLE_STAT4
|
|
assert( p->nSample==0
|
|
|| pNew->anLt[p->nCol-1] > p->a[p->nSample-1].anLt[p->nCol-1] );
|
|
-#endif
|
|
|
|
/* Insert the new sample */
|
|
pSample = &p->a[p->nSample];
|
|
@@ -105063,9 +107855,7 @@
|
|
/* Zero the first nEqZero entries in the anEq[] array. */
|
|
memset(pSample->anEq, 0, sizeof(tRowcnt)*nEqZero);
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT4
|
|
- find_new_min:
|
|
-#endif
|
|
+find_new_min:
|
|
if( p->nSample>=p->mxSample ){
|
|
int iMin = -1;
|
|
for(i=0; i<p->mxSample; i++){
|
|
@@ -105078,22 +107868,22 @@
|
|
p->iMin = iMin;
|
|
}
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Field iChng of the index being scanned has changed. So at this point
|
|
** p->current contains a sample that reflects the previous row of the
|
|
** index. The value of anEq[iChng] and subsequent anEq[] elements are
|
|
** correct at this point.
|
|
*/
|
|
-static void samplePushPrevious(Stat4Accum *p, int iChng){
|
|
-#ifdef SQLITE_ENABLE_STAT4
|
|
+static void samplePushPrevious(StatAccum *p, int iChng){
|
|
int i;
|
|
|
|
/* Check if any samples from the aBest[] array should be pushed
|
|
** into IndexSample.a[] at this point. */
|
|
for(i=(p->nCol-2); i>=iChng; i--){
|
|
- Stat4Sample *pBest = &p->aBest[i];
|
|
+ StatSample *pBest = &p->aBest[i];
|
|
pBest->anEq[i] = p->current.anEq[i];
|
|
if( p->nSample<p->mxSample || sampleIsBetter(p, pBest, &p->a[p->iMin]) ){
|
|
sampleInsert(p, pBest, i);
|
|
@@ -105117,50 +107907,27 @@
|
|
}
|
|
p->nMaxEqZero = iChng;
|
|
}
|
|
-#endif
|
|
-
|
|
-#if defined(SQLITE_ENABLE_STAT3) && !defined(SQLITE_ENABLE_STAT4)
|
|
- if( iChng==0 ){
|
|
- tRowcnt nLt = p->current.anLt[0];
|
|
- tRowcnt nEq = p->current.anEq[0];
|
|
-
|
|
- /* Check if this is to be a periodic sample. If so, add it. */
|
|
- if( (nLt/p->nPSample)!=(nLt+nEq)/p->nPSample ){
|
|
- p->current.isPSample = 1;
|
|
- sampleInsert(p, &p->current, 0);
|
|
- p->current.isPSample = 0;
|
|
- }else
|
|
-
|
|
- /* Or if it is a non-periodic sample. Add it in this case too. */
|
|
- if( p->nSample<p->mxSample
|
|
- || sampleIsBetter(p, &p->current, &p->a[p->iMin])
|
|
- ){
|
|
- sampleInsert(p, &p->current, 0);
|
|
- }
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- UNUSED_PARAMETER( p );
|
|
- UNUSED_PARAMETER( iChng );
|
|
-#endif
|
|
}
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
/*
|
|
** Implementation of the stat_push SQL function: stat_push(P,C,R)
|
|
** Arguments:
|
|
**
|
|
-** P Pointer to the Stat4Accum object created by stat_init()
|
|
+** P Pointer to the StatAccum object created by stat_init()
|
|
** C Index of left-most column to differ from previous row
|
|
** R Rowid for the current row. Might be a key record for
|
|
** WITHOUT ROWID tables.
|
|
**
|
|
-** This SQL function always returns NULL. It's purpose it to accumulate
|
|
-** statistical data and/or samples in the Stat4Accum object about the
|
|
-** index being analyzed. The stat_get() SQL function will later be used to
|
|
-** extract relevant information for constructing the sqlite_statN tables.
|
|
+** The purpose of this routine is to collect statistical data and/or
|
|
+** samples from the index being analyzed into the StatAccum object.
|
|
+** The stat_get() SQL function will be used afterwards to
|
|
+** retrieve the information gathered.
|
|
**
|
|
-** The R parameter is only used for STAT3 and STAT4
|
|
+** This SQL function usually returns NULL, but might return an integer
|
|
+** if it wants the byte-code to do special processing.
|
|
+**
|
|
+** The R parameter is only used for STAT4
|
|
*/
|
|
static void statPush(
|
|
sqlite3_context *context,
|
|
@@ -105170,7 +107937,7 @@
|
|
int i;
|
|
|
|
/* The three function arguments */
|
|
- Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
|
|
+ StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
|
|
int iChng = sqlite3_value_int(argv[1]);
|
|
|
|
UNUSED_PARAMETER( argc );
|
|
@@ -105183,7 +107950,9 @@
|
|
for(i=0; i<p->nCol; i++) p->current.anEq[i] = 1;
|
|
}else{
|
|
/* Second and subsequent calls get processed here */
|
|
- samplePushPrevious(p, iChng);
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( p->mxSample ) samplePushPrevious(p, iChng);
|
|
+#endif
|
|
|
|
/* Update anDLt[], anLt[] and anEq[] to reflect the values that apply
|
|
** to the current row of the index. */
|
|
@@ -105192,27 +107961,26 @@
|
|
}
|
|
for(i=iChng; i<p->nCol; i++){
|
|
p->current.anDLt[i]++;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- p->current.anLt[i] += p->current.anEq[i];
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( p->mxSample ) p->current.anLt[i] += p->current.anEq[i];
|
|
#endif
|
|
p->current.anEq[i] = 1;
|
|
}
|
|
}
|
|
- p->nRow++;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
|
|
- sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
|
|
- }else{
|
|
- sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
|
|
- sqlite3_value_blob(argv[2]));
|
|
- }
|
|
- p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
|
|
-#endif
|
|
|
|
+ p->nRow++;
|
|
#ifdef SQLITE_ENABLE_STAT4
|
|
- {
|
|
- tRowcnt nLt = p->current.anLt[p->nCol-1];
|
|
+ if( p->mxSample ){
|
|
+ tRowcnt nLt;
|
|
+ if( sqlite3_value_type(argv[2])==SQLITE_INTEGER ){
|
|
+ sampleSetRowidInt64(p->db, &p->current, sqlite3_value_int64(argv[2]));
|
|
+ }else{
|
|
+ sampleSetRowid(p->db, &p->current, sqlite3_value_bytes(argv[2]),
|
|
+ sqlite3_value_blob(argv[2]));
|
|
+ }
|
|
+ p->current.iHash = p->iPrn = p->iPrn*1103515245 + 12345;
|
|
|
|
+ nLt = p->current.anLt[p->nCol-1];
|
|
/* Check if this is to be a periodic sample. If so, add it. */
|
|
if( (nLt/p->nPSample)!=(nLt+1)/p->nPSample ){
|
|
p->current.isPSample = 1;
|
|
@@ -105228,11 +107996,16 @@
|
|
sampleCopy(p, &p->aBest[i], &p->current);
|
|
}
|
|
}
|
|
- }
|
|
+ }else
|
|
#endif
|
|
+ if( p->nLimit && p->nRow>(tRowcnt)p->nLimit*(p->nSkipAhead+1) ){
|
|
+ p->nSkipAhead++;
|
|
+ sqlite3_result_int(context, p->current.anDLt[0]>0);
|
|
+ }
|
|
}
|
|
+
|
|
static const FuncDef statPushFuncdef = {
|
|
- 2+IsStat34, /* nArg */
|
|
+ 2+IsStat4, /* nArg */
|
|
SQLITE_UTF8, /* funcFlags */
|
|
0, /* pUserData */
|
|
0, /* pNext */
|
|
@@ -105252,18 +108025,18 @@
|
|
/*
|
|
** Implementation of the stat_get(P,J) SQL function. This routine is
|
|
** used to query statistical information that has been gathered into
|
|
-** the Stat4Accum object by prior calls to stat_push(). The P parameter
|
|
-** has type BLOB but it is really just a pointer to the Stat4Accum object.
|
|
+** the StatAccum object by prior calls to stat_push(). The P parameter
|
|
+** has type BLOB but it is really just a pointer to the StatAccum object.
|
|
** The content to returned is determined by the parameter J
|
|
** which is one of the STAT_GET_xxxx values defined above.
|
|
**
|
|
** The stat_get(P,J) function is not available to generic SQL. It is
|
|
** inserted as part of a manually constructed bytecode program. (See
|
|
** the callStatGet() routine below.) It is guaranteed that the P
|
|
-** parameter will always be a poiner to a Stat4Accum object, never a
|
|
+** parameter will always be a pointer to a StatAccum object, never a
|
|
** NULL.
|
|
**
|
|
-** If neither STAT3 nor STAT4 are enabled, then J is always
|
|
+** If STAT4 is not enabled, then J is always
|
|
** STAT_GET_STAT1 and is hence omitted and this routine becomes
|
|
** a one-parameter function, stat_get(P), that always returns the
|
|
** stat1 table entry information.
|
|
@@ -105273,15 +108046,16 @@
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
- Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- /* STAT3 and STAT4 have a parameter on this routine. */
|
|
+ StatAccum *p = (StatAccum*)sqlite3_value_blob(argv[0]);
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ /* STAT4 has a parameter on this routine. */
|
|
int eCall = sqlite3_value_int(argv[1]);
|
|
assert( argc==2 );
|
|
assert( eCall==STAT_GET_STAT1 || eCall==STAT_GET_NEQ
|
|
|| eCall==STAT_GET_ROWID || eCall==STAT_GET_NLT
|
|
|| eCall==STAT_GET_NDLT
|
|
);
|
|
+ assert( eCall==STAT_GET_STAT1 || p->mxSample );
|
|
if( eCall==STAT_GET_STAT1 )
|
|
#else
|
|
assert( argc==1 );
|
|
@@ -105294,7 +108068,7 @@
|
|
** the index. The first integer in the list is the total number of
|
|
** entries in the index. There is one additional integer in the list
|
|
** for each indexed column. This additional integer is an estimate of
|
|
- ** the number of rows matched by a stabbing query on the index using
|
|
+ ** the number of rows matched by a equality query on the index using
|
|
** a key with the corresponding number of fields. In other words,
|
|
** if the index is on columns (a,b) and the sqlite_stat1 value is
|
|
** "100 10 2", then SQLite estimates that:
|
|
@@ -105317,7 +108091,8 @@
|
|
return;
|
|
}
|
|
|
|
- sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
|
|
+ sqlite3_snprintf(24, zRet, "%llu",
|
|
+ p->nSkipAhead ? (u64)p->nEst : (u64)p->nRow);
|
|
z = zRet + sqlite3Strlen30(zRet);
|
|
for(i=0; i<p->nKeyCol; i++){
|
|
u64 nDistinct = p->current.anDLt[i] + 1;
|
|
@@ -105330,14 +108105,14 @@
|
|
|
|
sqlite3_result_text(context, zRet, -1, sqlite3_free);
|
|
}
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
else if( eCall==STAT_GET_ROWID ){
|
|
if( p->iGet<0 ){
|
|
samplePushPrevious(p, 0);
|
|
p->iGet = 0;
|
|
}
|
|
if( p->iGet<p->nSample ){
|
|
- Stat4Sample *pS = p->a + p->iGet;
|
|
+ StatSample *pS = p->a + p->iGet;
|
|
if( pS->nRowid==0 ){
|
|
sqlite3_result_int64(context, pS->u.iRowid);
|
|
}else{
|
|
@@ -105359,9 +108134,7 @@
|
|
}
|
|
}
|
|
|
|
- if( IsStat3 ){
|
|
- sqlite3_result_int64(context, (i64)aCnt[0]);
|
|
- }else{
|
|
+ {
|
|
char *zRet = sqlite3MallocZero(p->nCol * 25);
|
|
if( zRet==0 ){
|
|
sqlite3_result_error_nomem(context);
|
|
@@ -105378,13 +108151,13 @@
|
|
}
|
|
}
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
#ifndef SQLITE_DEBUG
|
|
UNUSED_PARAMETER( argc );
|
|
#endif
|
|
}
|
|
static const FuncDef statGetFuncdef = {
|
|
- 1+IsStat34, /* nArg */
|
|
+ 1+IsStat4, /* nArg */
|
|
SQLITE_UTF8, /* funcFlags */
|
|
0, /* pUserData */
|
|
0, /* pNext */
|
|
@@ -105395,18 +108168,17 @@
|
|
{0}
|
|
};
|
|
|
|
-static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
|
|
- assert( regOut!=regStat4 && regOut!=regStat4+1 );
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
|
|
+static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ sqlite3VdbeAddOp2(pParse->pVdbe, OP_Integer, iParam, regStat+1);
|
|
#elif SQLITE_DEBUG
|
|
assert( iParam==STAT_GET_STAT1 );
|
|
#else
|
|
UNUSED_PARAMETER( iParam );
|
|
#endif
|
|
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4, regOut,
|
|
- (char*)&statGetFuncdef, P4_FUNCDEF);
|
|
- sqlite3VdbeChangeP5(v, 1 + IsStat34);
|
|
+ assert( regOut!=regStat && regOut!=regStat+1 );
|
|
+ sqlite3VdbeAddFunctionCall(pParse, 0, regStat, regOut, 1+IsStat4,
|
|
+ &statGetFuncdef, 0);
|
|
}
|
|
|
|
/*
|
|
@@ -105431,12 +108203,11 @@
|
|
int iDb; /* Index of database containing pTab */
|
|
u8 needTableCnt = 1; /* True to count the table */
|
|
int regNewRowid = iMem++; /* Rowid for the inserted record */
|
|
- int regStat4 = iMem++; /* Register to hold Stat4Accum object */
|
|
+ int regStat = iMem++; /* Register to hold StatAccum object */
|
|
int regChng = iMem++; /* Index of changed index field */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
int regRowid = iMem++; /* Rowid argument passed to stat_push() */
|
|
-#endif
|
|
int regTemp = iMem++; /* Temporary use register */
|
|
+ int regTemp2 = iMem++; /* Second temporary use register */
|
|
int regTabname = iMem++; /* Register containing table name */
|
|
int regIdxname = iMem++; /* Register containing index name */
|
|
int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */
|
|
@@ -105564,19 +108335,27 @@
|
|
** (1) the number of columns in the index including the rowid
|
|
** (or for a WITHOUT ROWID table, the number of PK columns),
|
|
** (2) the number of columns in the key without the rowid/pk
|
|
- ** (3) the number of rows in the index,
|
|
- **
|
|
- **
|
|
- ** The third argument is only used for STAT3 and STAT4
|
|
+ ** (3) estimated number of rows in the index,
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regStat4+3);
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat+1);
|
|
+ assert( regRowid==regStat+2 );
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regRowid);
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( OptimizationEnabled(db, SQLITE_Stat4) ){
|
|
+ sqlite3VdbeAddOp2(v, OP_Count, iIdxCur, regTemp);
|
|
+ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
|
|
+ VdbeCoverage(v);
|
|
+ }else
|
|
#endif
|
|
- sqlite3VdbeAddOp2(v, OP_Integer, nCol, regStat4+1);
|
|
- sqlite3VdbeAddOp2(v, OP_Integer, pIdx->nKeyCol, regStat4+2);
|
|
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regStat4+1, regStat4,
|
|
- (char*)&statInitFuncdef, P4_FUNCDEF);
|
|
- sqlite3VdbeChangeP5(v, 2+IsStat34);
|
|
+ {
|
|
+ addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
|
|
+ VdbeCoverage(v);
|
|
+ sqlite3VdbeAddOp3(v, OP_Count, iIdxCur, regTemp, 1);
|
|
+ }
|
|
+ assert( regTemp2==regStat+4 );
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer, db->nAnalysisLimit, regTemp2);
|
|
+ sqlite3VdbeAddFunctionCall(pParse, 0, regStat+1, regStat, 4,
|
|
+ &statInitFuncdef, 0);
|
|
|
|
/* Implementation of the following:
|
|
**
|
|
@@ -105586,8 +108365,6 @@
|
|
** goto next_push_0;
|
|
**
|
|
*/
|
|
- addrRewind = sqlite3VdbeAddOp1(v, OP_Rewind, iIdxCur);
|
|
- VdbeCoverage(v);
|
|
sqlite3VdbeAddOp2(v, OP_Integer, 0, regChng);
|
|
addrNextRow = sqlite3VdbeCurrentAddr(v);
|
|
|
|
@@ -105620,6 +108397,7 @@
|
|
char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
|
|
sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
|
|
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
|
|
+ VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
|
|
aGotoChng[i] =
|
|
sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
|
|
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
|
|
@@ -105640,6 +108418,7 @@
|
|
for(i=0; i<nColTest; i++){
|
|
sqlite3VdbeJumpHere(v, aGotoChng[i]);
|
|
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
|
|
+ VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
|
|
}
|
|
sqlite3VdbeResolveLabel(v, endDistinctTest);
|
|
sqlite3DbFree(db, aGotoChng);
|
|
@@ -105647,37 +108426,52 @@
|
|
|
|
/*
|
|
** chng_addr_N:
|
|
- ** regRowid = idx(rowid) // STAT34 only
|
|
- ** stat_push(P, regChng, regRowid) // 3rd parameter STAT34 only
|
|
+ ** regRowid = idx(rowid) // STAT4 only
|
|
+ ** stat_push(P, regChng, regRowid) // 3rd parameter STAT4 only
|
|
** Next csr
|
|
** if !eof(csr) goto next_row;
|
|
*/
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- assert( regRowid==(regStat4+2) );
|
|
- if( HasRowid(pTab) ){
|
|
- sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
|
|
- }else{
|
|
- Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
|
|
- int j, k, regKey;
|
|
- regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
|
- for(j=0; j<pPk->nKeyCol; j++){
|
|
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
|
|
- assert( k>=0 && k<pIdx->nColumn );
|
|
- sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
|
|
- VdbeComment((v, "%s", pTab->aCol[pPk->aiColumn[j]].zName));
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( OptimizationEnabled(db, SQLITE_Stat4) ){
|
|
+ assert( regRowid==(regStat+2) );
|
|
+ if( HasRowid(pTab) ){
|
|
+ sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, regRowid);
|
|
+ }else{
|
|
+ Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
|
|
+ int j, k, regKey;
|
|
+ regKey = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
|
+ for(j=0; j<pPk->nKeyCol; j++){
|
|
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
|
|
+ assert( k>=0 && k<pIdx->nColumn );
|
|
+ sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
|
|
+ VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
|
|
+ }
|
|
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
|
|
+ sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
|
|
}
|
|
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
|
|
- sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
|
|
}
|
|
#endif
|
|
- assert( regChng==(regStat4+1) );
|
|
- sqlite3VdbeAddOp4(v, OP_Function0, 1, regStat4, regTemp,
|
|
- (char*)&statPushFuncdef, P4_FUNCDEF);
|
|
- sqlite3VdbeChangeP5(v, 2+IsStat34);
|
|
- sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
|
|
+ assert( regChng==(regStat+1) );
|
|
+ {
|
|
+ sqlite3VdbeAddFunctionCall(pParse, 1, regStat, regTemp, 2+IsStat4,
|
|
+ &statPushFuncdef, 0);
|
|
+ if( db->nAnalysisLimit ){
|
|
+ int j1, j2, j3;
|
|
+ j1 = sqlite3VdbeAddOp1(v, OP_IsNull, regTemp); VdbeCoverage(v);
|
|
+ j2 = sqlite3VdbeAddOp1(v, OP_If, regTemp); VdbeCoverage(v);
|
|
+ j3 = sqlite3VdbeAddOp4Int(v, OP_SeekGT, iIdxCur, 0, regPrev, 1);
|
|
+ VdbeCoverage(v);
|
|
+ sqlite3VdbeJumpHere(v, j1);
|
|
+ sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
|
|
+ sqlite3VdbeJumpHere(v, j2);
|
|
+ sqlite3VdbeJumpHere(v, j3);
|
|
+ }else{
|
|
+ sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, addrNextRow); VdbeCoverage(v);
|
|
+ }
|
|
+ }
|
|
|
|
/* Add the entry to the stat1 table. */
|
|
- callStatGet(v, regStat4, STAT_GET_STAT1, regStat1);
|
|
+ callStatGet(pParse, regStat, STAT_GET_STAT1, regStat1);
|
|
assert( "BBB"[0]==SQLITE_AFF_TEXT );
|
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, regTabname, 3, regTemp, "BBB", 0);
|
|
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur, regNewRowid);
|
|
@@ -105687,9 +108481,9 @@
|
|
#endif
|
|
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
|
|
|
|
- /* Add the entries to the stat3 or stat4 table. */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- {
|
|
+ /* Add the entries to the stat4 table. */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ if( OptimizationEnabled(db, SQLITE_Stat4) && db->nAnalysisLimit==0 ){
|
|
int regEq = regStat1;
|
|
int regLt = regStat1+1;
|
|
int regDLt = regStat1+2;
|
|
@@ -105703,29 +108497,25 @@
|
|
pParse->nMem = MAX(pParse->nMem, regCol+nCol);
|
|
|
|
addrNext = sqlite3VdbeCurrentAddr(v);
|
|
- callStatGet(v, regStat4, STAT_GET_ROWID, regSampleRowid);
|
|
+ callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid);
|
|
addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid);
|
|
VdbeCoverage(v);
|
|
- callStatGet(v, regStat4, STAT_GET_NEQ, regEq);
|
|
- callStatGet(v, regStat4, STAT_GET_NLT, regLt);
|
|
- callStatGet(v, regStat4, STAT_GET_NDLT, regDLt);
|
|
+ callStatGet(pParse, regStat, STAT_GET_NEQ, regEq);
|
|
+ callStatGet(pParse, regStat, STAT_GET_NLT, regLt);
|
|
+ callStatGet(pParse, regStat, STAT_GET_NDLT, regDLt);
|
|
sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0);
|
|
VdbeCoverage(v);
|
|
-#ifdef SQLITE_ENABLE_STAT3
|
|
- sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, 0, regSample);
|
|
-#else
|
|
for(i=0; i<nCol; i++){
|
|
sqlite3ExprCodeLoadIndexColumn(pParse, pIdx, iTabCur, i, regCol+i);
|
|
}
|
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regCol, nCol, regSample);
|
|
-#endif
|
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp);
|
|
sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid);
|
|
sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid);
|
|
sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */
|
|
sqlite3VdbeJumpHere(v, addrIsNull);
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
/* End of analysis */
|
|
sqlite3VdbeJumpHere(v, addrRewind);
|
|
@@ -105900,7 +108690,7 @@
|
|
int i;
|
|
tRowcnt v;
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( z==0 ) z = "";
|
|
#else
|
|
assert( z!=0 );
|
|
@@ -105911,7 +108701,7 @@
|
|
v = v*10 + c - '0';
|
|
z++;
|
|
}
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( aOut ) aOut[i] = v;
|
|
if( aLog ) aLog[i] = sqlite3LogEst(v);
|
|
#else
|
|
@@ -105922,7 +108712,7 @@
|
|
#endif
|
|
if( *z==' ' ) z++;
|
|
}
|
|
-#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifndef SQLITE_ENABLE_STAT4
|
|
assert( pIndex!=0 ); {
|
|
#else
|
|
if( pIndex ){
|
|
@@ -105933,7 +108723,9 @@
|
|
if( sqlite3_strglob("unordered*", z)==0 ){
|
|
pIndex->bUnordered = 1;
|
|
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
|
|
- pIndex->szIdxRow = sqlite3LogEst(sqlite3Atoi(z+3));
|
|
+ int sz = sqlite3Atoi(z+3);
|
|
+ if( sz<2 ) sz = 2;
|
|
+ pIndex->szIdxRow = sqlite3LogEst(sz);
|
|
}else if( sqlite3_strglob("noskipscan*", z)==0 ){
|
|
pIndex->noSkipScan = 1;
|
|
}
|
|
@@ -105987,7 +108779,7 @@
|
|
if( pIndex ){
|
|
tRowcnt *aiRowEst = 0;
|
|
int nCol = pIndex->nKeyCol+1;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/* Index.aiRowEst may already be set here if there are duplicate
|
|
** sqlite_stat1 entries for this index. In that case just clobber
|
|
** the old data with the new instead of allocating a new array. */
|
|
@@ -106023,7 +108815,7 @@
|
|
** and its contents.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( pIdx->aSample ){
|
|
int j;
|
|
for(j=0; j<pIdx->nSample; j++){
|
|
@@ -106039,10 +108831,10 @@
|
|
#else
|
|
UNUSED_PARAMETER(db);
|
|
UNUSED_PARAMETER(pIdx);
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
}
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Populate the pIdx->aAvgEq[] array based on the samples currently
|
|
** stored in pIdx->aSample[].
|
|
@@ -106120,12 +108912,11 @@
|
|
}
|
|
|
|
/*
|
|
-** Load the content from either the sqlite_stat4 or sqlite_stat3 table
|
|
+** Load the content from either the sqlite_stat4
|
|
** into the relevant Index.aSample[] arrays.
|
|
**
|
|
** Arguments zSql1 and zSql2 must point to SQL statements that return
|
|
-** data equivalent to the following (statements are different for stat3,
|
|
-** see the caller of this function for details):
|
|
+** data equivalent to the following:
|
|
**
|
|
** zSql1: SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx
|
|
** zSql2: SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4
|
|
@@ -106134,7 +108925,6 @@
|
|
*/
|
|
static int loadStatTbl(
|
|
sqlite3 *db, /* Database handle */
|
|
- int bStat3, /* Assume single column records only */
|
|
const char *zSql1, /* SQL statement 1 (see above) */
|
|
const char *zSql2, /* SQL statement 2 (see above) */
|
|
const char *zDb /* Database name (e.g. "main") */
|
|
@@ -106168,17 +108958,13 @@
|
|
if( zIndex==0 ) continue;
|
|
nSample = sqlite3_column_int(pStmt, 1);
|
|
pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
|
|
- assert( pIdx==0 || bStat3 || pIdx->nSample==0 );
|
|
- /* Index.nSample is non-zero at this point if data has already been
|
|
- ** loaded from the stat4 table. In this case ignore stat3 data. */
|
|
- if( pIdx==0 || pIdx->nSample ) continue;
|
|
- if( bStat3==0 ){
|
|
- assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
|
|
- if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
|
|
- nIdxCol = pIdx->nKeyCol;
|
|
- }else{
|
|
- nIdxCol = pIdx->nColumn;
|
|
- }
|
|
+ assert( pIdx==0 || pIdx->nSample==0 );
|
|
+ if( pIdx==0 ) continue;
|
|
+ assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 );
|
|
+ if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){
|
|
+ nIdxCol = pIdx->nKeyCol;
|
|
+ }else{
|
|
+ nIdxCol = pIdx->nColumn;
|
|
}
|
|
pIdx->nSampleCol = nIdxCol;
|
|
nByte = sizeof(IndexSample) * nSample;
|
|
@@ -106220,9 +109006,8 @@
|
|
pIdx = findIndexOrPrimaryKey(db, zIndex, zDb);
|
|
if( pIdx==0 ) continue;
|
|
/* This next condition is true if data has already been loaded from
|
|
- ** the sqlite_stat4 table. In this case ignore stat3 data. */
|
|
+ ** the sqlite_stat4 table. */
|
|
nCol = pIdx->nSampleCol;
|
|
- if( bStat3 && nCol>1 ) continue;
|
|
if( pIdx!=pPrevIdx ){
|
|
initAvgEq(pPrevIdx);
|
|
pPrevIdx = pIdx;
|
|
@@ -106255,7 +109040,7 @@
|
|
}
|
|
|
|
/*
|
|
-** Load content from the sqlite_stat4 and sqlite_stat3 tables into
|
|
+** Load content from the sqlite_stat4 table into
|
|
** the Index.aSample[] arrays of all indices.
|
|
*/
|
|
static int loadStat4(sqlite3 *db, const char *zDb){
|
|
@@ -106263,37 +109048,28 @@
|
|
|
|
assert( db->lookaside.bDisable );
|
|
if( sqlite3FindTable(db, "sqlite_stat4", zDb) ){
|
|
- rc = loadStatTbl(db, 0,
|
|
+ rc = loadStatTbl(db,
|
|
"SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx",
|
|
"SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4",
|
|
zDb
|
|
);
|
|
}
|
|
-
|
|
- if( rc==SQLITE_OK && sqlite3FindTable(db, "sqlite_stat3", zDb) ){
|
|
- rc = loadStatTbl(db, 1,
|
|
- "SELECT idx,count(*) FROM %Q.sqlite_stat3 GROUP BY idx",
|
|
- "SELECT idx,neq,nlt,ndlt,sqlite_record(sample) FROM %Q.sqlite_stat3",
|
|
- zDb
|
|
- );
|
|
- }
|
|
-
|
|
return rc;
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
/*
|
|
-** Load the content of the sqlite_stat1 and sqlite_stat3/4 tables. The
|
|
+** Load the content of the sqlite_stat1 and sqlite_stat4 tables. The
|
|
** contents of sqlite_stat1 are used to populate the Index.aiRowEst[]
|
|
-** arrays. The contents of sqlite_stat3/4 are used to populate the
|
|
+** arrays. The contents of sqlite_stat4 are used to populate the
|
|
** Index.aSample[] arrays.
|
|
**
|
|
** If the sqlite_stat1 table is not present in the database, SQLITE_ERROR
|
|
-** is returned. In this case, even if SQLITE_ENABLE_STAT3/4 was defined
|
|
-** during compilation and the sqlite_stat3/4 table is present, no data is
|
|
+** is returned. In this case, even if SQLITE_ENABLE_STAT4 was defined
|
|
+** during compilation and the sqlite_stat4 table is present, no data is
|
|
** read from it.
|
|
**
|
|
-** If SQLITE_ENABLE_STAT3/4 was defined during compilation and the
|
|
+** If SQLITE_ENABLE_STAT4 was defined during compilation and the
|
|
** sqlite_stat4 table is not present in the database, SQLITE_ERROR is
|
|
** returned. However, in this case, data is read from the sqlite_stat1
|
|
** table (if it is present) before returning.
|
|
@@ -106321,7 +109097,7 @@
|
|
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
|
|
Index *pIdx = sqliteHashData(i);
|
|
pIdx->hasStat1 = 0;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
sqlite3DeleteIndexSamples(db, pIdx);
|
|
pIdx->aSample = 0;
|
|
#endif
|
|
@@ -106349,11 +109125,11 @@
|
|
}
|
|
|
|
/* Load the statistics from the sqlite_stat4 table. */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
if( rc==SQLITE_OK ){
|
|
- db->lookaside.bDisable++;
|
|
+ DisableLookaside;
|
|
rc = loadStat4(db, sInfo.zDatabase);
|
|
- db->lookaside.bDisable--;
|
|
+ EnableLookaside;
|
|
}
|
|
for(i=sqliteHashFirst(&pSchema->idxHash); i; i=sqliteHashNext(i)){
|
|
Index *pIdx = sqliteHashData(i);
|
|
@@ -106420,6 +109196,17 @@
|
|
return rc;
|
|
}
|
|
|
|
+/*
|
|
+** Return true if zName points to a name that may be used to refer to
|
|
+** database iDb attached to handle db.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3DbIsNamed(sqlite3 *db, int iDb, const char *zName){
|
|
+ return (
|
|
+ sqlite3StrICmp(db->aDb[iDb].zDbSName, zName)==0
|
|
+ || (iDb==0 && sqlite3StrICmp("main", zName)==0)
|
|
+ );
|
|
+}
|
|
+
|
|
/*
|
|
** An SQL user-function registered to do the work of an ATTACH statement. The
|
|
** three arguments to the function come directly from an attach statement:
|
|
@@ -106492,9 +109279,8 @@
|
|
goto attach_error;
|
|
}
|
|
for(i=0; i<db->nDb; i++){
|
|
- char *z = db->aDb[i].zDbSName;
|
|
- assert( z && zName );
|
|
- if( sqlite3StrICmp(z, zName)==0 ){
|
|
+ assert( zName );
|
|
+ if( sqlite3DbIsNamed(db, i, zName) ){
|
|
zErrDyn = sqlite3MPrintf(db, "database %s is already in use", zName);
|
|
goto attach_error;
|
|
}
|
|
@@ -106562,43 +109348,7 @@
|
|
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
|
|
rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
-
|
|
-
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( rc==SQLITE_OK ){
|
|
- extern int sqlite3CodecAttach(sqlite3*, int, const void*, int);
|
|
- extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
|
|
- int nKey;
|
|
- char *zKey;
|
|
- int t = sqlite3_value_type(argv[2]);
|
|
- switch( t ){
|
|
- case SQLITE_INTEGER:
|
|
- case SQLITE_FLOAT:
|
|
- zErrDyn = sqlite3DbStrDup(db, "Invalid key value");
|
|
- rc = SQLITE_ERROR;
|
|
- break;
|
|
-
|
|
- case SQLITE_TEXT:
|
|
- case SQLITE_BLOB:
|
|
- nKey = sqlite3_value_bytes(argv[2]);
|
|
- zKey = (char *)sqlite3_value_blob(argv[2]);
|
|
- rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
|
|
- break;
|
|
-
|
|
- case SQLITE_NULL:
|
|
- /* No key specified. Use the key from URI filename, or if none,
|
|
- ** use the key from the main database. */
|
|
- if( sqlite3CodecQueryParameters(db, zName, zPath)==0 ){
|
|
- sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
|
|
- if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
|
|
- rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
|
|
- }
|
|
- }
|
|
- break;
|
|
- }
|
|
- }
|
|
-#endif
|
|
- sqlite3_free( zPath );
|
|
+ sqlite3_free_filename( zPath );
|
|
|
|
/* If the file was opened successfully, read the schema for the new database.
|
|
** If this fails, or if opening the file failed, then close the file and
|
|
@@ -106674,6 +109424,7 @@
|
|
sqlite3 *db = sqlite3_context_db_handle(context);
|
|
int i;
|
|
Db *pDb = 0;
|
|
+ HashElem *pEntry;
|
|
char zErr[128];
|
|
|
|
UNUSED_PARAMETER(NotUsed);
|
|
@@ -106682,7 +109433,7 @@
|
|
for(i=0; i<db->nDb; i++){
|
|
pDb = &db->aDb[i];
|
|
if( pDb->pBt==0 ) continue;
|
|
- if( sqlite3StrICmp(pDb->zDbSName, zName)==0 ) break;
|
|
+ if( sqlite3DbIsNamed(db, i, zName) ) break;
|
|
}
|
|
|
|
if( i>=db->nDb ){
|
|
@@ -106698,6 +109449,18 @@
|
|
goto detach_error;
|
|
}
|
|
|
|
+ /* If any TEMP triggers reference the schema being detached, move those
|
|
+ ** triggers to reference the TEMP schema itself. */
|
|
+ assert( db->aDb[1].pSchema );
|
|
+ pEntry = sqliteHashFirst(&db->aDb[1].pSchema->trigHash);
|
|
+ while( pEntry ){
|
|
+ Trigger *pTrig = (Trigger*)sqliteHashData(pEntry);
|
|
+ if( pTrig->pTabSchema==pDb->pSchema ){
|
|
+ pTrig->pTabSchema = pTrig->pSchema;
|
|
+ }
|
|
+ pEntry = sqliteHashNext(pEntry);
|
|
+ }
|
|
+
|
|
sqlite3BtreeClose(pDb->pBt);
|
|
pDb->pBt = 0;
|
|
pDb->pSchema = 0;
|
|
@@ -106763,11 +109526,8 @@
|
|
|
|
assert( v || db->mallocFailed );
|
|
if( v ){
|
|
- sqlite3VdbeAddOp4(v, OP_Function0, 0, regArgs+3-pFunc->nArg, regArgs+3,
|
|
- (char *)pFunc, P4_FUNCDEF);
|
|
- assert( pFunc->nArg==-1 || (pFunc->nArg&0xff)==pFunc->nArg );
|
|
- sqlite3VdbeChangeP5(v, (u8)(pFunc->nArg));
|
|
-
|
|
+ sqlite3VdbeAddFunctionCall(pParse, 0, regArgs+3-pFunc->nArg, regArgs+3,
|
|
+ pFunc->nArg, pFunc, 0);
|
|
/* Code an OP_Expire. For an ATTACH statement, set P1 to true (expire this
|
|
** statement only). For DETACH, set it to false (expire all existing
|
|
** statements).
|
|
@@ -106842,7 +109602,7 @@
|
|
pFix->pSchema = db->aDb[iDb].pSchema;
|
|
pFix->zType = zType;
|
|
pFix->pName = pName;
|
|
- pFix->bVarOnly = (iDb==1);
|
|
+ pFix->bTemp = (iDb==1);
|
|
}
|
|
|
|
/*
|
|
@@ -106864,22 +109624,24 @@
|
|
SrcList *pList /* The Source list to check and modify */
|
|
){
|
|
int i;
|
|
- const char *zDb;
|
|
struct SrcList_item *pItem;
|
|
+ sqlite3 *db = pFix->pParse->db;
|
|
+ int iDb = sqlite3FindDbName(db, pFix->zDb);
|
|
|
|
if( NEVER(pList==0) ) return 0;
|
|
- zDb = pFix->zDb;
|
|
+
|
|
for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){
|
|
- if( pFix->bVarOnly==0 ){
|
|
- if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){
|
|
+ if( pFix->bTemp==0 ){
|
|
+ if( pItem->zDatabase && iDb!=sqlite3FindDbName(db, pItem->zDatabase) ){
|
|
sqlite3ErrorMsg(pFix->pParse,
|
|
"%s %T cannot reference objects in database %s",
|
|
pFix->zType, pFix->pName, pItem->zDatabase);
|
|
return 1;
|
|
}
|
|
- sqlite3DbFree(pFix->pParse->db, pItem->zDatabase);
|
|
+ sqlite3DbFree(db, pItem->zDatabase);
|
|
pItem->zDatabase = 0;
|
|
pItem->pSchema = pFix->pSchema;
|
|
+ pItem->fg.fromDDL = 1;
|
|
}
|
|
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER)
|
|
if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1;
|
|
@@ -106935,6 +109697,7 @@
|
|
Expr *pExpr /* The expression to be fixed to one database */
|
|
){
|
|
while( pExpr ){
|
|
+ if( !pFix->bTemp ) ExprSetProperty(pExpr, EP_FromDDL);
|
|
if( pExpr->op==TK_VARIABLE ){
|
|
if( pFix->pParse->db->init.busy ){
|
|
pExpr->op = TK_NULL;
|
|
@@ -107087,7 +109850,7 @@
|
|
sqlite3_mutex_enter(db->mutex);
|
|
db->xAuth = (sqlite3_xauth)xAuth;
|
|
db->pAuthArg = pArg;
|
|
- sqlite3ExpirePreparedStatements(db, 0);
|
|
+ if( db->xAuth ) sqlite3ExpirePreparedStatements(db, 1);
|
|
sqlite3_mutex_leave(db->mutex);
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -107597,22 +110360,39 @@
|
|
return 0;
|
|
}
|
|
#endif
|
|
- while(1){
|
|
- for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
|
- int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
|
- if( zDatabase==0 || sqlite3StrICmp(zDatabase, db->aDb[j].zDbSName)==0 ){
|
|
- assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
|
- p = sqlite3HashFind(&db->aDb[j].pSchema->tblHash, zName);
|
|
- if( p ) return p;
|
|
+ if( zDatabase ){
|
|
+ for(i=0; i<db->nDb; i++){
|
|
+ if( sqlite3StrICmp(zDatabase, db->aDb[i].zDbSName)==0 ) break;
|
|
+ }
|
|
+ if( i>=db->nDb ){
|
|
+ /* No match against the official names. But always match "main"
|
|
+ ** to schema 0 as a legacy fallback. */
|
|
+ if( sqlite3StrICmp(zDatabase,"main")==0 ){
|
|
+ i = 0;
|
|
+ }else{
|
|
+ return 0;
|
|
}
|
|
}
|
|
- /* Not found. If the name we were looking for was temp.sqlite_master
|
|
- ** then change the name to sqlite_temp_master and try again. */
|
|
- if( sqlite3StrICmp(zName, MASTER_NAME)!=0 ) break;
|
|
- if( sqlite3_stricmp(zDatabase, db->aDb[1].zDbSName)!=0 ) break;
|
|
- zName = TEMP_MASTER_NAME;
|
|
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
|
|
+ if( p==0 && i==1 && sqlite3StrICmp(zName, MASTER_NAME)==0 ){
|
|
+ /* All temp.sqlite_master to be an alias for sqlite_temp_master */
|
|
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, TEMP_MASTER_NAME);
|
|
+ }
|
|
+ }else{
|
|
+ /* Match against TEMP first */
|
|
+ p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, zName);
|
|
+ if( p ) return p;
|
|
+ /* The main database is second */
|
|
+ p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, zName);
|
|
+ if( p ) return p;
|
|
+ /* Attached databases are in order of attachment */
|
|
+ for(i=2; i<db->nDb; i++){
|
|
+ assert( sqlite3SchemaMutexHeld(db, i, 0) );
|
|
+ p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
|
|
+ if( p ) break;
|
|
+ }
|
|
}
|
|
- return 0;
|
|
+ return p;
|
|
}
|
|
|
|
/*
|
|
@@ -107722,7 +110502,7 @@
|
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
|
Schema *pSchema = db->aDb[j].pSchema;
|
|
assert( pSchema );
|
|
- if( zDb && sqlite3StrICmp(zDb, db->aDb[j].zDbSName) ) continue;
|
|
+ if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
|
|
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
|
p = sqlite3HashFind(&pSchema->idxHash, zName);
|
|
if( p ) break;
|
|
@@ -107741,7 +110521,7 @@
|
|
sqlite3ExprListDelete(db, p->aColExpr);
|
|
sqlite3DbFree(db, p->zColAff);
|
|
if( p->isResized ) sqlite3DbFree(db, (void *)p->azColl);
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
sqlite3_free(p->aiRowEst);
|
|
#endif
|
|
sqlite3DbFree(db, p);
|
|
@@ -107875,6 +110655,7 @@
|
|
assert( pTable!=0 );
|
|
if( (pCol = pTable->aCol)!=0 ){
|
|
for(i=0; i<pTable->nCol; i++, pCol++){
|
|
+ assert( pCol->zName==0 || pCol->hName==sqlite3StrIHash(pCol->zName) );
|
|
sqlite3DbFree(db, pCol->zName);
|
|
sqlite3ExprDelete(db, pCol->pDflt);
|
|
sqlite3DbFree(db, pCol->zColl);
|
|
@@ -108114,13 +110895,41 @@
|
|
** trigger). All names are legal except those that begin with the string
|
|
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
|
|
** is reserved for internal use.
|
|
+**
|
|
+** When parsing the sqlite_master table, this routine also checks to
|
|
+** make sure the "type", "name", and "tbl_name" columns are consistent
|
|
+** with the SQL.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3CheckObjectName(Parse *pParse, const char *zName){
|
|
- if( !pParse->db->init.busy && pParse->nested==0
|
|
- && sqlite3WritableSchema(pParse->db)==0
|
|
- && 0==sqlite3StrNICmp(zName, "sqlite_", 7) ){
|
|
- sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s", zName);
|
|
- return SQLITE_ERROR;
|
|
+SQLITE_PRIVATE int sqlite3CheckObjectName(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ const char *zName, /* Name of the object to check */
|
|
+ const char *zType, /* Type of this object */
|
|
+ const char *zTblName /* Parent table name for triggers and indexes */
|
|
+){
|
|
+ sqlite3 *db = pParse->db;
|
|
+ if( sqlite3WritableSchema(db) || db->init.imposterTable ){
|
|
+ /* Skip these error checks for writable_schema=ON */
|
|
+ return SQLITE_OK;
|
|
+ }
|
|
+ if( db->init.busy ){
|
|
+ if( sqlite3_stricmp(zType, db->init.azInit[0])
|
|
+ || sqlite3_stricmp(zName, db->init.azInit[1])
|
|
+ || sqlite3_stricmp(zTblName, db->init.azInit[2])
|
|
+ ){
|
|
+ if( sqlite3Config.bExtraSchemaChecks ){
|
|
+ sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
+ }
|
|
+ }else{
|
|
+ if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
|
|
+ || (sqlite3ReadOnlyShadowTables(db) && sqlite3ShadowTableName(db, zName))
|
|
+ ){
|
|
+ sqlite3ErrorMsg(pParse, "object name reserved for internal use: %s",
|
|
+ zName);
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
+
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -108135,10 +110944,12 @@
|
|
}
|
|
|
|
/*
|
|
-** Return the column of index pIdx that corresponds to table
|
|
-** column iCol. Return -1 if not found.
|
|
+** Convert an table column number into a index column number. That is,
|
|
+** for the column iCol in the table (as defined by the CREATE TABLE statement)
|
|
+** find the (first) offset of that column in index pIdx. Or return -1
|
|
+** if column iCol is not used in index pIdx.
|
|
*/
|
|
-SQLITE_PRIVATE i16 sqlite3ColumnOfIndex(Index *pIdx, i16 iCol){
|
|
+SQLITE_PRIVATE i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
|
|
int i;
|
|
for(i=0; i<pIdx->nColumn; i++){
|
|
if( iCol==pIdx->aiColumn[i] ) return i;
|
|
@@ -108146,6 +110957,84 @@
|
|
return -1;
|
|
}
|
|
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+/* Convert a storage column number into a table column number.
|
|
+**
|
|
+** The storage column number (0,1,2,....) is the index of the value
|
|
+** as it appears in the record on disk. The true column number
|
|
+** is the index (0,1,2,...) of the column in the CREATE TABLE statement.
|
|
+**
|
|
+** The storage column number is less than the table column number if
|
|
+** and only there are VIRTUAL columns to the left.
|
|
+**
|
|
+** If SQLITE_OMIT_GENERATED_COLUMNS, this routine is a no-op macro.
|
|
+*/
|
|
+SQLITE_PRIVATE i16 sqlite3StorageColumnToTable(Table *pTab, i16 iCol){
|
|
+ if( pTab->tabFlags & TF_HasVirtual ){
|
|
+ int i;
|
|
+ for(i=0; i<=iCol; i++){
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) iCol++;
|
|
+ }
|
|
+ }
|
|
+ return iCol;
|
|
+}
|
|
+#endif
|
|
+
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+/* Convert a table column number into a storage column number.
|
|
+**
|
|
+** The storage column number (0,1,2,....) is the index of the value
|
|
+** as it appears in the record on disk. Or, if the input column is
|
|
+** the N-th virtual column (zero-based) then the storage number is
|
|
+** the number of non-virtual columns in the table plus N.
|
|
+**
|
|
+** The true column number is the index (0,1,2,...) of the column in
|
|
+** the CREATE TABLE statement.
|
|
+**
|
|
+** If the input column is a VIRTUAL column, then it should not appear
|
|
+** in storage. But the value sometimes is cached in registers that
|
|
+** follow the range of registers used to construct storage. This
|
|
+** avoids computing the same VIRTUAL column multiple times, and provides
|
|
+** values for use by OP_Param opcodes in triggers. Hence, if the
|
|
+** input column is a VIRTUAL table, put it after all the other columns.
|
|
+**
|
|
+** In the following, N means "normal column", S means STORED, and
|
|
+** V means VIRTUAL. Suppose the CREATE TABLE has columns like this:
|
|
+**
|
|
+** CREATE TABLE ex(N,S,V,N,S,V,N,S,V);
|
|
+** -- 0 1 2 3 4 5 6 7 8
|
|
+**
|
|
+** Then the mapping from this function is as follows:
|
|
+**
|
|
+** INPUTS: 0 1 2 3 4 5 6 7 8
|
|
+** OUTPUTS: 0 1 6 2 3 7 4 5 8
|
|
+**
|
|
+** So, in other words, this routine shifts all the virtual columns to
|
|
+** the end.
|
|
+**
|
|
+** If SQLITE_OMIT_GENERATED_COLUMNS then there are no virtual columns and
|
|
+** this routine is a no-op macro. If the pTab does not have any virtual
|
|
+** columns, then this routine is no-op that always return iCol. If iCol
|
|
+** is negative (indicating the ROWID column) then this routine return iCol.
|
|
+*/
|
|
+SQLITE_PRIVATE i16 sqlite3TableColumnToStorage(Table *pTab, i16 iCol){
|
|
+ int i;
|
|
+ i16 n;
|
|
+ assert( iCol<pTab->nCol );
|
|
+ if( (pTab->tabFlags & TF_HasVirtual)==0 || iCol<0 ) return iCol;
|
|
+ for(i=0, n=0; i<iCol; i++){
|
|
+ if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) n++;
|
|
+ }
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ){
|
|
+ /* iCol is a virtual column itself */
|
|
+ return pTab->nNVCol + i - n;
|
|
+ }else{
|
|
+ /* iCol is a normal or stored column */
|
|
+ return n;
|
|
+ }
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
** Begin constructing a new table representation in memory. This is
|
|
** the first of several action routines that get called in response
|
|
@@ -108201,7 +111090,7 @@
|
|
}
|
|
pParse->sNameToken = *pName;
|
|
if( zName==0 ) return;
|
|
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
|
+ if( sqlite3CheckObjectName(pParse, zName, isView?"view":"table", zName) ){
|
|
goto begin_table_error;
|
|
}
|
|
if( db->init.iDb==1 ) isTemp = 1;
|
|
@@ -108415,6 +111304,7 @@
|
|
pCol = &p->aCol[p->nCol];
|
|
memset(pCol, 0, sizeof(p->aCol[0]));
|
|
pCol->zName = z;
|
|
+ pCol->hName = sqlite3StrIHash(z);
|
|
sqlite3ColumnPropertiesFromName(p, pCol);
|
|
|
|
if( pType->n==0 ){
|
|
@@ -108436,6 +111326,7 @@
|
|
pCol->colFlags |= COLFLAG_HASTYPE;
|
|
}
|
|
p->nCol++;
|
|
+ p->nNVCol++;
|
|
pParse->constraintName.n = 0;
|
|
}
|
|
|
|
@@ -108580,10 +111471,17 @@
|
|
sqlite3 *db = pParse->db;
|
|
p = pParse->pNewTable;
|
|
if( p!=0 ){
|
|
+ int isInit = db->init.busy && db->init.iDb!=1;
|
|
pCol = &(p->aCol[p->nCol-1]);
|
|
- if( !sqlite3ExprIsConstantOrFunction(pExpr, db->init.busy) ){
|
|
+ if( !sqlite3ExprIsConstantOrFunction(pExpr, isInit) ){
|
|
sqlite3ErrorMsg(pParse, "default value of column [%s] is not constant",
|
|
pCol->zName);
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ }else if( pCol->colFlags & COLFLAG_GENERATED ){
|
|
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pCol->colFlags & COLFLAG_STORED );
|
|
+ sqlite3ErrorMsg(pParse, "cannot use DEFAULT on a generated column");
|
|
+#endif
|
|
}else{
|
|
/* A copy of pExpr is used instead of the original, as pExpr contains
|
|
** tokens that point to volatile memory.
|
|
@@ -108629,6 +111527,21 @@
|
|
}
|
|
}
|
|
|
|
+/*
|
|
+** Tag the given column as being part of the PRIMARY KEY
|
|
+*/
|
|
+static void makeColumnPartOfPrimaryKey(Parse *pParse, Column *pCol){
|
|
+ pCol->colFlags |= COLFLAG_PRIMKEY;
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( pCol->colFlags & COLFLAG_GENERATED ){
|
|
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pCol->colFlags & COLFLAG_STORED );
|
|
+ sqlite3ErrorMsg(pParse,
|
|
+ "generated columns cannot be part of the PRIMARY KEY");
|
|
+ }
|
|
+#endif
|
|
+}
|
|
+
|
|
/*
|
|
** Designate the PRIMARY KEY for the table. pList is a list of names
|
|
** of columns that form the primary key. If pList is NULL, then the
|
|
@@ -108668,7 +111581,7 @@
|
|
if( pList==0 ){
|
|
iCol = pTab->nCol - 1;
|
|
pCol = &pTab->aCol[iCol];
|
|
- pCol->colFlags |= COLFLAG_PRIMKEY;
|
|
+ makeColumnPartOfPrimaryKey(pParse, pCol);
|
|
nTerm = 1;
|
|
}else{
|
|
nTerm = pList->nExpr;
|
|
@@ -108681,7 +111594,7 @@
|
|
for(iCol=0; iCol<pTab->nCol; iCol++){
|
|
if( sqlite3StrICmp(zCName, pTab->aCol[iCol].zName)==0 ){
|
|
pCol = &pTab->aCol[iCol];
|
|
- pCol->colFlags |= COLFLAG_PRIMKEY;
|
|
+ makeColumnPartOfPrimaryKey(pParse, pCol);
|
|
break;
|
|
}
|
|
}
|
|
@@ -108701,7 +111614,8 @@
|
|
pTab->keyConf = (u8)onError;
|
|
assert( autoInc==0 || autoInc==1 );
|
|
pTab->tabFlags |= autoInc*TF_Autoincrement;
|
|
- if( pList ) pParse->iPkSortOrder = pList->a[0].sortOrder;
|
|
+ if( pList ) pParse->iPkSortOrder = pList->a[0].sortFlags;
|
|
+ (void)sqlite3HasExplicitNulls(pParse, pList);
|
|
}else if( autoInc ){
|
|
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
|
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
|
|
@@ -108778,41 +111692,58 @@
|
|
}
|
|
}
|
|
|
|
-/*
|
|
-** This function returns the collation sequence for database native text
|
|
-** encoding identified by the string zName, length nName.
|
|
-**
|
|
-** If the requested collation sequence is not available, or not available
|
|
-** in the database native encoding, the collation factory is invoked to
|
|
-** request it. If the collation factory does not supply such a sequence,
|
|
-** and the sequence is available in another text encoding, then that is
|
|
-** returned instead.
|
|
-**
|
|
-** If no versions of the requested collations sequence are available, or
|
|
-** another error occurs, NULL is returned and an error message written into
|
|
-** pParse.
|
|
-**
|
|
-** This routine is a wrapper around sqlite3FindCollSeq(). This routine
|
|
-** invokes the collation factory if the named collation cannot be found
|
|
-** and generates an error message.
|
|
-**
|
|
-** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
|
|
+/* Change the most recently parsed column to be a GENERATED ALWAYS AS
|
|
+** column.
|
|
*/
|
|
-SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
|
|
- sqlite3 *db = pParse->db;
|
|
- u8 enc = ENC(db);
|
|
- u8 initbusy = db->init.busy;
|
|
- CollSeq *pColl;
|
|
-
|
|
- pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
|
|
- if( !initbusy && (!pColl || !pColl->xCmp) ){
|
|
- pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
|
|
+SQLITE_PRIVATE void sqlite3AddGenerated(Parse *pParse, Expr *pExpr, Token *pType){
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ u8 eType = COLFLAG_VIRTUAL;
|
|
+ Table *pTab = pParse->pNewTable;
|
|
+ Column *pCol;
|
|
+ if( pTab==0 ){
|
|
+ /* generated column in an CREATE TABLE IF NOT EXISTS that already exists */
|
|
+ goto generated_done;
|
|
}
|
|
+ pCol = &(pTab->aCol[pTab->nCol-1]);
|
|
+ if( IN_DECLARE_VTAB ){
|
|
+ sqlite3ErrorMsg(pParse, "virtual tables cannot use computed columns");
|
|
+ goto generated_done;
|
|
+ }
|
|
+ if( pCol->pDflt ) goto generated_error;
|
|
+ if( pType ){
|
|
+ if( pType->n==7 && sqlite3StrNICmp("virtual",pType->z,7)==0 ){
|
|
+ /* no-op */
|
|
+ }else if( pType->n==6 && sqlite3StrNICmp("stored",pType->z,6)==0 ){
|
|
+ eType = COLFLAG_STORED;
|
|
+ }else{
|
|
+ goto generated_error;
|
|
+ }
|
|
+ }
|
|
+ if( eType==COLFLAG_VIRTUAL ) pTab->nNVCol--;
|
|
+ pCol->colFlags |= eType;
|
|
+ assert( TF_HasVirtual==COLFLAG_VIRTUAL );
|
|
+ assert( TF_HasStored==COLFLAG_STORED );
|
|
+ pTab->tabFlags |= eType;
|
|
+ if( pCol->colFlags & COLFLAG_PRIMKEY ){
|
|
+ makeColumnPartOfPrimaryKey(pParse, pCol); /* For the error message */
|
|
+ }
|
|
+ pCol->pDflt = pExpr;
|
|
+ pExpr = 0;
|
|
+ goto generated_done;
|
|
|
|
- return pColl;
|
|
+generated_error:
|
|
+ sqlite3ErrorMsg(pParse, "error in generated column \"%s\"",
|
|
+ pCol->zName);
|
|
+generated_done:
|
|
+ sqlite3ExprDelete(pParse->db, pExpr);
|
|
+#else
|
|
+ /* Throw and error for the GENERATED ALWAYS AS clause if the
|
|
+ ** SQLITE_OMIT_GENERATED_COLUMNS compile-time option is used. */
|
|
+ sqlite3ErrorMsg(pParse, "generated columns not supported");
|
|
+ sqlite3ExprDelete(pParse->db, pExpr);
|
|
+#endif
|
|
}
|
|
|
|
-
|
|
/*
|
|
** Generate code that will increment the schema cookie.
|
|
**
|
|
@@ -109070,15 +112001,24 @@
|
|
** high-order bit of colNotIdxed is always 1. All unindexed columns
|
|
** of the table have a 1.
|
|
**
|
|
+** 2019-10-24: For the purpose of this computation, virtual columns are
|
|
+** not considered to be covered by the index, even if they are in the
|
|
+** index, because we do not trust the logic in whereIndexExprTrans() to be
|
|
+** able to find all instances of a reference to the indexed table column
|
|
+** and convert them into references to the index. Hence we always want
|
|
+** the actual table at hand in order to recompute the virtual column, if
|
|
+** necessary.
|
|
+**
|
|
** The colNotIdxed mask is AND-ed with the SrcList.a[].colUsed mask
|
|
** to determine if the index is covering index.
|
|
*/
|
|
static void recomputeColumnsNotIndexed(Index *pIdx){
|
|
Bitmask m = 0;
|
|
int j;
|
|
+ Table *pTab = pIdx->pTable;
|
|
for(j=pIdx->nColumn-1; j>=0; j--){
|
|
int x = pIdx->aiColumn[j];
|
|
- if( x>=0 ){
|
|
+ if( x>=0 && (pTab->aCol[x].colFlags & COLFLAG_VIRTUAL)==0 ){
|
|
testcase( x==BMS-1 );
|
|
testcase( x==BMS-2 );
|
|
if( x<BMS-1 ) m |= MASKBIT(x);
|
|
@@ -109116,6 +112056,7 @@
|
|
Index *pIdx;
|
|
Index *pPk;
|
|
int nPk;
|
|
+ int nExtra;
|
|
int i, j;
|
|
sqlite3 *db = pParse->db;
|
|
Vdbe *v = pParse->pVdbe;
|
|
@@ -109128,6 +112069,7 @@
|
|
pTab->aCol[i].notNull = OE_Abort;
|
|
}
|
|
}
|
|
+ pTab->tabFlags |= TF_HasNotNull;
|
|
}
|
|
|
|
/* Convert the P3 operand of the OP_CreateBtree opcode from BTREE_INTKEY
|
|
@@ -109151,13 +112093,14 @@
|
|
if( IN_RENAME_OBJECT ){
|
|
sqlite3RenameTokenRemap(pParse, pList->a[0].pExpr, &pTab->iPKey);
|
|
}
|
|
- pList->a[0].sortOrder = pParse->iPkSortOrder;
|
|
+ pList->a[0].sortFlags = pParse->iPkSortOrder;
|
|
assert( pParse->pNewTable==pTab );
|
|
pTab->iPKey = -1;
|
|
sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0,
|
|
SQLITE_IDXTYPE_PRIMARYKEY);
|
|
if( db->mallocFailed || pParse->nErr ) return;
|
|
pPk = sqlite3PrimaryKeyIndex(pTab);
|
|
+ assert( pPk->nKeyCol==1 );
|
|
}else{
|
|
pPk = sqlite3PrimaryKeyIndex(pTab);
|
|
assert( pPk!=0 );
|
|
@@ -109172,6 +112115,8 @@
|
|
pPk->nColumn--;
|
|
}else{
|
|
testcase( hasColumn(pPk->aiColumn, j, pPk->aiColumn[i]) );
|
|
+ pPk->azColl[j] = pPk->azColl[i];
|
|
+ pPk->aSortOrder[j] = pPk->aSortOrder[i];
|
|
pPk->aiColumn[j++] = pPk->aiColumn[i];
|
|
}
|
|
}
|
|
@@ -109180,7 +112125,7 @@
|
|
assert( pPk!=0 );
|
|
pPk->isCovering = 1;
|
|
if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
|
|
- nPk = pPk->nKeyCol;
|
|
+ nPk = pPk->nColumn = pPk->nKeyCol;
|
|
|
|
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
|
|
** table entry. This is only required if currently generating VDBE
|
|
@@ -109230,24 +112175,49 @@
|
|
|
|
/* Add all table columns to the PRIMARY KEY index
|
|
*/
|
|
- if( nPk<pTab->nCol ){
|
|
- if( resizeIndexObject(db, pPk, pTab->nCol) ) return;
|
|
- for(i=0, j=nPk; i<pTab->nCol; i++){
|
|
- if( !hasColumn(pPk->aiColumn, j, i) ){
|
|
- assert( j<pPk->nColumn );
|
|
- pPk->aiColumn[j] = i;
|
|
- pPk->azColl[j] = sqlite3StrBINARY;
|
|
- j++;
|
|
- }
|
|
+ nExtra = 0;
|
|
+ for(i=0; i<pTab->nCol; i++){
|
|
+ if( !hasColumn(pPk->aiColumn, nPk, i)
|
|
+ && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
|
|
+ }
|
|
+ if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
|
|
+ for(i=0, j=nPk; i<pTab->nCol; i++){
|
|
+ if( !hasColumn(pPk->aiColumn, j, i)
|
|
+ && (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
|
|
+ ){
|
|
+ assert( j<pPk->nColumn );
|
|
+ pPk->aiColumn[j] = i;
|
|
+ pPk->azColl[j] = sqlite3StrBINARY;
|
|
+ j++;
|
|
}
|
|
- assert( pPk->nColumn==j );
|
|
- assert( pTab->nCol==j );
|
|
- }else{
|
|
- pPk->nColumn = pTab->nCol;
|
|
}
|
|
+ assert( pPk->nColumn==j );
|
|
+ assert( pTab->nNVCol<=j );
|
|
recomputeColumnsNotIndexed(pPk);
|
|
}
|
|
|
|
+
|
|
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
+/*
|
|
+** Return true if pTab is a virtual table and zName is a shadow table name
|
|
+** for that virtual table.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3IsShadowTableOf(sqlite3 *db, Table *pTab, const char *zName){
|
|
+ int nName; /* Length of zName */
|
|
+ Module *pMod; /* Module for the virtual table */
|
|
+
|
|
+ if( !IsVirtual(pTab) ) return 0;
|
|
+ nName = sqlite3Strlen30(pTab->zName);
|
|
+ if( sqlite3_strnicmp(zName, pTab->zName, nName)!=0 ) return 0;
|
|
+ if( zName[nName]!='_' ) return 0;
|
|
+ pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
|
|
+ if( pMod==0 ) return 0;
|
|
+ if( pMod->pModule->iVersion<3 ) return 0;
|
|
+ if( pMod->pModule->xShadowName==0 ) return 0;
|
|
+ return pMod->pModule->xShadowName(zName+nName+1);
|
|
+}
|
|
+#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
|
+
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
/*
|
|
** Return true if zName is a shadow table name in the current database
|
|
@@ -109256,11 +112226,9 @@
|
|
** zName is temporarily modified while this routine is running, but is
|
|
** restored to its original value prior to this routine returning.
|
|
*/
|
|
-static int isShadowTableName(sqlite3 *db, char *zName){
|
|
+SQLITE_PRIVATE int sqlite3ShadowTableName(sqlite3 *db, const char *zName){
|
|
char *zTail; /* Pointer to the last "_" in zName */
|
|
Table *pTab; /* Table that zName is a shadow of */
|
|
- Module *pMod; /* Module for the virtual table */
|
|
-
|
|
zTail = strrchr(zName, '_');
|
|
if( zTail==0 ) return 0;
|
|
*zTail = 0;
|
|
@@ -109268,16 +112236,37 @@
|
|
*zTail = '_';
|
|
if( pTab==0 ) return 0;
|
|
if( !IsVirtual(pTab) ) return 0;
|
|
- pMod = (Module*)sqlite3HashFind(&db->aModule, pTab->azModuleArg[0]);
|
|
- if( pMod==0 ) return 0;
|
|
- if( pMod->pModule->iVersion<3 ) return 0;
|
|
- if( pMod->pModule->xShadowName==0 ) return 0;
|
|
- return pMod->pModule->xShadowName(zTail+1);
|
|
+ return sqlite3IsShadowTableOf(db, pTab, zName);
|
|
}
|
|
-#else
|
|
-# define isShadowTableName(x,y) 0
|
|
#endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */
|
|
|
|
+
|
|
+#ifdef SQLITE_DEBUG
|
|
+/*
|
|
+** Mark all nodes of an expression as EP_Immutable, indicating that
|
|
+** they should not be changed. Expressions attached to a table or
|
|
+** index definition are tagged this way to help ensure that we do
|
|
+** not pass them into code generator routines by mistake.
|
|
+*/
|
|
+static int markImmutableExprStep(Walker *pWalker, Expr *pExpr){
|
|
+ ExprSetVVAProperty(pExpr, EP_Immutable);
|
|
+ return WRC_Continue;
|
|
+}
|
|
+static void markExprListImmutable(ExprList *pList){
|
|
+ if( pList ){
|
|
+ Walker w;
|
|
+ memset(&w, 0, sizeof(w));
|
|
+ w.xExprCallback = markImmutableExprStep;
|
|
+ w.xSelectCallback = sqlite3SelectWalkNoop;
|
|
+ w.xSelectCallback2 = 0;
|
|
+ sqlite3WalkExprList(&w, pList);
|
|
+ }
|
|
+}
|
|
+#else
|
|
+#define markExprListImmutable(X) /* no-op */
|
|
+#endif /* SQLITE_DEBUG */
|
|
+
|
|
+
|
|
/*
|
|
** This routine is called to report the final ")" that terminates
|
|
** a CREATE TABLE statement.
|
|
@@ -109317,7 +112306,7 @@
|
|
p = pParse->pNewTable;
|
|
if( p==0 ) return;
|
|
|
|
- if( pSelect==0 && isShadowTableName(db, p->zName) ){
|
|
+ if( pSelect==0 && sqlite3ShadowTableName(db, p->zName) ){
|
|
p->tabFlags |= TF_Shadow;
|
|
}
|
|
|
|
@@ -109353,12 +112342,11 @@
|
|
}
|
|
if( (p->tabFlags & TF_HasPrimaryKey)==0 ){
|
|
sqlite3ErrorMsg(pParse, "PRIMARY KEY missing on table %s", p->zName);
|
|
- }else{
|
|
- p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
|
|
- convertToWithoutRowidTable(pParse, p);
|
|
+ return;
|
|
}
|
|
+ p->tabFlags |= TF_WithoutRowid | TF_NoVisibleRowid;
|
|
+ convertToWithoutRowidTable(pParse, p);
|
|
}
|
|
-
|
|
iDb = sqlite3SchemaToIndex(db, p->pSchema);
|
|
|
|
#ifndef SQLITE_OMIT_CHECK
|
|
@@ -109366,8 +112354,47 @@
|
|
*/
|
|
if( p->pCheck ){
|
|
sqlite3ResolveSelfReference(pParse, p, NC_IsCheck, 0, p->pCheck);
|
|
+ if( pParse->nErr ){
|
|
+ /* If errors are seen, delete the CHECK constraints now, else they might
|
|
+ ** actually be used if PRAGMA writable_schema=ON is set. */
|
|
+ sqlite3ExprListDelete(db, p->pCheck);
|
|
+ p->pCheck = 0;
|
|
+ }else{
|
|
+ markExprListImmutable(p->pCheck);
|
|
+ }
|
|
}
|
|
#endif /* !defined(SQLITE_OMIT_CHECK) */
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( p->tabFlags & TF_HasGenerated ){
|
|
+ int ii, nNG = 0;
|
|
+ testcase( p->tabFlags & TF_HasVirtual );
|
|
+ testcase( p->tabFlags & TF_HasStored );
|
|
+ for(ii=0; ii<p->nCol; ii++){
|
|
+ u32 colFlags = p->aCol[ii].colFlags;
|
|
+ if( (colFlags & COLFLAG_GENERATED)!=0 ){
|
|
+ Expr *pX = p->aCol[ii].pDflt;
|
|
+ testcase( colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( colFlags & COLFLAG_STORED );
|
|
+ if( sqlite3ResolveSelfReference(pParse, p, NC_GenCol, pX, 0) ){
|
|
+ /* If there are errors in resolving the expression, change the
|
|
+ ** expression to a NULL. This prevents code generators that operate
|
|
+ ** on the expression from inserting extra parts into the expression
|
|
+ ** tree that have been allocated from lookaside memory, which is
|
|
+ ** illegal in a schema and will lead to errors or heap corruption
|
|
+ ** when the database connection closes. */
|
|
+ sqlite3ExprDelete(db, pX);
|
|
+ p->aCol[ii].pDflt = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
|
|
+ }
|
|
+ }else{
|
|
+ nNG++;
|
|
+ }
|
|
+ }
|
|
+ if( nNG==0 ){
|
|
+ sqlite3ErrorMsg(pParse, "must have at least one non-generated column");
|
|
+ return;
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
|
|
/* Estimate the average row size for the table and for all implied indices */
|
|
estimateTableWidth(p);
|
|
@@ -109441,10 +112468,10 @@
|
|
addrTop = sqlite3VdbeCurrentAddr(v) + 1;
|
|
sqlite3VdbeAddOp3(v, OP_InitCoroutine, regYield, 0, addrTop);
|
|
if( pParse->nErr ) return;
|
|
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect);
|
|
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSelect, SQLITE_AFF_BLOB);
|
|
if( pSelTab==0 ) return;
|
|
assert( p->aCol==0 );
|
|
- p->nCol = pSelTab->nCol;
|
|
+ p->nCol = p->nNVCol = pSelTab->nCol;
|
|
p->aCol = pSelTab->aCol;
|
|
pSelTab->nCol = 0;
|
|
pSelTab->aCol = 0;
|
|
@@ -109517,7 +112544,6 @@
|
|
sqlite3MPrintf(db, "tbl_name='%q' AND type!='trigger'", p->zName));
|
|
}
|
|
|
|
-
|
|
/* Add the table to the in-memory representation of the database.
|
|
*/
|
|
if( db->init.busy ){
|
|
@@ -109588,6 +112614,7 @@
|
|
** allocated rather than point to the input string - which means that
|
|
** they will persist after the current sqlite3_exec() call returns.
|
|
*/
|
|
+ pSelect->selFlags |= SF_View;
|
|
if( IN_RENAME_OBJECT ){
|
|
p->pSelect = pSelect;
|
|
pSelect = 0;
|
|
@@ -109701,17 +112728,20 @@
|
|
n = pParse->nTab;
|
|
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
|
|
pTable->nCol = -1;
|
|
- db->lookaside.bDisable++;
|
|
+ DisableLookaside;
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
xAuth = db->xAuth;
|
|
db->xAuth = 0;
|
|
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
|
|
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
|
|
db->xAuth = xAuth;
|
|
#else
|
|
- pSelTab = sqlite3ResultSetOfSelect(pParse, pSel);
|
|
+ pSelTab = sqlite3ResultSetOfSelect(pParse, pSel, SQLITE_AFF_NONE);
|
|
#endif
|
|
pParse->nTab = n;
|
|
- if( pTable->pCheck ){
|
|
+ if( pSelTab==0 ){
|
|
+ pTable->nCol = 0;
|
|
+ nErr++;
|
|
+ }else if( pTable->pCheck ){
|
|
/* CREATE VIEW name(arglist) AS ...
|
|
** The names of the columns in the table are taken from
|
|
** arglist which is stored in pTable->pCheck. The pCheck field
|
|
@@ -109724,9 +112754,10 @@
|
|
&& pParse->nErr==0
|
|
&& pTable->nCol==pSel->pEList->nExpr
|
|
){
|
|
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel);
|
|
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTable, pSel,
|
|
+ SQLITE_AFF_NONE);
|
|
}
|
|
- }else if( pSelTab ){
|
|
+ }else{
|
|
/* CREATE VIEW name AS... without an argument list. Construct
|
|
** the column names from the SELECT statement that defines the view.
|
|
*/
|
|
@@ -109736,13 +112767,11 @@
|
|
pSelTab->nCol = 0;
|
|
pSelTab->aCol = 0;
|
|
assert( sqlite3SchemaMutexHeld(db, 0, pTable->pSchema) );
|
|
- }else{
|
|
- pTable->nCol = 0;
|
|
- nErr++;
|
|
}
|
|
+ pTable->nNVCol = pTable->nCol;
|
|
sqlite3DeleteTable(db, pSelTab);
|
|
sqlite3SelectDelete(db, pSel);
|
|
- db->lookaside.bDisable--;
|
|
+ EnableLookaside;
|
|
#ifndef SQLITE_OMIT_ALTERTABLE
|
|
pParse->eParseMode = eParseMode;
|
|
#endif
|
|
@@ -109999,6 +113028,37 @@
|
|
sqliteViewResetAll(db, iDb);
|
|
}
|
|
|
|
+/*
|
|
+** Return TRUE if shadow tables should be read-only in the current
|
|
+** context.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3ReadOnlyShadowTables(sqlite3 *db){
|
|
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
+ if( (db->flags & SQLITE_Defensive)!=0
|
|
+ && db->pVtabCtx==0
|
|
+ && db->nVdbeExec==0
|
|
+ ){
|
|
+ return 1;
|
|
+ }
|
|
+#endif
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Return true if it is not allowed to drop the given table
|
|
+*/
|
|
+static int tableMayNotBeDropped(sqlite3 *db, Table *pTab){
|
|
+ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
|
|
+ if( sqlite3StrNICmp(pTab->zName+7, "stat", 4)==0 ) return 0;
|
|
+ if( sqlite3StrNICmp(pTab->zName+7, "parameters", 10)==0 ) return 0;
|
|
+ return 1;
|
|
+ }
|
|
+ if( (pTab->tabFlags & TF_Shadow)!=0 && sqlite3ReadOnlyShadowTables(db) ){
|
|
+ return 1;
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
** This routine is called to do the work of a DROP TABLE statement.
|
|
** pName is the name of the table to be dropped.
|
|
@@ -110068,8 +113128,7 @@
|
|
}
|
|
}
|
|
#endif
|
|
- if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0
|
|
- && sqlite3StrNICmp(pTab->zName, "sqlite_stat", 11)!=0 ){
|
|
+ if( tableMayNotBeDropped(db, pTab) ){
|
|
sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName);
|
|
goto exit_drop_table;
|
|
}
|
|
@@ -110161,7 +113220,7 @@
|
|
nByte = sizeof(*pFKey) + (nCol-1)*sizeof(pFKey->aCol[0]) + pTo->n + 1;
|
|
if( pToCol ){
|
|
for(i=0; i<pToCol->nExpr; i++){
|
|
- nByte += sqlite3Strlen30(pToCol->a[i].zName) + 1;
|
|
+ nByte += sqlite3Strlen30(pToCol->a[i].zEName) + 1;
|
|
}
|
|
}
|
|
pFKey = sqlite3DbMallocZero(db, nByte );
|
|
@@ -110186,7 +113245,7 @@
|
|
for(i=0; i<nCol; i++){
|
|
int j;
|
|
for(j=0; j<p->nCol; j++){
|
|
- if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zName)==0 ){
|
|
+ if( sqlite3StrICmp(p->aCol[j].zName, pFromCol->a[i].zEName)==0 ){
|
|
pFKey->aCol[i].iFrom = j;
|
|
break;
|
|
}
|
|
@@ -110194,22 +113253,22 @@
|
|
if( j>=p->nCol ){
|
|
sqlite3ErrorMsg(pParse,
|
|
"unknown column \"%s\" in foreign key definition",
|
|
- pFromCol->a[i].zName);
|
|
+ pFromCol->a[i].zEName);
|
|
goto fk_end;
|
|
}
|
|
if( IN_RENAME_OBJECT ){
|
|
- sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zName);
|
|
+ sqlite3RenameTokenRemap(pParse, &pFKey->aCol[i], pFromCol->a[i].zEName);
|
|
}
|
|
}
|
|
}
|
|
if( pToCol ){
|
|
for(i=0; i<nCol; i++){
|
|
- int n = sqlite3Strlen30(pToCol->a[i].zName);
|
|
+ int n = sqlite3Strlen30(pToCol->a[i].zEName);
|
|
pFKey->aCol[i].zCol = z;
|
|
if( IN_RENAME_OBJECT ){
|
|
- sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zName);
|
|
+ sqlite3RenameTokenRemap(pParse, z, pToCol->a[i].zEName);
|
|
}
|
|
- memcpy(z, pToCol->a[i].zName, n);
|
|
+ memcpy(z, pToCol->a[i].zEName, n);
|
|
z[n] = 0;
|
|
z += n+1;
|
|
}
|
|
@@ -110406,6 +113465,27 @@
|
|
return p;
|
|
}
|
|
|
|
+/*
|
|
+** If expression list pList contains an expression that was parsed with
|
|
+** an explicit "NULLS FIRST" or "NULLS LAST" clause, leave an error in
|
|
+** pParse and return non-zero. Otherwise, return zero.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3HasExplicitNulls(Parse *pParse, ExprList *pList){
|
|
+ if( pList ){
|
|
+ int i;
|
|
+ for(i=0; i<pList->nExpr; i++){
|
|
+ if( pList->a[i].bNulls ){
|
|
+ u8 sf = pList->a[i].sortFlags;
|
|
+ sqlite3ErrorMsg(pParse, "unsupported use of NULLS %s",
|
|
+ (sf==0 || sf==3) ? "FIRST" : "LAST"
|
|
+ );
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
/*
|
|
** Create a new index for an SQL table. pName1.pName2 is the name of the index
|
|
** and pTblList is the name of the table that is to be indexed. Both will
|
|
@@ -110457,6 +113537,9 @@
|
|
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
|
goto exit_create_index;
|
|
}
|
|
+ if( sqlite3HasExplicitNulls(pParse, pList) ){
|
|
+ goto exit_create_index;
|
|
+ }
|
|
|
|
/*
|
|
** Find the table that is to be indexed. Return early if not found.
|
|
@@ -110555,7 +113638,7 @@
|
|
zName = sqlite3NameFromToken(db, pName);
|
|
if( zName==0 ) goto exit_create_index;
|
|
assert( pName->z!=0 );
|
|
- if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
|
+ if( SQLITE_OK!=sqlite3CheckObjectName(pParse, zName,"index",pTab->zName) ){
|
|
goto exit_create_index;
|
|
}
|
|
if( !IN_RENAME_OBJECT ){
|
|
@@ -110621,7 +113704,7 @@
|
|
sqlite3ExprAlloc(db, TK_ID, &prevCol, 0));
|
|
if( pList==0 ) goto exit_create_index;
|
|
assert( pList->nExpr==1 );
|
|
- sqlite3ExprListSetSortOrder(pList, sortOrder);
|
|
+ sqlite3ExprListSetSortOrder(pList, sortOrder, SQLITE_SO_UNDEFINED);
|
|
}else{
|
|
sqlite3ExprListCheckLength(pParse, pList, "index");
|
|
if( pParse->nErr ) goto exit_create_index;
|
|
@@ -110716,8 +113799,13 @@
|
|
assert( j<=0x7fff );
|
|
if( j<0 ){
|
|
j = pTab->iPKey;
|
|
- }else if( pTab->aCol[j].notNull==0 ){
|
|
- pIndex->uniqNotNull = 0;
|
|
+ }else{
|
|
+ if( pTab->aCol[j].notNull==0 ){
|
|
+ pIndex->uniqNotNull = 0;
|
|
+ }
|
|
+ if( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL ){
|
|
+ pIndex->bHasVCol = 1;
|
|
+ }
|
|
}
|
|
pIndex->aiColumn[i] = (i16)j;
|
|
}
|
|
@@ -110739,7 +113827,7 @@
|
|
goto exit_create_index;
|
|
}
|
|
pIndex->azColl[i] = zColl;
|
|
- requestedSortOrder = pListItem->sortOrder & sortOrderMask;
|
|
+ requestedSortOrder = pListItem->sortFlags & sortOrderMask;
|
|
pIndex->aSortOrder[i] = (u8)requestedSortOrder;
|
|
}
|
|
|
|
@@ -110772,13 +113860,13 @@
|
|
/* If this index contains every column of its table, then mark
|
|
** it as a covering index */
|
|
assert( HasRowid(pTab)
|
|
- || pTab->iPKey<0 || sqlite3ColumnOfIndex(pIndex, pTab->iPKey)>=0 );
|
|
+ || pTab->iPKey<0 || sqlite3TableColumnToIndex(pIndex, pTab->iPKey)>=0 );
|
|
recomputeColumnsNotIndexed(pIndex);
|
|
if( pTblName!=0 && pIndex->nColumn>=pTab->nCol ){
|
|
pIndex->isCovering = 1;
|
|
for(j=0; j<pTab->nCol; j++){
|
|
if( j==pTab->iPKey ) continue;
|
|
- if( sqlite3ColumnOfIndex(pIndex,j)>=0 ) continue;
|
|
+ if( sqlite3TableColumnToIndex(pIndex,j)>=0 ) continue;
|
|
pIndex->isCovering = 0;
|
|
break;
|
|
}
|
|
@@ -110914,6 +114002,7 @@
|
|
/* Gather the complete text of the CREATE INDEX statement into
|
|
** the zStmt variable
|
|
*/
|
|
+ assert( pName!=0 || pStart==0 );
|
|
if( pStart ){
|
|
int n = (int)(pParse->sLastToken.z - pName->z) + pParse->sLastToken.n;
|
|
if( pName->z[n-1]==';' ) n--;
|
|
@@ -110952,26 +114041,9 @@
|
|
sqlite3VdbeJumpHere(v, pIndex->tnum);
|
|
}
|
|
}
|
|
-
|
|
- /* When adding an index to the list of indices for a table, make
|
|
- ** sure all indices labeled OE_Replace come after all those labeled
|
|
- ** OE_Ignore. This is necessary for the correct constraint check
|
|
- ** processing (in sqlite3GenerateConstraintChecks()) as part of
|
|
- ** UPDATE and INSERT statements.
|
|
- */
|
|
if( db->init.busy || pTblName==0 ){
|
|
- if( onError!=OE_Replace || pTab->pIndex==0
|
|
- || pTab->pIndex->onError==OE_Replace){
|
|
- pIndex->pNext = pTab->pIndex;
|
|
- pTab->pIndex = pIndex;
|
|
- }else{
|
|
- Index *pOther = pTab->pIndex;
|
|
- while( pOther->pNext && pOther->pNext->onError!=OE_Replace ){
|
|
- pOther = pOther->pNext;
|
|
- }
|
|
- pIndex->pNext = pOther->pNext;
|
|
- pOther->pNext = pIndex;
|
|
- }
|
|
+ pIndex->pNext = pTab->pIndex;
|
|
+ pTab->pIndex = pIndex;
|
|
pIndex = 0;
|
|
}
|
|
else if( IN_RENAME_OBJECT ){
|
|
@@ -110983,6 +114055,21 @@
|
|
/* Clean up before exiting */
|
|
exit_create_index:
|
|
if( pIndex ) sqlite3FreeIndex(db, pIndex);
|
|
+ if( pTab ){ /* Ensure all REPLACE indexes are at the end of the list */
|
|
+ Index **ppFrom = &pTab->pIndex;
|
|
+ Index *pThis;
|
|
+ for(ppFrom=&pTab->pIndex; (pThis = *ppFrom)!=0; ppFrom=&pThis->pNext){
|
|
+ Index *pNext;
|
|
+ if( pThis->onError!=OE_Replace ) continue;
|
|
+ while( (pNext = pThis->pNext)!=0 && pNext->onError!=OE_Replace ){
|
|
+ *ppFrom = pNext;
|
|
+ pThis->pNext = pNext->pNext;
|
|
+ pNext->pNext = pThis;
|
|
+ ppFrom = &pNext->pNext;
|
|
+ }
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
sqlite3ExprDelete(db, pPIWhere);
|
|
sqlite3ExprListDelete(db, pList);
|
|
sqlite3SrcListDelete(db, pTblName);
|
|
@@ -111625,7 +114712,7 @@
|
|
}
|
|
db->aDb[1].pBt = pBt;
|
|
assert( db->aDb[1].pSchema );
|
|
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, -1, 0) ){
|
|
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize, 0, 0) ){
|
|
sqlite3OomFault(db);
|
|
return 1;
|
|
}
|
|
@@ -111736,7 +114823,7 @@
|
|
u8 p5Errmsg /* P5_ErrMsg type */
|
|
){
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
- assert( (errCode&0xff)==SQLITE_CONSTRAINT );
|
|
+ assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested );
|
|
if( onError==OE_Abort ){
|
|
sqlite3MayAbort(pParse);
|
|
}
|
|
@@ -111956,7 +115043,8 @@
|
|
const char *zColl = pIdx->azColl[i];
|
|
pKey->aColl[i] = zColl==sqlite3StrBINARY ? 0 :
|
|
sqlite3LocateCollSeq(pParse, zColl);
|
|
- pKey->aSortOrder[i] = pIdx->aSortOrder[i];
|
|
+ pKey->aSortFlags[i] = pIdx->aSortOrder[i];
|
|
+ assert( 0==(pKey->aSortFlags[i] & KEYINFO_ORDER_BIGNULL) );
|
|
}
|
|
if( pParse->nErr ){
|
|
assert( pParse->rc==SQLITE_ERROR_MISSING_COLLSEQ );
|
|
@@ -112116,51 +115204,6 @@
|
|
return SQLITE_ERROR;
|
|
}
|
|
|
|
-/*
|
|
-** This function is responsible for invoking the collation factory callback
|
|
-** or substituting a collation sequence of a different encoding when the
|
|
-** requested collation sequence is not available in the desired encoding.
|
|
-**
|
|
-** If it is not NULL, then pColl must point to the database native encoding
|
|
-** collation sequence with name zName, length nName.
|
|
-**
|
|
-** The return value is either the collation sequence to be used in database
|
|
-** db for collation type name zName, length nName, or NULL, if no collation
|
|
-** sequence can be found. If no collation is found, leave an error message.
|
|
-**
|
|
-** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
|
|
-*/
|
|
-SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
|
|
- Parse *pParse, /* Parsing context */
|
|
- u8 enc, /* The desired encoding for the collating sequence */
|
|
- CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
|
|
- const char *zName /* Collating sequence name */
|
|
-){
|
|
- CollSeq *p;
|
|
- sqlite3 *db = pParse->db;
|
|
-
|
|
- p = pColl;
|
|
- if( !p ){
|
|
- p = sqlite3FindCollSeq(db, enc, zName, 0);
|
|
- }
|
|
- if( !p || !p->xCmp ){
|
|
- /* No collation sequence of this type for this encoding is registered.
|
|
- ** Call the collation factory to see if it can supply us with one.
|
|
- */
|
|
- callCollNeeded(db, enc, zName);
|
|
- p = sqlite3FindCollSeq(db, enc, zName, 0);
|
|
- }
|
|
- if( p && !p->xCmp && synthCollSeq(db, p) ){
|
|
- p = 0;
|
|
- }
|
|
- assert( !p || p->xCmp );
|
|
- if( p==0 ){
|
|
- sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
|
|
- pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
|
|
- }
|
|
- return p;
|
|
-}
|
|
-
|
|
/*
|
|
** This routine is called on a collation sequence before it is used to
|
|
** check that it is defined. An undefined collation sequence exists when
|
|
@@ -112253,20 +115296,112 @@
|
|
** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq()
|
|
*/
|
|
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(
|
|
- sqlite3 *db,
|
|
- u8 enc,
|
|
- const char *zName,
|
|
- int create
|
|
+ sqlite3 *db, /* Database connection to search */
|
|
+ u8 enc, /* Desired text encoding */
|
|
+ const char *zName, /* Name of the collating sequence. Might be NULL */
|
|
+ int create /* True to create CollSeq if doesn't already exist */
|
|
){
|
|
CollSeq *pColl;
|
|
+ assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
|
+ assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
|
|
if( zName ){
|
|
pColl = findCollSeqEntry(db, zName, create);
|
|
+ if( pColl ) pColl += enc-1;
|
|
}else{
|
|
pColl = db->pDfltColl;
|
|
}
|
|
- assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 );
|
|
- assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE );
|
|
- if( pColl ) pColl += enc-1;
|
|
+ return pColl;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Change the text encoding for a database connection. This means that
|
|
+** the pDfltColl must change as well.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3SetTextEncoding(sqlite3 *db, u8 enc){
|
|
+ assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE );
|
|
+ db->enc = enc;
|
|
+ /* EVIDENCE-OF: R-08308-17224 The default collating function for all
|
|
+ ** strings is BINARY.
|
|
+ */
|
|
+ db->pDfltColl = sqlite3FindCollSeq(db, enc, sqlite3StrBINARY, 0);
|
|
+}
|
|
+
|
|
+/*
|
|
+** This function is responsible for invoking the collation factory callback
|
|
+** or substituting a collation sequence of a different encoding when the
|
|
+** requested collation sequence is not available in the desired encoding.
|
|
+**
|
|
+** If it is not NULL, then pColl must point to the database native encoding
|
|
+** collation sequence with name zName, length nName.
|
|
+**
|
|
+** The return value is either the collation sequence to be used in database
|
|
+** db for collation type name zName, length nName, or NULL, if no collation
|
|
+** sequence can be found. If no collation is found, leave an error message.
|
|
+**
|
|
+** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq()
|
|
+*/
|
|
+SQLITE_PRIVATE CollSeq *sqlite3GetCollSeq(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ u8 enc, /* The desired encoding for the collating sequence */
|
|
+ CollSeq *pColl, /* Collating sequence with native encoding, or NULL */
|
|
+ const char *zName /* Collating sequence name */
|
|
+){
|
|
+ CollSeq *p;
|
|
+ sqlite3 *db = pParse->db;
|
|
+
|
|
+ p = pColl;
|
|
+ if( !p ){
|
|
+ p = sqlite3FindCollSeq(db, enc, zName, 0);
|
|
+ }
|
|
+ if( !p || !p->xCmp ){
|
|
+ /* No collation sequence of this type for this encoding is registered.
|
|
+ ** Call the collation factory to see if it can supply us with one.
|
|
+ */
|
|
+ callCollNeeded(db, enc, zName);
|
|
+ p = sqlite3FindCollSeq(db, enc, zName, 0);
|
|
+ }
|
|
+ if( p && !p->xCmp && synthCollSeq(db, p) ){
|
|
+ p = 0;
|
|
+ }
|
|
+ assert( !p || p->xCmp );
|
|
+ if( p==0 ){
|
|
+ sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName);
|
|
+ pParse->rc = SQLITE_ERROR_MISSING_COLLSEQ;
|
|
+ }
|
|
+ return p;
|
|
+}
|
|
+
|
|
+/*
|
|
+** This function returns the collation sequence for database native text
|
|
+** encoding identified by the string zName.
|
|
+**
|
|
+** If the requested collation sequence is not available, or not available
|
|
+** in the database native encoding, the collation factory is invoked to
|
|
+** request it. If the collation factory does not supply such a sequence,
|
|
+** and the sequence is available in another text encoding, then that is
|
|
+** returned instead.
|
|
+**
|
|
+** If no versions of the requested collations sequence are available, or
|
|
+** another error occurs, NULL is returned and an error message written into
|
|
+** pParse.
|
|
+**
|
|
+** This routine is a wrapper around sqlite3FindCollSeq(). This routine
|
|
+** invokes the collation factory if the named collation cannot be found
|
|
+** and generates an error message.
|
|
+**
|
|
+** See also: sqlite3FindCollSeq(), sqlite3GetCollSeq()
|
|
+*/
|
|
+SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
|
|
+ sqlite3 *db = pParse->db;
|
|
+ u8 enc = ENC(db);
|
|
+ u8 initbusy = db->init.busy;
|
|
+ CollSeq *pColl;
|
|
+
|
|
+ pColl = sqlite3FindCollSeq(db, enc, zName, initbusy);
|
|
+ if( !initbusy && (!pColl || !pColl->xCmp) ){
|
|
+ pColl = sqlite3GetCollSeq(pParse, enc, pColl, zName);
|
|
+ }
|
|
+
|
|
return pColl;
|
|
}
|
|
|
|
@@ -112305,12 +115440,13 @@
|
|
u8 enc /* Desired text encoding */
|
|
){
|
|
int match;
|
|
-
|
|
- /* nArg of -2 is a special case */
|
|
- if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
|
|
+ assert( p->nArg>=-1 );
|
|
|
|
/* Wrong number of arguments means "no match" */
|
|
- if( p->nArg!=nArg && p->nArg>=0 ) return 0;
|
|
+ if( p->nArg!=nArg ){
|
|
+ if( nArg==(-2) ) return (p->xSFunc==0) ? 0 : FUNC_PERFECT_MATCH;
|
|
+ if( p->nArg>=0 ) return 0;
|
|
+ }
|
|
|
|
/* Give a better score to a function with a specific number of arguments
|
|
** than to function that accepts any number of arguments. */
|
|
@@ -112612,11 +115748,7 @@
|
|
return sqlite3WritableSchema(db)==0 && pParse->nested==0;
|
|
}
|
|
assert( pTab->tabFlags & TF_Shadow );
|
|
- return (db->flags & SQLITE_Defensive)!=0
|
|
-#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
- && db->pVtabCtx==0
|
|
-#endif
|
|
- && db->nVdbeExec==0;
|
|
+ return sqlite3ReadOnlyShadowTables(db);
|
|
}
|
|
|
|
/*
|
|
@@ -113079,7 +116211,9 @@
|
|
iTabCur, aToOpen, &iDataCur, &iIdxCur);
|
|
assert( pPk || IsVirtual(pTab) || iDataCur==iTabCur );
|
|
assert( pPk || IsVirtual(pTab) || iIdxCur==iDataCur+1 );
|
|
- if( eOnePass==ONEPASS_MULTI ) sqlite3VdbeJumpHere(v, iAddrOnce);
|
|
+ if( eOnePass==ONEPASS_MULTI ){
|
|
+ sqlite3VdbeJumpHereOrPopInst(v, iAddrOnce);
|
|
+ }
|
|
}
|
|
|
|
/* Set up a loop over the rowids/primary-keys that were found in the
|
|
@@ -113279,7 +116413,8 @@
|
|
testcase( mask!=0xffffffff && iCol==31 );
|
|
testcase( mask!=0xffffffff && iCol==32 );
|
|
if( mask==0xffffffff || (iCol<=31 && (mask & MASKBIT32(iCol))!=0) ){
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+iCol+1);
|
|
+ int kk = sqlite3TableColumnToStorage(pTab, iCol);
|
|
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, iCol, iOld+kk+1);
|
|
}
|
|
}
|
|
|
|
@@ -113401,6 +116536,7 @@
|
|
&iPartIdxLabel, pPrior, r1);
|
|
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
|
|
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
|
|
+ sqlite3VdbeChangeP5(v, 1); /* Cause IdxDelete to error if no entry found */
|
|
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
|
|
pPrior = pIdx;
|
|
}
|
|
@@ -113459,6 +116595,8 @@
|
|
sqlite3ExprIfFalseDup(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
|
|
SQLITE_JUMPIFNULL);
|
|
pParse->iSelfTab = 0;
|
|
+ pPrior = 0; /* Ticket a9efb42811fa41ee 2019-11-02;
|
|
+ ** pPartIdxWhere may have corrupted regPrior registers */
|
|
}else{
|
|
*piPartIdxLabel = 0;
|
|
}
|
|
@@ -113525,7 +116663,9 @@
|
|
/* #include "sqliteInt.h" */
|
|
/* #include <stdlib.h> */
|
|
/* #include <assert.h> */
|
|
+#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
/* #include <math.h> */
|
|
+#endif
|
|
/* #include "vdbeInt.h" */
|
|
|
|
/*
|
|
@@ -113712,6 +116852,8 @@
|
|
int N = 1;
|
|
int isText;
|
|
unsigned char firstChar;
|
|
+ sqlite3_value *pC1 = 0;
|
|
+ sqlite3_value *pC2 = 0;
|
|
|
|
UNUSED_PARAMETER(argc);
|
|
typeHaystack = sqlite3_value_type(argv[0]);
|
|
@@ -113724,12 +116866,22 @@
|
|
zHaystack = sqlite3_value_blob(argv[0]);
|
|
zNeedle = sqlite3_value_blob(argv[1]);
|
|
isText = 0;
|
|
- }else{
|
|
+ }else if( typeHaystack!=SQLITE_BLOB && typeNeedle!=SQLITE_BLOB ){
|
|
zHaystack = sqlite3_value_text(argv[0]);
|
|
zNeedle = sqlite3_value_text(argv[1]);
|
|
isText = 1;
|
|
+ }else{
|
|
+ pC1 = sqlite3_value_dup(argv[0]);
|
|
+ zHaystack = sqlite3_value_text(pC1);
|
|
+ if( zHaystack==0 ) goto endInstrOOM;
|
|
+ nHaystack = sqlite3_value_bytes(pC1);
|
|
+ pC2 = sqlite3_value_dup(argv[1]);
|
|
+ zNeedle = sqlite3_value_text(pC2);
|
|
+ if( zNeedle==0 ) goto endInstrOOM;
|
|
+ nNeedle = sqlite3_value_bytes(pC2);
|
|
+ isText = 1;
|
|
}
|
|
- if( zNeedle==0 || (nHaystack && zHaystack==0) ) return;
|
|
+ if( zNeedle==0 || (nHaystack && zHaystack==0) ) goto endInstrOOM;
|
|
firstChar = zNeedle[0];
|
|
while( nNeedle<=nHaystack
|
|
&& (zHaystack[0]!=firstChar || memcmp(zHaystack, zNeedle, nNeedle)!=0)
|
|
@@ -113743,6 +116895,13 @@
|
|
if( nNeedle>nHaystack ) N = 0;
|
|
}
|
|
sqlite3_result_int(context, N);
|
|
+endInstr:
|
|
+ sqlite3_value_free(pC1);
|
|
+ sqlite3_value_free(pC2);
|
|
+ return;
|
|
+endInstrOOM:
|
|
+ sqlite3_result_error_nomem(context);
|
|
+ goto endInstr;
|
|
}
|
|
|
|
/*
|
|
@@ -114341,6 +117500,7 @@
|
|
int nPat;
|
|
sqlite3 *db = sqlite3_context_db_handle(context);
|
|
struct compareInfo *pInfo = sqlite3_user_data(context);
|
|
+ struct compareInfo backupInfo;
|
|
|
|
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
|
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
|
|
@@ -114376,6 +117536,12 @@
|
|
return;
|
|
}
|
|
escape = sqlite3Utf8Read(&zEsc);
|
|
+ if( escape==pInfo->matchAll || escape==pInfo->matchOne ){
|
|
+ memcpy(&backupInfo, pInfo, sizeof(backupInfo));
|
|
+ pInfo = &backupInfo;
|
|
+ if( escape==pInfo->matchAll ) pInfo->matchAll = 0;
|
|
+ if( escape==pInfo->matchOne ) pInfo->matchOne = 0;
|
|
+ }
|
|
}else{
|
|
escape = pInfo->matchSet;
|
|
}
|
|
@@ -114764,7 +117930,7 @@
|
|
** whose index is a power of two: 1, 2, 4, 8, 16, 32, ... */
|
|
u8 *zOld;
|
|
zOld = zOut;
|
|
- zOut = sqlite3_realloc64(zOut, (int)nOut + (nOut - nStr - 1));
|
|
+ zOut = sqlite3Realloc(zOut, (int)nOut + (nOut - nStr - 1));
|
|
if( zOut==0 ){
|
|
sqlite3_result_error_nomem(context);
|
|
sqlite3_free(zOld);
|
|
@@ -115352,9 +118518,22 @@
|
|
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
|
nExpr = pExpr->x.pList->nExpr;
|
|
pDef = sqlite3FindFunction(db, pExpr->u.zToken, nExpr, SQLITE_UTF8, 0);
|
|
+#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
|
+ if( pDef==0 ) return 0;
|
|
+#endif
|
|
if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
|
|
return 0;
|
|
}
|
|
+
|
|
+ /* The memcpy() statement assumes that the wildcard characters are
|
|
+ ** the first three statements in the compareInfo structure. The
|
|
+ ** asserts() that follow verify that assumption
|
|
+ */
|
|
+ memcpy(aWc, pDef->pUserData, 3);
|
|
+ assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
|
|
+ assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
|
|
+ assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
|
|
+
|
|
if( nExpr<3 ){
|
|
aWc[3] = 0;
|
|
}else{
|
|
@@ -115363,17 +118542,11 @@
|
|
if( pEscape->op!=TK_STRING ) return 0;
|
|
zEscape = pEscape->u.zToken;
|
|
if( zEscape[0]==0 || zEscape[1]!=0 ) return 0;
|
|
+ if( zEscape[0]==aWc[0] ) return 0;
|
|
+ if( zEscape[0]==aWc[1] ) return 0;
|
|
aWc[3] = zEscape[0];
|
|
}
|
|
|
|
- /* The memcpy() statement assumes that the wildcard characters are
|
|
- ** the first three statements in the compareInfo structure. The
|
|
- ** asserts() that follow verify that assumption
|
|
- */
|
|
- memcpy(aWc, pDef->pUserData, 3);
|
|
- assert( (char*)&likeInfoAlt == (char*)&likeInfoAlt.matchAll );
|
|
- assert( &((char*)&likeInfoAlt)[1] == (char*)&likeInfoAlt.matchOne );
|
|
- assert( &((char*)&likeInfoAlt)[2] == (char*)&likeInfoAlt.matchSet );
|
|
*pIsNocase = (pDef->funcFlags & SQLITE_FUNC_CASE)==0;
|
|
return 1;
|
|
}
|
|
@@ -115397,12 +118570,20 @@
|
|
** For peak efficiency, put the most frequently used function last.
|
|
*/
|
|
static FuncDef aBuiltinFunc[] = {
|
|
+/***** Functions only available with SQLITE_TESTCTRL_INTERNAL_FUNCTIONS *****/
|
|
+ TEST_FUNC(implies_nonnull_row, 2, INLINEFUNC_implies_nonnull_row, 0),
|
|
+ TEST_FUNC(expr_compare, 2, INLINEFUNC_expr_compare, 0),
|
|
+ TEST_FUNC(expr_implies_expr, 2, INLINEFUNC_expr_implies_expr, 0),
|
|
+#ifdef SQLITE_DEBUG
|
|
+ TEST_FUNC(affinity, 1, INLINEFUNC_affinity, 0),
|
|
+#endif
|
|
+/***** Regular functions *****/
|
|
#ifdef SQLITE_SOUNDEX
|
|
FUNCTION(soundex, 1, 0, 0, soundexFunc ),
|
|
#endif
|
|
#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
|
- VFUNCTION(load_extension, 1, 0, 0, loadExt ),
|
|
- VFUNCTION(load_extension, 2, 0, 0, loadExt ),
|
|
+ SFUNCTION(load_extension, 1, 0, 0, loadExt ),
|
|
+ SFUNCTION(load_extension, 2, 0, 0, loadExt ),
|
|
#endif
|
|
#if SQLITE_USER_AUTHENTICATION
|
|
FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
|
|
@@ -115411,12 +118592,9 @@
|
|
DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
|
|
DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
|
|
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
|
- FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
|
- FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
|
- FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
|
-#ifdef SQLITE_DEBUG
|
|
- FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
|
|
-#endif
|
|
+ INLINE_FUNC(unlikely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
|
+ INLINE_FUNC(likelihood, 2, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
|
+ INLINE_FUNC(likely, 1, INLINEFUNC_unlikely, SQLITE_FUNC_UNLIKELY),
|
|
#ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC
|
|
FUNCTION2(sqlite_offset, 1, 0, 0, noopFunc, SQLITE_FUNC_OFFSET|
|
|
SQLITE_FUNC_TYPEOF),
|
|
@@ -115449,7 +118627,7 @@
|
|
FUNCTION(upper, 1, 0, 0, upperFunc ),
|
|
FUNCTION(lower, 1, 0, 0, lowerFunc ),
|
|
FUNCTION(hex, 1, 0, 0, hexFunc ),
|
|
- FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
|
+ INLINE_FUNC(ifnull, 2, INLINEFUNC_coalesce, 0 ),
|
|
VFUNCTION(random, 0, 0, 0, randomFunc ),
|
|
VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
|
|
FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
|
@@ -115489,15 +118667,13 @@
|
|
#endif
|
|
FUNCTION(coalesce, 1, 0, 0, 0 ),
|
|
FUNCTION(coalesce, 0, 0, 0, 0 ),
|
|
- FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
|
+ INLINE_FUNC(coalesce, -1, INLINEFUNC_coalesce, 0 ),
|
|
+ INLINE_FUNC(iif, 3, INLINEFUNC_iif, 0 ),
|
|
};
|
|
#ifndef SQLITE_OMIT_ALTERTABLE
|
|
sqlite3AlterFunctions();
|
|
#endif
|
|
sqlite3WindowFunctions();
|
|
-#if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
|
|
- sqlite3AnalyzeFunctions();
|
|
-#endif
|
|
sqlite3RegisterDateTimeFunctions();
|
|
sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
|
|
|
|
@@ -115871,7 +119047,7 @@
|
|
VdbeCoverage(v);
|
|
}
|
|
for(i=0; i<pFKey->nCol; i++){
|
|
- int iReg = aiCol[i] + regData + 1;
|
|
+ int iReg = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i]) + regData + 1;
|
|
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iOk); VdbeCoverage(v);
|
|
}
|
|
|
|
@@ -115887,7 +119063,8 @@
|
|
** is no matching parent key. Before using MustBeInt, make a copy of
|
|
** the value. Otherwise, the value inserted into the child key column
|
|
** will have INTEGER affinity applied to it, which may not be correct. */
|
|
- sqlite3VdbeAddOp2(v, OP_SCopy, aiCol[0]+1+regData, regTemp);
|
|
+ sqlite3VdbeAddOp2(v, OP_SCopy,
|
|
+ sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[0])+1+regData, regTemp);
|
|
iMustBeInt = sqlite3VdbeAddOp2(v, OP_MustBeInt, regTemp, 0);
|
|
VdbeCoverage(v);
|
|
|
|
@@ -115914,7 +119091,9 @@
|
|
sqlite3VdbeAddOp3(v, OP_OpenRead, iCur, pIdx->tnum, iDb);
|
|
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
|
for(i=0; i<nCol; i++){
|
|
- sqlite3VdbeAddOp2(v, OP_Copy, aiCol[i]+1+regData, regTemp+i);
|
|
+ sqlite3VdbeAddOp2(v, OP_Copy,
|
|
+ sqlite3TableColumnToStorage(pFKey->pFrom, aiCol[i])+1+regData,
|
|
+ regTemp+i);
|
|
}
|
|
|
|
/* If the parent table is the same as the child table, and we are about
|
|
@@ -115930,8 +119109,11 @@
|
|
if( pTab==pFKey->pFrom && nIncr==1 ){
|
|
int iJump = sqlite3VdbeCurrentAddr(v) + nCol + 1;
|
|
for(i=0; i<nCol; i++){
|
|
- int iChild = aiCol[i]+1+regData;
|
|
- int iParent = pIdx->aiColumn[i]+1+regData;
|
|
+ int iChild = sqlite3TableColumnToStorage(pFKey->pFrom,aiCol[i])
|
|
+ +1+regData;
|
|
+ int iParent = 1+regData;
|
|
+ iParent += sqlite3TableColumnToStorage(pIdx->pTable,
|
|
+ pIdx->aiColumn[i]);
|
|
assert( pIdx->aiColumn[i]>=0 );
|
|
assert( aiCol[i]!=pTab->iPKey );
|
|
if( pIdx->aiColumn[i]==pTab->iPKey ){
|
|
@@ -115999,14 +119181,14 @@
|
|
if( pExpr ){
|
|
if( iCol>=0 && iCol!=pTab->iPKey ){
|
|
pCol = &pTab->aCol[iCol];
|
|
- pExpr->iTable = regBase + iCol + 1;
|
|
- pExpr->affinity = pCol->affinity;
|
|
+ pExpr->iTable = regBase + sqlite3TableColumnToStorage(pTab,iCol) + 1;
|
|
+ pExpr->affExpr = pCol->affinity;
|
|
zColl = pCol->zColl;
|
|
if( zColl==0 ) zColl = db->pDfltColl->zName;
|
|
pExpr = sqlite3ExprAddCollateString(pParse, pExpr, zColl);
|
|
}else{
|
|
pExpr->iTable = regBase;
|
|
- pExpr->affinity = SQLITE_AFF_INTEGER;
|
|
+ pExpr->affExpr = SQLITE_AFF_INTEGER;
|
|
}
|
|
}
|
|
return pExpr;
|
|
@@ -116174,7 +119356,7 @@
|
|
/* Clean up the WHERE clause constructed above. */
|
|
sqlite3ExprDelete(db, pWhere);
|
|
if( iFkIfZero ){
|
|
- sqlite3VdbeJumpHere(v, iFkIfZero);
|
|
+ sqlite3VdbeJumpHereOrPopInst(v, iFkIfZero);
|
|
}
|
|
}
|
|
|
|
@@ -116448,7 +119630,9 @@
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
int iJump = sqlite3VdbeCurrentAddr(v) + pFKey->nCol + 1;
|
|
for(i=0; i<pFKey->nCol; i++){
|
|
- int iReg = pFKey->aCol[i].iFrom + regOld + 1;
|
|
+ int iFromCol, iReg;
|
|
+ iFromCol = pFKey->aCol[i].iFrom;
|
|
+ iReg = sqlite3TableColumnToStorage(pFKey->pFrom,iFromCol) + regOld+1;
|
|
sqlite3VdbeAddOp2(v, OP_IsNull, iReg, iJump); VdbeCoverage(v);
|
|
}
|
|
sqlite3VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, -1);
|
|
@@ -116783,7 +119967,15 @@
|
|
sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
|
|
sqlite3ExprAlloc(db, TK_ID, &tToCol, 0));
|
|
}else if( action==OE_SetDflt ){
|
|
- Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
|
|
+ Column *pCol = pFKey->pFrom->aCol + iFromCol;
|
|
+ Expr *pDflt;
|
|
+ if( pCol->colFlags & COLFLAG_GENERATED ){
|
|
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pCol->colFlags & COLFLAG_STORED );
|
|
+ pDflt = 0;
|
|
+ }else{
|
|
+ pDflt = pCol->pDflt;
|
|
+ }
|
|
if( pDflt ){
|
|
pNew = sqlite3ExprDup(db, pDflt, 0);
|
|
}else{
|
|
@@ -116809,7 +120001,7 @@
|
|
tFrom.n = nFrom;
|
|
pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed");
|
|
if( pRaise ){
|
|
- pRaise->affinity = OE_Abort;
|
|
+ pRaise->affExpr = OE_Abort;
|
|
}
|
|
pSelect = sqlite3SelectNew(pParse,
|
|
sqlite3ExprListAppend(pParse, 0, pRaise),
|
|
@@ -116821,7 +120013,7 @@
|
|
}
|
|
|
|
/* Disable lookaside memory allocation */
|
|
- db->lookaside.bDisable++;
|
|
+ DisableLookaside;
|
|
|
|
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
|
|
sizeof(Trigger) + /* struct Trigger */
|
|
@@ -116843,7 +120035,7 @@
|
|
}
|
|
|
|
/* Re-enable the lookaside buffer, if it was disabled earlier. */
|
|
- db->lookaside.bDisable--;
|
|
+ EnableLookaside;
|
|
|
|
sqlite3ExprDelete(db, pWhere);
|
|
sqlite3ExprDelete(db, pWhen);
|
|
@@ -116854,6 +120046,7 @@
|
|
return 0;
|
|
}
|
|
assert( pStep!=0 );
|
|
+ assert( pTrigger!=0 );
|
|
|
|
switch( action ){
|
|
case OE_Restrict:
|
|
@@ -116993,7 +120186,7 @@
|
|
sqlite3TableLock(pParse, iDb, pTab->tnum,
|
|
(opcode==OP_OpenWrite)?1:0, pTab->zName);
|
|
if( HasRowid(pTab) ){
|
|
- sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nCol);
|
|
+ sqlite3VdbeAddOp4Int(v, opcode, iCur, pTab->tnum, iDb, pTab->nNVCol);
|
|
VdbeComment((v, "%s", pTab->zName));
|
|
}else{
|
|
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
|
@@ -117044,18 +120237,19 @@
|
|
}
|
|
for(n=0; n<pIdx->nColumn; n++){
|
|
i16 x = pIdx->aiColumn[n];
|
|
+ char aff;
|
|
if( x>=0 ){
|
|
- pIdx->zColAff[n] = pTab->aCol[x].affinity;
|
|
+ aff = pTab->aCol[x].affinity;
|
|
}else if( x==XN_ROWID ){
|
|
- pIdx->zColAff[n] = SQLITE_AFF_INTEGER;
|
|
+ aff = SQLITE_AFF_INTEGER;
|
|
}else{
|
|
- char aff;
|
|
assert( x==XN_EXPR );
|
|
assert( pIdx->aColExpr!=0 );
|
|
aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr);
|
|
- if( aff==0 ) aff = SQLITE_AFF_BLOB;
|
|
- pIdx->zColAff[n] = aff;
|
|
}
|
|
+ if( aff<SQLITE_AFF_BLOB ) aff = SQLITE_AFF_BLOB;
|
|
+ if( aff>SQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC;
|
|
+ pIdx->zColAff[n] = aff;
|
|
}
|
|
pIdx->zColAff[n] = 0;
|
|
}
|
|
@@ -117084,7 +120278,7 @@
|
|
** 'E' REAL
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){
|
|
- int i;
|
|
+ int i, j;
|
|
char *zColAff = pTab->zColAff;
|
|
if( zColAff==0 ){
|
|
sqlite3 *db = sqlite3VdbeDb(v);
|
|
@@ -117094,12 +120288,15 @@
|
|
return;
|
|
}
|
|
|
|
- for(i=0; i<pTab->nCol; i++){
|
|
- zColAff[i] = pTab->aCol[i].affinity;
|
|
+ for(i=j=0; i<pTab->nCol; i++){
|
|
+ assert( pTab->aCol[i].affinity!=0 );
|
|
+ if( (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ){
|
|
+ zColAff[j++] = pTab->aCol[i].affinity;
|
|
+ }
|
|
}
|
|
do{
|
|
- zColAff[i--] = 0;
|
|
- }while( i>=0 && zColAff[i]==SQLITE_AFF_BLOB );
|
|
+ zColAff[j--] = 0;
|
|
+ }while( j>=0 && zColAff[j]<=SQLITE_AFF_BLOB );
|
|
pTab->zColAff = zColAff;
|
|
}
|
|
assert( zColAff!=0 );
|
|
@@ -117153,6 +120350,119 @@
|
|
return 0;
|
|
}
|
|
|
|
+/* This walker callback will compute the union of colFlags flags for all
|
|
+** referenced columns in a CHECK constraint or generated column expression.
|
|
+*/
|
|
+static int exprColumnFlagUnion(Walker *pWalker, Expr *pExpr){
|
|
+ if( pExpr->op==TK_COLUMN && pExpr->iColumn>=0 ){
|
|
+ assert( pExpr->iColumn < pWalker->u.pTab->nCol );
|
|
+ pWalker->eCode |= pWalker->u.pTab->aCol[pExpr->iColumn].colFlags;
|
|
+ }
|
|
+ return WRC_Continue;
|
|
+}
|
|
+
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+/*
|
|
+** All regular columns for table pTab have been puts into registers
|
|
+** starting with iRegStore. The registers that correspond to STORED
|
|
+** or VIRTUAL columns have not yet been initialized. This routine goes
|
|
+** back and computes the values for those columns based on the previously
|
|
+** computed normal columns.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3ComputeGeneratedColumns(
|
|
+ Parse *pParse, /* Parsing context */
|
|
+ int iRegStore, /* Register holding the first column */
|
|
+ Table *pTab /* The table */
|
|
+){
|
|
+ int i;
|
|
+ Walker w;
|
|
+ Column *pRedo;
|
|
+ int eProgress;
|
|
+ VdbeOp *pOp;
|
|
+
|
|
+ assert( pTab->tabFlags & TF_HasGenerated );
|
|
+ testcase( pTab->tabFlags & TF_HasVirtual );
|
|
+ testcase( pTab->tabFlags & TF_HasStored );
|
|
+
|
|
+ /* Before computing generated columns, first go through and make sure
|
|
+ ** that appropriate affinity has been applied to the regular columns
|
|
+ */
|
|
+ sqlite3TableAffinity(pParse->pVdbe, pTab, iRegStore);
|
|
+ if( (pTab->tabFlags & TF_HasStored)!=0
|
|
+ && (pOp = sqlite3VdbeGetOp(pParse->pVdbe,-1))->opcode==OP_Affinity
|
|
+ ){
|
|
+ /* Change the OP_Affinity argument to '@' (NONE) for all stored
|
|
+ ** columns. '@' is the no-op affinity and those columns have not
|
|
+ ** yet been computed. */
|
|
+ int ii, jj;
|
|
+ char *zP4 = pOp->p4.z;
|
|
+ assert( zP4!=0 );
|
|
+ assert( pOp->p4type==P4_DYNAMIC );
|
|
+ for(ii=jj=0; zP4[jj]; ii++){
|
|
+ if( pTab->aCol[ii].colFlags & COLFLAG_VIRTUAL ){
|
|
+ continue;
|
|
+ }
|
|
+ if( pTab->aCol[ii].colFlags & COLFLAG_STORED ){
|
|
+ zP4[jj] = SQLITE_AFF_NONE;
|
|
+ }
|
|
+ jj++;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Because there can be multiple generated columns that refer to one another,
|
|
+ ** this is a two-pass algorithm. On the first pass, mark all generated
|
|
+ ** columns as "not available".
|
|
+ */
|
|
+ for(i=0; i<pTab->nCol; i++){
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
|
|
+ testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
|
|
+ pTab->aCol[i].colFlags |= COLFLAG_NOTAVAIL;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ w.u.pTab = pTab;
|
|
+ w.xExprCallback = exprColumnFlagUnion;
|
|
+ w.xSelectCallback = 0;
|
|
+ w.xSelectCallback2 = 0;
|
|
+
|
|
+ /* On the second pass, compute the value of each NOT-AVAILABLE column.
|
|
+ ** Companion code in the TK_COLUMN case of sqlite3ExprCodeTarget() will
|
|
+ ** compute dependencies and mark remove the COLSPAN_NOTAVAIL mark, as
|
|
+ ** they are needed.
|
|
+ */
|
|
+ pParse->iSelfTab = -iRegStore;
|
|
+ do{
|
|
+ eProgress = 0;
|
|
+ pRedo = 0;
|
|
+ for(i=0; i<pTab->nCol; i++){
|
|
+ Column *pCol = pTab->aCol + i;
|
|
+ if( (pCol->colFlags & COLFLAG_NOTAVAIL)!=0 ){
|
|
+ int x;
|
|
+ pCol->colFlags |= COLFLAG_BUSY;
|
|
+ w.eCode = 0;
|
|
+ sqlite3WalkExpr(&w, pCol->pDflt);
|
|
+ pCol->colFlags &= ~COLFLAG_BUSY;
|
|
+ if( w.eCode & COLFLAG_NOTAVAIL ){
|
|
+ pRedo = pCol;
|
|
+ continue;
|
|
+ }
|
|
+ eProgress = 1;
|
|
+ assert( pCol->colFlags & COLFLAG_GENERATED );
|
|
+ x = sqlite3TableColumnToStorage(pTab, i) + iRegStore;
|
|
+ sqlite3ExprCodeGeneratedColumn(pParse, pCol, x);
|
|
+ pCol->colFlags &= ~COLFLAG_NOTAVAIL;
|
|
+ }
|
|
+ }
|
|
+ }while( pRedo && eProgress );
|
|
+ if( pRedo ){
|
|
+ sqlite3ErrorMsg(pParse, "generated column loop on \"%s\"", pRedo->zName);
|
|
+ }
|
|
+ pParse->iSelfTab = 0;
|
|
+}
|
|
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
|
+
|
|
+
|
|
#ifndef SQLITE_OMIT_AUTOINCREMENT
|
|
/*
|
|
** Locate or create an AutoincInfo structure associated with table pTab
|
|
@@ -117460,7 +120770,7 @@
|
|
Parse *pParse, /* Parser context */
|
|
SrcList *pTabList, /* Name of table into which we are inserting */
|
|
Select *pSelect, /* A SELECT statement to use as the data source */
|
|
- IdList *pColumn, /* Column names corresponding to IDLIST. */
|
|
+ IdList *pColumn, /* Column names corresponding to IDLIST, or NULL. */
|
|
int onError, /* How to handle constraint errors */
|
|
Upsert *pUpsert /* ON CONFLICT clauses for upsert, or NULL */
|
|
){
|
|
@@ -117485,6 +120795,7 @@
|
|
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
|
|
u8 bIdListInOrder; /* True if IDLIST is in table order */
|
|
ExprList *pList = 0; /* List of VALUES() to be inserted */
|
|
+ int iRegStore; /* Register in which to store next column */
|
|
|
|
/* Register allocations */
|
|
int regFromSelect = 0;/* Base register for data coming from SELECT */
|
|
@@ -117592,8 +120903,8 @@
|
|
*/
|
|
regAutoinc = autoIncBegin(pParse, iDb, pTab);
|
|
|
|
- /* Allocate registers for holding the rowid of the new row,
|
|
- ** the content of the new row, and the assembled row record.
|
|
+ /* Allocate a block registers to hold the rowid and the values
|
|
+ ** for all columns of the new row.
|
|
*/
|
|
regRowid = regIns = pParse->nMem+1;
|
|
pParse->nMem += pTab->nCol + 1;
|
|
@@ -117612,9 +120923,17 @@
|
|
** the index into IDLIST of the primary key column. ipkColumn is
|
|
** the index of the primary key as it appears in IDLIST, not as
|
|
** is appears in the original table. (The index of the INTEGER
|
|
- ** PRIMARY KEY in the original table is pTab->iPKey.)
|
|
+ ** PRIMARY KEY in the original table is pTab->iPKey.) After this
|
|
+ ** loop, if ipkColumn==(-1), that means that integer primary key
|
|
+ ** is unspecified, and hence the table is either WITHOUT ROWID or
|
|
+ ** it will automatically generated an integer primary key.
|
|
+ **
|
|
+ ** bIdListInOrder is true if the columns in IDLIST are in storage
|
|
+ ** order. This enables an optimization that avoids shuffling the
|
|
+ ** columns into storage order. False negatives are harmless,
|
|
+ ** but false positives will cause database corruption.
|
|
*/
|
|
- bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
|
|
+ bIdListInOrder = (pTab->tabFlags & (TF_OOOHidden|TF_HasStored))==0;
|
|
if( pColumn ){
|
|
for(i=0; i<pColumn->nId; i++){
|
|
pColumn->a[i].idx = -1;
|
|
@@ -117627,6 +120946,14 @@
|
|
if( j==pTab->iPKey ){
|
|
ipkColumn = i; assert( !withoutRowid );
|
|
}
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( pTab->aCol[j].colFlags & (COLFLAG_STORED|COLFLAG_VIRTUAL) ){
|
|
+ sqlite3ErrorMsg(pParse,
|
|
+ "cannot INSERT into generated column \"%s\"",
|
|
+ pTab->aCol[j].zName);
|
|
+ goto insert_cleanup;
|
|
+ }
|
|
+#endif
|
|
break;
|
|
}
|
|
}
|
|
@@ -117736,13 +121063,26 @@
|
|
*/
|
|
if( pColumn==0 && nColumn>0 ){
|
|
ipkColumn = pTab->iPKey;
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( ipkColumn>=0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
|
|
+ testcase( pTab->tabFlags & TF_HasVirtual );
|
|
+ testcase( pTab->tabFlags & TF_HasStored );
|
|
+ for(i=ipkColumn-1; i>=0; i--){
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
|
|
+ testcase( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pTab->aCol[i].colFlags & COLFLAG_STORED );
|
|
+ ipkColumn--;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
/* Make sure the number of columns in the source data matches the number
|
|
** of columns to be inserted into the table.
|
|
*/
|
|
for(i=0; i<pTab->nCol; i++){
|
|
- nHidden += (IsHiddenColumn(&pTab->aCol[i]) ? 1 : 0);
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_NOINSERT ) nHidden++;
|
|
}
|
|
if( pColumn==0 && nColumn && nColumn!=(pTab->nCol-nHidden) ){
|
|
sqlite3ErrorMsg(pParse,
|
|
@@ -117788,6 +121128,13 @@
|
|
pTab->zName);
|
|
goto insert_cleanup;
|
|
}
|
|
+ if( pTab->pSelect ){
|
|
+ sqlite3ErrorMsg(pParse, "cannot UPSERT a view");
|
|
+ goto insert_cleanup;
|
|
+ }
|
|
+ if( sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget) ){
|
|
+ goto insert_cleanup;
|
|
+ }
|
|
pTabList->a[0].iCursor = iDataCur;
|
|
pUpsert->pUpsertSrc = pTabList;
|
|
pUpsert->regData = regData;
|
|
@@ -117822,10 +121169,91 @@
|
|
** goto C
|
|
** D: ...
|
|
*/
|
|
+ sqlite3VdbeReleaseRegisters(pParse, regData, pTab->nCol, 0, 0);
|
|
addrInsTop = addrCont = sqlite3VdbeAddOp1(v, OP_Yield, dest.iSDParm);
|
|
VdbeCoverage(v);
|
|
+ if( ipkColumn>=0 ){
|
|
+ /* tag-20191021-001: If the INTEGER PRIMARY KEY is being generated by the
|
|
+ ** SELECT, go ahead and copy the value into the rowid slot now, so that
|
|
+ ** the value does not get overwritten by a NULL at tag-20191021-002. */
|
|
+ sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
|
|
+ }
|
|
}
|
|
|
|
+ /* Compute data for ordinary columns of the new entry. Values
|
|
+ ** are written in storage order into registers starting with regData.
|
|
+ ** Only ordinary columns are computed in this loop. The rowid
|
|
+ ** (if there is one) is computed later and generated columns are
|
|
+ ** computed after the rowid since they might depend on the value
|
|
+ ** of the rowid.
|
|
+ */
|
|
+ nHidden = 0;
|
|
+ iRegStore = regData; assert( regData==regRowid+1 );
|
|
+ for(i=0; i<pTab->nCol; i++, iRegStore++){
|
|
+ int k;
|
|
+ u32 colFlags;
|
|
+ assert( i>=nHidden );
|
|
+ if( i==pTab->iPKey ){
|
|
+ /* tag-20191021-002: References to the INTEGER PRIMARY KEY are filled
|
|
+ ** using the rowid. So put a NULL in the IPK slot of the record to avoid
|
|
+ ** using excess space. The file format definition requires this extra
|
|
+ ** NULL - we cannot optimize further by skipping the column completely */
|
|
+ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
|
|
+ continue;
|
|
+ }
|
|
+ if( ((colFlags = pTab->aCol[i].colFlags) & COLFLAG_NOINSERT)!=0 ){
|
|
+ nHidden++;
|
|
+ if( (colFlags & COLFLAG_VIRTUAL)!=0 ){
|
|
+ /* Virtual columns do not participate in OP_MakeRecord. So back up
|
|
+ ** iRegStore by one slot to compensate for the iRegStore++ in the
|
|
+ ** outer for() loop */
|
|
+ iRegStore--;
|
|
+ continue;
|
|
+ }else if( (colFlags & COLFLAG_STORED)!=0 ){
|
|
+ /* Stored columns are computed later. But if there are BEFORE
|
|
+ ** triggers, the slots used for stored columns will be OP_Copy-ed
|
|
+ ** to a second block of registers, so the register needs to be
|
|
+ ** initialized to NULL to avoid an uninitialized register read */
|
|
+ if( tmask & TRIGGER_BEFORE ){
|
|
+ sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
|
|
+ }
|
|
+ continue;
|
|
+ }else if( pColumn==0 ){
|
|
+ /* Hidden columns that are not explicitly named in the INSERT
|
|
+ ** get there default value */
|
|
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
|
+ continue;
|
|
+ }
|
|
+ }
|
|
+ if( pColumn ){
|
|
+ for(j=0; j<pColumn->nId && pColumn->a[j].idx!=i; j++){}
|
|
+ if( j>=pColumn->nId ){
|
|
+ /* A column not named in the insert column list gets its
|
|
+ ** default value */
|
|
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
|
+ continue;
|
|
+ }
|
|
+ k = j;
|
|
+ }else if( nColumn==0 ){
|
|
+ /* This is INSERT INTO ... DEFAULT VALUES. Load the default value. */
|
|
+ sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
|
+ continue;
|
|
+ }else{
|
|
+ k = i - nHidden;
|
|
+ }
|
|
+
|
|
+ if( useTempTable ){
|
|
+ sqlite3VdbeAddOp3(v, OP_Column, srcTab, k, iRegStore);
|
|
+ }else if( pSelect ){
|
|
+ if( regFromSelect!=regData ){
|
|
+ sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+k, iRegStore);
|
|
+ }
|
|
+ }else{
|
|
+ sqlite3ExprCode(pParse, pList->a[k].pExpr, iRegStore);
|
|
+ }
|
|
+ }
|
|
+
|
|
+
|
|
/* Run the BEFORE and INSTEAD OF triggers, if there are any
|
|
*/
|
|
endOfLoop = sqlite3VdbeMakeLabel(pParse);
|
|
@@ -117860,25 +121288,21 @@
|
|
*/
|
|
assert( !IsVirtual(pTab) );
|
|
|
|
- /* Create the new column data
|
|
- */
|
|
- for(i=j=0; i<pTab->nCol; i++){
|
|
- if( pColumn ){
|
|
- for(j=0; j<pColumn->nId; j++){
|
|
- if( pColumn->a[j].idx==i ) break;
|
|
- }
|
|
- }
|
|
- if( (!useTempTable && !pList) || (pColumn && j>=pColumn->nId)
|
|
- || (pColumn==0 && IsOrdinaryHiddenColumn(&pTab->aCol[i])) ){
|
|
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regCols+i+1);
|
|
- }else if( useTempTable ){
|
|
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, regCols+i+1);
|
|
- }else{
|
|
- assert( pSelect==0 ); /* Otherwise useTempTable is true */
|
|
- sqlite3ExprCodeAndCache(pParse, pList->a[j].pExpr, regCols+i+1);
|
|
- }
|
|
- if( pColumn==0 && !IsOrdinaryHiddenColumn(&pTab->aCol[i]) ) j++;
|
|
+ /* Copy the new data already generated. */
|
|
+ assert( pTab->nNVCol>0 );
|
|
+ sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1);
|
|
+
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ /* Compute the new value for generated columns after all other
|
|
+ ** columns have already been computed. This must be done after
|
|
+ ** computing the ROWID in case one of the generated columns
|
|
+ ** refers to the ROWID. */
|
|
+ if( pTab->tabFlags & TF_HasGenerated ){
|
|
+ testcase( pTab->tabFlags & TF_HasVirtual );
|
|
+ testcase( pTab->tabFlags & TF_HasStored );
|
|
+ sqlite3ComputeGeneratedColumns(pParse, regCols+1, pTab);
|
|
}
|
|
+#endif
|
|
|
|
/* If this is an INSERT on a view with an INSTEAD OF INSERT trigger,
|
|
** do not attempt any conversions before assembling the record.
|
|
@@ -117896,19 +121320,17 @@
|
|
sqlite3ReleaseTempRange(pParse, regCols, pTab->nCol+1);
|
|
}
|
|
|
|
- /* Compute the content of the next row to insert into a range of
|
|
- ** registers beginning at regIns.
|
|
- */
|
|
if( !isView ){
|
|
if( IsVirtual(pTab) ){
|
|
/* The row that the VUpdate opcode will delete: none */
|
|
sqlite3VdbeAddOp2(v, OP_Null, 0, regIns);
|
|
}
|
|
if( ipkColumn>=0 ){
|
|
+ /* Compute the new rowid */
|
|
if( useTempTable ){
|
|
sqlite3VdbeAddOp3(v, OP_Column, srcTab, ipkColumn, regRowid);
|
|
}else if( pSelect ){
|
|
- sqlite3VdbeAddOp2(v, OP_Copy, regFromSelect+ipkColumn, regRowid);
|
|
+ /* Rowid already initialized at tag-20191021-001 */
|
|
}else{
|
|
Expr *pIpk = pList->a[ipkColumn].pExpr;
|
|
if( pIpk->op==TK_NULL && !IsVirtual(pTab) ){
|
|
@@ -117941,45 +121363,15 @@
|
|
}
|
|
autoIncStep(pParse, regAutoinc, regRowid);
|
|
|
|
- /* Compute data for all columns of the new entry, beginning
|
|
- ** with the first column.
|
|
- */
|
|
- nHidden = 0;
|
|
- for(i=0; i<pTab->nCol; i++){
|
|
- int iRegStore = regRowid+1+i;
|
|
- if( i==pTab->iPKey ){
|
|
- /* The value of the INTEGER PRIMARY KEY column is always a NULL.
|
|
- ** Whenever this column is read, the rowid will be substituted
|
|
- ** in its place. Hence, fill this column with a NULL to avoid
|
|
- ** taking up data space with information that will never be used.
|
|
- ** As there may be shallow copies of this value, make it a soft-NULL */
|
|
- sqlite3VdbeAddOp1(v, OP_SoftNull, iRegStore);
|
|
- continue;
|
|
- }
|
|
- if( pColumn==0 ){
|
|
- if( IsHiddenColumn(&pTab->aCol[i]) ){
|
|
- j = -1;
|
|
- nHidden++;
|
|
- }else{
|
|
- j = i - nHidden;
|
|
- }
|
|
- }else{
|
|
- for(j=0; j<pColumn->nId; j++){
|
|
- if( pColumn->a[j].idx==i ) break;
|
|
- }
|
|
- }
|
|
- if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
|
|
- sqlite3ExprCodeFactorable(pParse, pTab->aCol[i].pDflt, iRegStore);
|
|
- }else if( useTempTable ){
|
|
- sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore);
|
|
- }else if( pSelect ){
|
|
- if( regFromSelect!=regData ){
|
|
- sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
|
|
- }
|
|
- }else{
|
|
- sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
|
|
- }
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ /* Compute the new value for generated columns after all other
|
|
+ ** columns have already been computed. This must be done after
|
|
+ ** computing the ROWID in case one of the generated columns
|
|
+ ** is derived from the INTEGER PRIMARY KEY. */
|
|
+ if( pTab->tabFlags & TF_HasGenerated ){
|
|
+ sqlite3ComputeGeneratedColumns(pParse, regRowid+1, pTab);
|
|
}
|
|
+#endif
|
|
|
|
/* Generate code to check constraints and generate index keys and
|
|
** do the insertion.
|
|
@@ -118009,9 +121401,7 @@
|
|
** cursor that is disturbed. And these instructions both clear the
|
|
** VdbeCursor.seekResult variable, disabling the OPFLAG_USESEEKRESULT
|
|
** functionality. */
|
|
- bUseSeek = (isReplace==0 || (pTrigger==0 &&
|
|
- ((db->flags & SQLITE_ForeignKeys)==0 || sqlite3FkReferences(pTab)==0)
|
|
- ));
|
|
+ bUseSeek = (isReplace==0 || !sqlite3VdbeHasSubProgram(v));
|
|
sqlite3CompleteInsertion(pParse, pTab, iDataCur, iIdxCur,
|
|
regIns, aRegIdx, 0, appendFlag, bUseSeek
|
|
);
|
|
@@ -118040,6 +121430,15 @@
|
|
sqlite3VdbeAddOp1(v, OP_Close, srcTab);
|
|
}else if( pSelect ){
|
|
sqlite3VdbeGoto(v, addrCont);
|
|
+#ifdef SQLITE_DEBUG
|
|
+ /* If we are jumping back to an OP_Yield that is preceded by an
|
|
+ ** OP_ReleaseReg, set the p5 flag on the OP_Goto so that the
|
|
+ ** OP_ReleaseReg will be included in the loop. */
|
|
+ if( sqlite3VdbeGetOp(v, addrCont-1)->opcode==OP_ReleaseReg ){
|
|
+ assert( sqlite3VdbeGetOp(v, addrCont)->opcode==OP_Yield );
|
|
+ sqlite3VdbeChangeP5(v, 1);
|
|
+ }
|
|
+#endif
|
|
sqlite3VdbeJumpHere(v, addrInsTop);
|
|
}
|
|
|
|
@@ -118262,7 +121661,6 @@
|
|
int ix; /* Index loop counter */
|
|
int nCol; /* Number of columns */
|
|
int onError; /* Conflict resolution strategy */
|
|
- int addr1; /* Address of jump instruction */
|
|
int seenReplace = 0; /* True if REPLACE is used to resolve INT PK conflict */
|
|
int nPkField; /* Number of fields in PRIMARY KEY. 1 for ROWID tables */
|
|
Index *pUpIdx = 0; /* Index to which to apply the upsert */
|
|
@@ -118272,6 +121670,13 @@
|
|
int upsertJump = 0; /* Address of Goto that jumps into upsert subroutine */
|
|
int ipkTop = 0; /* Top of the IPK uniqueness check */
|
|
int ipkBottom = 0; /* OP_Goto at the end of the IPK uniqueness check */
|
|
+ /* Variables associated with retesting uniqueness constraints after
|
|
+ ** replace triggers fire have run */
|
|
+ int regTrigCnt; /* Register used to count replace trigger invocations */
|
|
+ int addrRecheck = 0; /* Jump here to recheck all uniqueness constraints */
|
|
+ int lblRecheckOk = 0; /* Each recheck jumps to this label if it passes */
|
|
+ Trigger *pTrigger; /* List of DELETE triggers on the table pTab */
|
|
+ int nReplaceTrig = 0; /* Number of replace triggers coded */
|
|
|
|
isUpdate = regOldData!=0;
|
|
db = pParse->db;
|
|
@@ -118298,63 +121703,103 @@
|
|
|
|
/* Test all NOT NULL constraints.
|
|
*/
|
|
- for(i=0; i<nCol; i++){
|
|
- if( i==pTab->iPKey ){
|
|
- continue; /* ROWID is never NULL */
|
|
- }
|
|
- if( aiChng && aiChng[i]<0 ){
|
|
- /* Don't bother checking for NOT NULL on columns that do not change */
|
|
- continue;
|
|
- }
|
|
- onError = pTab->aCol[i].notNull;
|
|
- if( onError==OE_None ) continue; /* This column is allowed to be NULL */
|
|
- if( overrideError!=OE_Default ){
|
|
- onError = overrideError;
|
|
- }else if( onError==OE_Default ){
|
|
- onError = OE_Abort;
|
|
- }
|
|
- if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
|
|
- onError = OE_Abort;
|
|
- }
|
|
- assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
|
- || onError==OE_Ignore || onError==OE_Replace );
|
|
- addr1 = 0;
|
|
- switch( onError ){
|
|
- case OE_Replace: {
|
|
- assert( onError==OE_Replace );
|
|
- addr1 = sqlite3VdbeMakeLabel(pParse);
|
|
- sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
|
|
- VdbeCoverage(v);
|
|
- sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, regNewData+1+i);
|
|
- sqlite3VdbeAddOp2(v, OP_NotNull, regNewData+1+i, addr1);
|
|
- VdbeCoverage(v);
|
|
- onError = OE_Abort;
|
|
- /* Fall through into the OE_Abort case to generate code that runs
|
|
- ** if both the input and the default value are NULL */
|
|
- }
|
|
- case OE_Abort:
|
|
- sqlite3MayAbort(pParse);
|
|
- /* Fall through */
|
|
- case OE_Rollback:
|
|
- case OE_Fail: {
|
|
- char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
|
|
- pTab->aCol[i].zName);
|
|
- sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL, onError,
|
|
- regNewData+1+i);
|
|
- sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
|
|
- sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
|
|
- VdbeCoverage(v);
|
|
- if( addr1 ) sqlite3VdbeResolveLabel(v, addr1);
|
|
+ if( pTab->tabFlags & TF_HasNotNull ){
|
|
+ int b2ndPass = 0; /* True if currently running 2nd pass */
|
|
+ int nSeenReplace = 0; /* Number of ON CONFLICT REPLACE operations */
|
|
+ int nGenerated = 0; /* Number of generated columns with NOT NULL */
|
|
+ while(1){ /* Make 2 passes over columns. Exit loop via "break" */
|
|
+ for(i=0; i<nCol; i++){
|
|
+ int iReg; /* Register holding column value */
|
|
+ Column *pCol = &pTab->aCol[i]; /* The column to check for NOT NULL */
|
|
+ int isGenerated; /* non-zero if column is generated */
|
|
+ onError = pCol->notNull;
|
|
+ if( onError==OE_None ) continue; /* No NOT NULL on this column */
|
|
+ if( i==pTab->iPKey ){
|
|
+ continue; /* ROWID is never NULL */
|
|
+ }
|
|
+ isGenerated = pCol->colFlags & COLFLAG_GENERATED;
|
|
+ if( isGenerated && !b2ndPass ){
|
|
+ nGenerated++;
|
|
+ continue; /* Generated columns processed on 2nd pass */
|
|
+ }
|
|
+ if( aiChng && aiChng[i]<0 && !isGenerated ){
|
|
+ /* Do not check NOT NULL on columns that do not change */
|
|
+ continue;
|
|
+ }
|
|
+ if( overrideError!=OE_Default ){
|
|
+ onError = overrideError;
|
|
+ }else if( onError==OE_Default ){
|
|
+ onError = OE_Abort;
|
|
+ }
|
|
+ if( onError==OE_Replace ){
|
|
+ if( b2ndPass /* REPLACE becomes ABORT on the 2nd pass */
|
|
+ || pCol->pDflt==0 /* REPLACE is ABORT if no DEFAULT value */
|
|
+ ){
|
|
+ testcase( pCol->colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pCol->colFlags & COLFLAG_STORED );
|
|
+ testcase( pCol->colFlags & COLFLAG_GENERATED );
|
|
+ onError = OE_Abort;
|
|
+ }else{
|
|
+ assert( !isGenerated );
|
|
+ }
|
|
+ }else if( b2ndPass && !isGenerated ){
|
|
+ continue;
|
|
+ }
|
|
+ assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
|
|
+ || onError==OE_Ignore || onError==OE_Replace );
|
|
+ testcase( i!=sqlite3TableColumnToStorage(pTab, i) );
|
|
+ iReg = sqlite3TableColumnToStorage(pTab, i) + regNewData + 1;
|
|
+ switch( onError ){
|
|
+ case OE_Replace: {
|
|
+ int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, iReg);
|
|
+ VdbeCoverage(v);
|
|
+ assert( (pCol->colFlags & COLFLAG_GENERATED)==0 );
|
|
+ nSeenReplace++;
|
|
+ sqlite3ExprCodeCopy(pParse, pCol->pDflt, iReg);
|
|
+ sqlite3VdbeJumpHere(v, addr1);
|
|
+ break;
|
|
+ }
|
|
+ case OE_Abort:
|
|
+ sqlite3MayAbort(pParse);
|
|
+ /* Fall through */
|
|
+ case OE_Rollback:
|
|
+ case OE_Fail: {
|
|
+ char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
|
|
+ pCol->zName);
|
|
+ sqlite3VdbeAddOp3(v, OP_HaltIfNull, SQLITE_CONSTRAINT_NOTNULL,
|
|
+ onError, iReg);
|
|
+ sqlite3VdbeAppendP4(v, zMsg, P4_DYNAMIC);
|
|
+ sqlite3VdbeChangeP5(v, P5_ConstraintNotNull);
|
|
+ VdbeCoverage(v);
|
|
+ break;
|
|
+ }
|
|
+ default: {
|
|
+ assert( onError==OE_Ignore );
|
|
+ sqlite3VdbeAddOp2(v, OP_IsNull, iReg, ignoreDest);
|
|
+ VdbeCoverage(v);
|
|
+ break;
|
|
+ }
|
|
+ } /* end switch(onError) */
|
|
+ } /* end loop i over columns */
|
|
+ if( nGenerated==0 && nSeenReplace==0 ){
|
|
+ /* If there are no generated columns with NOT NULL constraints
|
|
+ ** and no NOT NULL ON CONFLICT REPLACE constraints, then a single
|
|
+ ** pass is sufficient */
|
|
break;
|
|
}
|
|
- default: {
|
|
- assert( onError==OE_Ignore );
|
|
- sqlite3VdbeAddOp2(v, OP_IsNull, regNewData+1+i, ignoreDest);
|
|
- VdbeCoverage(v);
|
|
- break;
|
|
+ if( b2ndPass ) break; /* Never need more than 2 passes */
|
|
+ b2ndPass = 1;
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( nSeenReplace>0 && (pTab->tabFlags & TF_HasGenerated)!=0 ){
|
|
+ /* If any NOT NULL ON CONFLICT REPLACE constraints fired on the
|
|
+ ** first pass, recomputed values for all generated columns, as
|
|
+ ** those values might depend on columns affected by the REPLACE.
|
|
+ */
|
|
+ sqlite3ComputeGeneratedColumns(pParse, regNewData+1, pTab);
|
|
}
|
|
- }
|
|
- }
|
|
+#endif
|
|
+ } /* end of 2-pass loop */
|
|
+ } /* end if( has-not-null-constraints ) */
|
|
|
|
/* Test all CHECK constraints
|
|
*/
|
|
@@ -118365,6 +121810,7 @@
|
|
onError = overrideError!=OE_Default ? overrideError : OE_Abort;
|
|
for(i=0; i<pCheck->nExpr; i++){
|
|
int allOk;
|
|
+ Expr *pCopy;
|
|
Expr *pExpr = pCheck->a[i].pExpr;
|
|
if( aiChng
|
|
&& !sqlite3ExprReferencesUpdatedColumn(pExpr, aiChng, pkChng)
|
|
@@ -118373,13 +121819,21 @@
|
|
** updated so there is no point it verifying the check constraint */
|
|
continue;
|
|
}
|
|
+ if( bAffinityDone==0 ){
|
|
+ sqlite3TableAffinity(v, pTab, regNewData+1);
|
|
+ bAffinityDone = 1;
|
|
+ }
|
|
allOk = sqlite3VdbeMakeLabel(pParse);
|
|
sqlite3VdbeVerifyAbortable(v, onError);
|
|
- sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
|
|
+ pCopy = sqlite3ExprDup(db, pExpr, 0);
|
|
+ if( !db->mallocFailed ){
|
|
+ sqlite3ExprIfTrue(pParse, pCopy, allOk, SQLITE_JUMPIFNULL);
|
|
+ }
|
|
+ sqlite3ExprDelete(db, pCopy);
|
|
if( onError==OE_Ignore ){
|
|
sqlite3VdbeGoto(v, ignoreDest);
|
|
}else{
|
|
- char *zName = pCheck->a[i].zName;
|
|
+ char *zName = pCheck->a[i].zEName;
|
|
if( zName==0 ) zName = pTab->zName;
|
|
if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-26383-51744 */
|
|
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_CHECK,
|
|
@@ -118436,6 +121890,50 @@
|
|
}
|
|
}
|
|
|
|
+ /* Determine if it is possible that triggers (either explicitly coded
|
|
+ ** triggers or FK resolution actions) might run as a result of deletes
|
|
+ ** that happen when OE_Replace conflict resolution occurs. (Call these
|
|
+ ** "replace triggers".) If any replace triggers run, we will need to
|
|
+ ** recheck all of the uniqueness constraints after they have all run.
|
|
+ ** But on the recheck, the resolution is OE_Abort instead of OE_Replace.
|
|
+ **
|
|
+ ** If replace triggers are a possibility, then
|
|
+ **
|
|
+ ** (1) Allocate register regTrigCnt and initialize it to zero.
|
|
+ ** That register will count the number of replace triggers that
|
|
+ ** fire. Constraint recheck only occurs if the number is positive.
|
|
+ ** (2) Initialize pTrigger to the list of all DELETE triggers on pTab.
|
|
+ ** (3) Initialize addrRecheck and lblRecheckOk
|
|
+ **
|
|
+ ** The uniqueness rechecking code will create a series of tests to run
|
|
+ ** in a second pass. The addrRecheck and lblRecheckOk variables are
|
|
+ ** used to link together these tests which are separated from each other
|
|
+ ** in the generate bytecode.
|
|
+ */
|
|
+ if( (db->flags & (SQLITE_RecTriggers|SQLITE_ForeignKeys))==0 ){
|
|
+ /* There are not DELETE triggers nor FK constraints. No constraint
|
|
+ ** rechecks are needed. */
|
|
+ pTrigger = 0;
|
|
+ regTrigCnt = 0;
|
|
+ }else{
|
|
+ if( db->flags&SQLITE_RecTriggers ){
|
|
+ pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
|
+ regTrigCnt = pTrigger!=0 || sqlite3FkRequired(pParse, pTab, 0, 0);
|
|
+ }else{
|
|
+ pTrigger = 0;
|
|
+ regTrigCnt = sqlite3FkRequired(pParse, pTab, 0, 0);
|
|
+ }
|
|
+ if( regTrigCnt ){
|
|
+ /* Replace triggers might exist. Allocate the counter and
|
|
+ ** initialize it to zero. */
|
|
+ regTrigCnt = ++pParse->nMem;
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regTrigCnt);
|
|
+ VdbeComment((v, "trigger count"));
|
|
+ lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
|
|
+ addrRecheck = lblRecheckOk;
|
|
+ }
|
|
+ }
|
|
+
|
|
/* If rowid is changing, make sure the new rowid does not previously
|
|
** exist in the table.
|
|
*/
|
|
@@ -118525,14 +122023,12 @@
|
|
** to run without a statement journal if there are no indexes on the
|
|
** table.
|
|
*/
|
|
- Trigger *pTrigger = 0;
|
|
- if( db->flags&SQLITE_RecTriggers ){
|
|
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
|
- }
|
|
- if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
|
+ if( regTrigCnt ){
|
|
sqlite3MultiWrite(pParse);
|
|
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
|
regNewData, 1, 0, OE_Replace, 1, -1);
|
|
+ sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
|
|
+ nReplaceTrig++;
|
|
}else{
|
|
#ifdef SQLITE_ENABLE_PREUPDATE_HOOK
|
|
assert( HasRowid(pTab) );
|
|
@@ -118582,6 +122078,7 @@
|
|
int regR; /* Range of registers holding conflicting PK */
|
|
int iThisCur; /* Cursor for this UNIQUE index */
|
|
int addrUniqueOk; /* Jump here if the UNIQUE constraint is satisfied */
|
|
+ int addrConflictCk; /* First opcode in the conflict check logic */
|
|
|
|
if( aRegIdx[ix]==0 ) continue; /* Skip indices that do not change */
|
|
if( pUpIdx==pIdx ){
|
|
@@ -118596,7 +122093,7 @@
|
|
sqlite3TableAffinity(v, pTab, regNewData+1);
|
|
bAffinityDone = 1;
|
|
}
|
|
- VdbeNoopComment((v, "uniqueness check for %s", pIdx->zName));
|
|
+ VdbeNoopComment((v, "prep index %s", pIdx->zName));
|
|
iThisCur = iIdxCur+ix;
|
|
|
|
|
|
@@ -118621,14 +122118,15 @@
|
|
sqlite3ExprCodeCopy(pParse, pIdx->aColExpr->a[i].pExpr, regIdx+i);
|
|
pParse->iSelfTab = 0;
|
|
VdbeComment((v, "%s column %d", pIdx->zName, i));
|
|
+ }else if( iField==XN_ROWID || iField==pTab->iPKey ){
|
|
+ x = regNewData;
|
|
+ sqlite3VdbeAddOp2(v, OP_IntCopy, x, regIdx+i);
|
|
+ VdbeComment((v, "rowid"));
|
|
}else{
|
|
- if( iField==XN_ROWID || iField==pTab->iPKey ){
|
|
- x = regNewData;
|
|
- }else{
|
|
- x = iField + regNewData + 1;
|
|
- }
|
|
- sqlite3VdbeAddOp2(v, iField<0 ? OP_IntCopy : OP_SCopy, x, regIdx+i);
|
|
- VdbeComment((v, "%s", iField<0 ? "rowid" : pTab->aCol[iField].zName));
|
|
+ testcase( sqlite3TableColumnToStorage(pTab, iField)!=iField );
|
|
+ x = sqlite3TableColumnToStorage(pTab, iField) + regNewData + 1;
|
|
+ sqlite3VdbeAddOp2(v, OP_SCopy, x, regIdx+i);
|
|
+ VdbeComment((v, "%s", pTab->aCol[iField].zName));
|
|
}
|
|
}
|
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn, aRegIdx[ix]);
|
|
@@ -118638,6 +122136,7 @@
|
|
sqlite3SetMakeRecordP5(v, pIdx->pTable);
|
|
}
|
|
#endif
|
|
+ sqlite3VdbeReleaseRegisters(pParse, regIdx, pIdx->nColumn, 0, 0);
|
|
|
|
/* In an UPDATE operation, if this index is the PRIMARY KEY index
|
|
** of a WITHOUT ROWID table and there has been no change the
|
|
@@ -118695,8 +122194,9 @@
|
|
|
|
/* Check to see if the new index entry will be unique */
|
|
sqlite3VdbeVerifyAbortable(v, onError);
|
|
- sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
|
|
- regIdx, pIdx->nKeyCol); VdbeCoverage(v);
|
|
+ addrConflictCk =
|
|
+ sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
|
|
+ regIdx, pIdx->nKeyCol); VdbeCoverage(v);
|
|
|
|
/* Generate code to handle collisions */
|
|
regR = (pIdx==pPk) ? regIdx : sqlite3GetTempRange(pParse, nPkField);
|
|
@@ -118717,7 +122217,7 @@
|
|
if( pIdx!=pPk ){
|
|
for(i=0; i<pPk->nKeyCol; i++){
|
|
assert( pPk->aiColumn[i]>=0 );
|
|
- x = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
|
|
+ x = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
|
|
sqlite3VdbeAddOp3(v, OP_Column, iThisCur, x, regR+i);
|
|
VdbeComment((v, "%s.%s", pTab->zName,
|
|
pTab->aCol[pPk->aiColumn[i]].zName));
|
|
@@ -118743,6 +122243,7 @@
|
|
addrJump = addrUniqueOk;
|
|
op = OP_Eq;
|
|
}
|
|
+ x = sqlite3TableColumnToStorage(pTab, x);
|
|
sqlite3VdbeAddOp4(v, op,
|
|
regOldData+1+x, addrJump, regCmp+i, p4, P4_COLLSEQ
|
|
);
|
|
@@ -118779,17 +122280,73 @@
|
|
break;
|
|
}
|
|
default: {
|
|
- Trigger *pTrigger = 0;
|
|
+ int nConflictCk; /* Number of opcodes in conflict check logic */
|
|
+
|
|
assert( onError==OE_Replace );
|
|
- if( db->flags&SQLITE_RecTriggers ){
|
|
- pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
|
- }
|
|
- if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
|
+ nConflictCk = sqlite3VdbeCurrentAddr(v) - addrConflictCk;
|
|
+ assert( nConflictCk>0 );
|
|
+ testcase( nConflictCk>1 );
|
|
+ if( regTrigCnt ){
|
|
sqlite3MultiWrite(pParse);
|
|
+ nReplaceTrig++;
|
|
+ }
|
|
+ if( pTrigger && isUpdate ){
|
|
+ sqlite3VdbeAddOp1(v, OP_CursorLock, iDataCur);
|
|
}
|
|
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
|
regR, nPkField, 0, OE_Replace,
|
|
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
|
|
+ if( pTrigger && isUpdate ){
|
|
+ sqlite3VdbeAddOp1(v, OP_CursorUnlock, iDataCur);
|
|
+ }
|
|
+ if( regTrigCnt ){
|
|
+ int addrBypass; /* Jump destination to bypass recheck logic */
|
|
+
|
|
+ sqlite3VdbeAddOp2(v, OP_AddImm, regTrigCnt, 1); /* incr trigger cnt */
|
|
+ addrBypass = sqlite3VdbeAddOp0(v, OP_Goto); /* Bypass recheck */
|
|
+ VdbeComment((v, "bypass recheck"));
|
|
+
|
|
+ /* Here we insert code that will be invoked after all constraint
|
|
+ ** checks have run, if and only if one or more replace triggers
|
|
+ ** fired. */
|
|
+ sqlite3VdbeResolveLabel(v, lblRecheckOk);
|
|
+ lblRecheckOk = sqlite3VdbeMakeLabel(pParse);
|
|
+ if( pIdx->pPartIdxWhere ){
|
|
+ /* Bypass the recheck if this partial index is not defined
|
|
+ ** for the current row */
|
|
+ sqlite3VdbeAddOp2(v, OP_IsNull, regIdx-1, lblRecheckOk);
|
|
+ VdbeCoverage(v);
|
|
+ }
|
|
+ /* Copy the constraint check code from above, except change
|
|
+ ** the constraint-ok jump destination to be the address of
|
|
+ ** the next retest block */
|
|
+ while( nConflictCk>0 ){
|
|
+ VdbeOp x; /* Conflict check opcode to copy */
|
|
+ /* The sqlite3VdbeAddOp4() call might reallocate the opcode array.
|
|
+ ** Hence, make a complete copy of the opcode, rather than using
|
|
+ ** a pointer to the opcode. */
|
|
+ x = *sqlite3VdbeGetOp(v, addrConflictCk);
|
|
+ if( x.opcode!=OP_IdxRowid ){
|
|
+ int p2; /* New P2 value for copied conflict check opcode */
|
|
+ const char *zP4;
|
|
+ if( sqlite3OpcodeProperty[x.opcode]&OPFLG_JUMP ){
|
|
+ p2 = lblRecheckOk;
|
|
+ }else{
|
|
+ p2 = x.p2;
|
|
+ }
|
|
+ zP4 = x.p4type==P4_INT32 ? SQLITE_INT_TO_PTR(x.p4.i) : x.p4.z;
|
|
+ sqlite3VdbeAddOp4(v, x.opcode, x.p1, p2, x.p3, zP4, x.p4type);
|
|
+ sqlite3VdbeChangeP5(v, x.p5);
|
|
+ VdbeCoverageIf(v, p2!=x.p2);
|
|
+ }
|
|
+ nConflictCk--;
|
|
+ addrConflictCk++;
|
|
+ }
|
|
+ /* If the retest fails, issue an abort */
|
|
+ sqlite3UniqueConstraint(pParse, OE_Abort, pIdx);
|
|
+
|
|
+ sqlite3VdbeJumpHere(v, addrBypass); /* Terminate the recheck bypass */
|
|
+ }
|
|
seenReplace = 1;
|
|
break;
|
|
}
|
|
@@ -118810,10 +122367,30 @@
|
|
sqlite3VdbeJumpHere(v, ipkBottom);
|
|
}
|
|
|
|
+ /* Recheck all uniqueness constraints after replace triggers have run */
|
|
+ testcase( regTrigCnt!=0 && nReplaceTrig==0 );
|
|
+ assert( regTrigCnt!=0 || nReplaceTrig==0 );
|
|
+ if( nReplaceTrig ){
|
|
+ sqlite3VdbeAddOp2(v, OP_IfNot, regTrigCnt, lblRecheckOk);VdbeCoverage(v);
|
|
+ if( !pPk ){
|
|
+ if( isUpdate ){
|
|
+ sqlite3VdbeAddOp3(v, OP_Eq, regNewData, addrRecheck, regOldData);
|
|
+ sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
|
+ VdbeCoverage(v);
|
|
+ }
|
|
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRecheck, regNewData);
|
|
+ VdbeCoverage(v);
|
|
+ sqlite3RowidConstraint(pParse, OE_Abort, pTab);
|
|
+ }else{
|
|
+ sqlite3VdbeGoto(v, addrRecheck);
|
|
+ }
|
|
+ sqlite3VdbeResolveLabel(v, lblRecheckOk);
|
|
+ }
|
|
+
|
|
/* Generate the table record */
|
|
if( HasRowid(pTab) ){
|
|
int regRec = aRegIdx[ix];
|
|
- sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nCol, regRec);
|
|
+ sqlite3VdbeAddOp3(v, OP_MakeRecord, regNewData+1, pTab->nNVCol, regRec);
|
|
sqlite3SetMakeRecordP5(v, pTab);
|
|
if( !bAffinityDone ){
|
|
sqlite3TableAffinity(v, pTab, 0);
|
|
@@ -118880,6 +122457,10 @@
|
|
assert( v!=0 );
|
|
assert( pTab->pSelect==0 ); /* This table is not a VIEW */
|
|
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
|
|
+ /* All REPLACE indexes are at the end of the list */
|
|
+ assert( pIdx->onError!=OE_Replace
|
|
+ || pIdx->pNext==0
|
|
+ || pIdx->pNext->onError==OE_Replace );
|
|
if( aRegIdx[i]==0 ) continue;
|
|
if( pIdx->pPartIdxWhere ){
|
|
sqlite3VdbeAddOp2(v, OP_IsNull, aRegIdx[i], sqlite3VdbeCurrentAddr(v)+2);
|
|
@@ -119030,7 +122611,7 @@
|
|
int i;
|
|
assert( pDest && pSrc );
|
|
assert( pDest->pTable!=pSrc->pTable );
|
|
- if( pDest->nKeyCol!=pSrc->nKeyCol ){
|
|
+ if( pDest->nKeyCol!=pSrc->nKeyCol || pDest->nColumn!=pSrc->nColumn ){
|
|
return 0; /* Different number of columns */
|
|
}
|
|
if( pDest->onError!=pSrc->onError ){
|
|
@@ -119207,6 +122788,39 @@
|
|
){
|
|
return 0; /* Neither table may have __hidden__ columns */
|
|
}
|
|
+#endif
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ /* Even if tables t1 and t2 have identical schemas, if they contain
|
|
+ ** generated columns, then this statement is semantically incorrect:
|
|
+ **
|
|
+ ** INSERT INTO t2 SELECT * FROM t1;
|
|
+ **
|
|
+ ** The reason is that generated column values are returned by the
|
|
+ ** the SELECT statement on the right but the INSERT statement on the
|
|
+ ** left wants them to be omitted.
|
|
+ **
|
|
+ ** Nevertheless, this is a useful notational shorthand to tell SQLite
|
|
+ ** to do a bulk transfer all of the content from t1 over to t2.
|
|
+ **
|
|
+ ** We could, in theory, disable this (except for internal use by the
|
|
+ ** VACUUM command where it is actually needed). But why do that? It
|
|
+ ** seems harmless enough, and provides a useful service.
|
|
+ */
|
|
+ if( (pDestCol->colFlags & COLFLAG_GENERATED) !=
|
|
+ (pSrcCol->colFlags & COLFLAG_GENERATED) ){
|
|
+ return 0; /* Both columns have the same generated-column type */
|
|
+ }
|
|
+ /* But the transfer is only allowed if both the source and destination
|
|
+ ** tables have the exact same expressions for generated columns.
|
|
+ ** This requirement could be relaxed for VIRTUAL columns, I suppose.
|
|
+ */
|
|
+ if( (pDestCol->colFlags & COLFLAG_GENERATED)!=0 ){
|
|
+ if( sqlite3ExprCompare(0, pSrcCol->pDflt, pDestCol->pDflt, -1)!=0 ){
|
|
+ testcase( pDestCol->colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pDestCol->colFlags & COLFLAG_STORED );
|
|
+ return 0; /* Different generator expressions */
|
|
+ }
|
|
+ }
|
|
#endif
|
|
if( pDestCol->affinity!=pSrcCol->affinity ){
|
|
return 0; /* Affinity must be the same on all columns */
|
|
@@ -119218,7 +122832,7 @@
|
|
return 0; /* tab2 must be NOT NULL if tab1 is */
|
|
}
|
|
/* Default values for second and subsequent columns need to match. */
|
|
- if( i>0 ){
|
|
+ if( (pDestCol->colFlags & COLFLAG_GENERATED)==0 && i>0 ){
|
|
assert( pDestCol->pDflt==0 || pDestCol->pDflt->op==TK_SPAN );
|
|
assert( pSrcCol->pDflt==0 || pSrcCol->pDflt->op==TK_SPAN );
|
|
if( (pDestCol->pDflt==0)!=(pSrcCol->pDflt==0)
|
|
@@ -119329,14 +122943,13 @@
|
|
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
|
|
assert( (pDest->tabFlags & TF_Autoincrement)==0 );
|
|
}
|
|
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
|
if( db->mDbFlags & DBFLAG_Vacuum ){
|
|
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
|
|
- insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|
|
|
- OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
|
|
+ insFlags = OPFLAG_APPEND|OPFLAG_USESEEKRESULT;
|
|
}else{
|
|
insFlags = OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND;
|
|
}
|
|
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
|
sqlite3VdbeAddOp4(v, OP_Insert, iDest, regData, regRowid,
|
|
(char*)pDest, P4_TABLE);
|
|
sqlite3VdbeChangeP5(v, insFlags);
|
|
@@ -119361,7 +122974,6 @@
|
|
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR);
|
|
VdbeComment((v, "%s", pDestIdx->zName));
|
|
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
|
|
- sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
|
if( db->mDbFlags & DBFLAG_Vacuum ){
|
|
/* This INSERT command is part of a VACUUM operation, which guarantees
|
|
** that the destination table is empty. If all indexed columns use
|
|
@@ -119385,10 +122997,10 @@
|
|
idxInsFlags = OPFLAG_USESEEKRESULT;
|
|
sqlite3VdbeAddOp1(v, OP_SeekEnd, iDest);
|
|
}
|
|
- }
|
|
- if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
|
|
+ }else if( !HasRowid(pSrc) && pDestIdx->idxType==SQLITE_IDXTYPE_PRIMARYKEY ){
|
|
idxInsFlags |= OPFLAG_NCHANGE;
|
|
}
|
|
+ sqlite3VdbeAddOp3(v, OP_RowData, iSrc, regData, 1);
|
|
sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, regData);
|
|
sqlite3VdbeChangeP5(v, idxInsFlags|OPFLAG_APPEND);
|
|
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
|
|
@@ -119901,6 +123513,19 @@
|
|
/* Version 3.28.0 and later */
|
|
int (*stmt_isexplain)(sqlite3_stmt*);
|
|
int (*value_frombind)(sqlite3_value*);
|
|
+ /* Version 3.30.0 and later */
|
|
+ int (*drop_modules)(sqlite3*,const char**);
|
|
+ /* Version 3.31.0 and later */
|
|
+ sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
|
|
+ const char *(*uri_key)(const char*,int);
|
|
+ const char *(*filename_database)(const char*);
|
|
+ const char *(*filename_journal)(const char*);
|
|
+ const char *(*filename_wal)(const char*);
|
|
+ /* Version 3.32.0 and later */
|
|
+ char *(*create_filename)(const char*,const char*,const char*,
|
|
+ int,const char**);
|
|
+ void (*free_filename)(char*);
|
|
+ sqlite3_file *(*database_file_object)(const char*);
|
|
};
|
|
|
|
/*
|
|
@@ -120191,8 +123816,20 @@
|
|
/* Version 3.26.0 and later */
|
|
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
|
/* Version 3.28.0 and later */
|
|
-#define sqlite3_stmt_isexplain sqlite3_api->isexplain
|
|
-#define sqlite3_value_frombind sqlite3_api->frombind
|
|
+#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
|
|
+#define sqlite3_value_frombind sqlite3_api->value_frombind
|
|
+/* Version 3.30.0 and later */
|
|
+#define sqlite3_drop_modules sqlite3_api->drop_modules
|
|
+/* Version 3.31.0 and later */
|
|
+#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
|
+#define sqlite3_uri_key sqlite3_api->uri_key
|
|
+#define sqlite3_filename_database sqlite3_api->filename_database
|
|
+#define sqlite3_filename_journal sqlite3_api->filename_journal
|
|
+#define sqlite3_filename_wal sqlite3_api->filename_wal
|
|
+/* Version 3.32.0 and later */
|
|
+#define sqlite3_create_filename sqlite3_api->create_filename
|
|
+#define sqlite3_free_filename sqlite3_api->free_filename
|
|
+#define sqlite3_database_file_object sqlite3_api->database_file_object
|
|
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
|
|
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
@@ -120658,9 +124295,33 @@
|
|
#endif
|
|
/* Version 3.28.0 and later */
|
|
sqlite3_stmt_isexplain,
|
|
- sqlite3_value_frombind
|
|
+ sqlite3_value_frombind,
|
|
+ /* Version 3.30.0 and later */
|
|
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
+ sqlite3_drop_modules,
|
|
+#else
|
|
+ 0,
|
|
+#endif
|
|
+ /* Version 3.31.0 and later */
|
|
+ sqlite3_hard_heap_limit64,
|
|
+ sqlite3_uri_key,
|
|
+ sqlite3_filename_database,
|
|
+ sqlite3_filename_journal,
|
|
+ sqlite3_filename_wal,
|
|
+ /* Version 3.32.0 and later */
|
|
+ sqlite3_create_filename,
|
|
+ sqlite3_free_filename,
|
|
+ sqlite3_database_file_object,
|
|
};
|
|
|
|
+/* True if x is the directory separator character
|
|
+*/
|
|
+#if SQLITE_OS_WIN
|
|
+# define DirSep(X) ((X)=='/'||(X)=='\\')
|
|
+#else
|
|
+# define DirSep(X) ((X)=='/')
|
|
+#endif
|
|
+
|
|
/*
|
|
** Attempt to load an SQLite extension library contained in the file
|
|
** zFile. The entry point is zProc. zProc may be 0 in which case a
|
|
@@ -120762,7 +124423,7 @@
|
|
return SQLITE_NOMEM_BKPT;
|
|
}
|
|
memcpy(zAltEntry, "sqlite3_", 8);
|
|
- for(iFile=ncFile-1; iFile>=0 && zFile[iFile]!='/'; iFile--){}
|
|
+ for(iFile=ncFile-1; iFile>=0 && !DirSep(zFile[iFile]); iFile--){}
|
|
iFile++;
|
|
if( sqlite3_strnicmp(zFile+iFile, "lib", 3)==0 ) iFile += 3;
|
|
for(iEntry=8; (c = zFile[iFile])!=0 && c!='.'; iFile++){
|
|
@@ -121065,50 +124726,51 @@
|
|
*/
|
|
|
|
/* The various pragma types */
|
|
-#define PragTyp_HEADER_VALUE 0
|
|
-#define PragTyp_AUTO_VACUUM 1
|
|
-#define PragTyp_FLAG 2
|
|
-#define PragTyp_BUSY_TIMEOUT 3
|
|
-#define PragTyp_CACHE_SIZE 4
|
|
-#define PragTyp_CACHE_SPILL 5
|
|
-#define PragTyp_CASE_SENSITIVE_LIKE 6
|
|
-#define PragTyp_COLLATION_LIST 7
|
|
-#define PragTyp_COMPILE_OPTIONS 8
|
|
-#define PragTyp_DATA_STORE_DIRECTORY 9
|
|
-#define PragTyp_DATABASE_LIST 10
|
|
-#define PragTyp_DEFAULT_CACHE_SIZE 11
|
|
-#define PragTyp_ENCODING 12
|
|
-#define PragTyp_FOREIGN_KEY_CHECK 13
|
|
-#define PragTyp_FOREIGN_KEY_LIST 14
|
|
-#define PragTyp_FUNCTION_LIST 15
|
|
-#define PragTyp_INCREMENTAL_VACUUM 16
|
|
-#define PragTyp_INDEX_INFO 17
|
|
-#define PragTyp_INDEX_LIST 18
|
|
-#define PragTyp_INTEGRITY_CHECK 19
|
|
-#define PragTyp_JOURNAL_MODE 20
|
|
-#define PragTyp_JOURNAL_SIZE_LIMIT 21
|
|
-#define PragTyp_LOCK_PROXY_FILE 22
|
|
-#define PragTyp_LOCKING_MODE 23
|
|
-#define PragTyp_PAGE_COUNT 24
|
|
-#define PragTyp_MMAP_SIZE 25
|
|
-#define PragTyp_MODULE_LIST 26
|
|
-#define PragTyp_OPTIMIZE 27
|
|
-#define PragTyp_PAGE_SIZE 28
|
|
-#define PragTyp_PRAGMA_LIST 29
|
|
-#define PragTyp_SECURE_DELETE 30
|
|
-#define PragTyp_SHRINK_MEMORY 31
|
|
-#define PragTyp_SOFT_HEAP_LIMIT 32
|
|
-#define PragTyp_SYNCHRONOUS 33
|
|
-#define PragTyp_TABLE_INFO 34
|
|
-#define PragTyp_TEMP_STORE 35
|
|
-#define PragTyp_TEMP_STORE_DIRECTORY 36
|
|
-#define PragTyp_THREADS 37
|
|
-#define PragTyp_WAL_AUTOCHECKPOINT 38
|
|
-#define PragTyp_WAL_CHECKPOINT 39
|
|
-#define PragTyp_ACTIVATE_EXTENSIONS 40
|
|
-#define PragTyp_KEY 41
|
|
-#define PragTyp_LOCK_STATUS 42
|
|
-#define PragTyp_STATS 43
|
|
+#define PragTyp_ACTIVATE_EXTENSIONS 0
|
|
+#define PragTyp_ANALYSIS_LIMIT 1
|
|
+#define PragTyp_HEADER_VALUE 2
|
|
+#define PragTyp_AUTO_VACUUM 3
|
|
+#define PragTyp_FLAG 4
|
|
+#define PragTyp_BUSY_TIMEOUT 5
|
|
+#define PragTyp_CACHE_SIZE 6
|
|
+#define PragTyp_CACHE_SPILL 7
|
|
+#define PragTyp_CASE_SENSITIVE_LIKE 8
|
|
+#define PragTyp_COLLATION_LIST 9
|
|
+#define PragTyp_COMPILE_OPTIONS 10
|
|
+#define PragTyp_DATA_STORE_DIRECTORY 11
|
|
+#define PragTyp_DATABASE_LIST 12
|
|
+#define PragTyp_DEFAULT_CACHE_SIZE 13
|
|
+#define PragTyp_ENCODING 14
|
|
+#define PragTyp_FOREIGN_KEY_CHECK 15
|
|
+#define PragTyp_FOREIGN_KEY_LIST 16
|
|
+#define PragTyp_FUNCTION_LIST 17
|
|
+#define PragTyp_HARD_HEAP_LIMIT 18
|
|
+#define PragTyp_INCREMENTAL_VACUUM 19
|
|
+#define PragTyp_INDEX_INFO 20
|
|
+#define PragTyp_INDEX_LIST 21
|
|
+#define PragTyp_INTEGRITY_CHECK 22
|
|
+#define PragTyp_JOURNAL_MODE 23
|
|
+#define PragTyp_JOURNAL_SIZE_LIMIT 24
|
|
+#define PragTyp_LOCK_PROXY_FILE 25
|
|
+#define PragTyp_LOCKING_MODE 26
|
|
+#define PragTyp_PAGE_COUNT 27
|
|
+#define PragTyp_MMAP_SIZE 28
|
|
+#define PragTyp_MODULE_LIST 29
|
|
+#define PragTyp_OPTIMIZE 30
|
|
+#define PragTyp_PAGE_SIZE 31
|
|
+#define PragTyp_PRAGMA_LIST 32
|
|
+#define PragTyp_SECURE_DELETE 33
|
|
+#define PragTyp_SHRINK_MEMORY 34
|
|
+#define PragTyp_SOFT_HEAP_LIMIT 35
|
|
+#define PragTyp_SYNCHRONOUS 36
|
|
+#define PragTyp_TABLE_INFO 37
|
|
+#define PragTyp_TEMP_STORE 38
|
|
+#define PragTyp_TEMP_STORE_DIRECTORY 39
|
|
+#define PragTyp_THREADS 40
|
|
+#define PragTyp_WAL_AUTOCHECKPOINT 41
|
|
+#define PragTyp_WAL_CHECKPOINT 42
|
|
+#define PragTyp_LOCK_STATUS 43
|
|
+#define PragTyp_STATS 44
|
|
|
|
/* Property flags associated with various pragma. */
|
|
#define PragFlg_NeedSchema 0x01 /* Force schema load before running */
|
|
@@ -121147,35 +124809,39 @@
|
|
/* 18 */ "desc",
|
|
/* 19 */ "coll",
|
|
/* 20 */ "key",
|
|
- /* 21 */ "tbl", /* Used by: stats */
|
|
- /* 22 */ "idx",
|
|
- /* 23 */ "wdth",
|
|
- /* 24 */ "hght",
|
|
- /* 25 */ "flgs",
|
|
- /* 26 */ "seq", /* Used by: index_list */
|
|
- /* 27 */ "name",
|
|
- /* 28 */ "unique",
|
|
- /* 29 */ "origin",
|
|
- /* 30 */ "partial",
|
|
- /* 31 */ "table", /* Used by: foreign_key_check */
|
|
- /* 32 */ "rowid",
|
|
- /* 33 */ "parent",
|
|
- /* 34 */ "fkid",
|
|
+ /* 21 */ "name", /* Used by: function_list */
|
|
+ /* 22 */ "builtin",
|
|
+ /* 23 */ "type",
|
|
+ /* 24 */ "enc",
|
|
+ /* 25 */ "narg",
|
|
+ /* 26 */ "flags",
|
|
+ /* 27 */ "tbl", /* Used by: stats */
|
|
+ /* 28 */ "idx",
|
|
+ /* 29 */ "wdth",
|
|
+ /* 30 */ "hght",
|
|
+ /* 31 */ "flgs",
|
|
+ /* 32 */ "seq", /* Used by: index_list */
|
|
+ /* 33 */ "name",
|
|
+ /* 34 */ "unique",
|
|
+ /* 35 */ "origin",
|
|
+ /* 36 */ "partial",
|
|
+ /* 37 */ "table", /* Used by: foreign_key_check */
|
|
+ /* 38 */ "rowid",
|
|
+ /* 39 */ "parent",
|
|
+ /* 40 */ "fkid",
|
|
/* index_info reuses 15 */
|
|
- /* 35 */ "seq", /* Used by: database_list */
|
|
- /* 36 */ "name",
|
|
- /* 37 */ "file",
|
|
- /* 38 */ "busy", /* Used by: wal_checkpoint */
|
|
- /* 39 */ "log",
|
|
- /* 40 */ "checkpointed",
|
|
- /* 41 */ "name", /* Used by: function_list */
|
|
- /* 42 */ "builtin",
|
|
- /* collation_list reuses 26 */
|
|
- /* 43 */ "database", /* Used by: lock_status */
|
|
- /* 44 */ "status",
|
|
- /* 45 */ "cache_size", /* Used by: default_cache_size */
|
|
+ /* 41 */ "seq", /* Used by: database_list */
|
|
+ /* 42 */ "name",
|
|
+ /* 43 */ "file",
|
|
+ /* 44 */ "busy", /* Used by: wal_checkpoint */
|
|
+ /* 45 */ "log",
|
|
+ /* 46 */ "checkpointed",
|
|
+ /* collation_list reuses 32 */
|
|
+ /* 47 */ "database", /* Used by: lock_status */
|
|
+ /* 48 */ "status",
|
|
+ /* 49 */ "cache_size", /* Used by: default_cache_size */
|
|
/* module_list pragma_list reuses 9 */
|
|
- /* 46 */ "timeout", /* Used by: busy_timeout */
|
|
+ /* 50 */ "timeout", /* Used by: busy_timeout */
|
|
};
|
|
|
|
/* Definitions of all built-in pragmas */
|
|
@@ -121188,13 +124854,18 @@
|
|
u64 iArg; /* Extra argument */
|
|
} PragmaName;
|
|
static const PragmaName aPragmaName[] = {
|
|
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
|
|
+#if defined(SQLITE_ENABLE_CEROD)
|
|
{/* zName: */ "activate_extensions",
|
|
/* ePragTyp: */ PragTyp_ACTIVATE_EXTENSIONS,
|
|
/* ePragFlg: */ 0,
|
|
/* ColNames: */ 0, 0,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
+ {/* zName: */ "analysis_limit",
|
|
+ /* ePragTyp: */ PragTyp_ANALYSIS_LIMIT,
|
|
+ /* ePragFlg: */ PragFlg_Result0,
|
|
+ /* ColNames: */ 0, 0,
|
|
+ /* iArg: */ 0 },
|
|
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
|
{/* zName: */ "application_id",
|
|
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
|
@@ -121221,7 +124892,7 @@
|
|
{/* zName: */ "busy_timeout",
|
|
/* ePragTyp: */ PragTyp_BUSY_TIMEOUT,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
- /* ColNames: */ 46, 1,
|
|
+ /* ColNames: */ 50, 1,
|
|
/* iArg: */ 0 },
|
|
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
|
{/* zName: */ "cache_size",
|
|
@@ -121260,7 +124931,7 @@
|
|
{/* zName: */ "collation_list",
|
|
/* ePragTyp: */ PragTyp_COLLATION_LIST,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
- /* ColNames: */ 26, 2,
|
|
+ /* ColNames: */ 32, 2,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_COMPILEOPTION_DIAGS)
|
|
@@ -121295,14 +124966,14 @@
|
|
{/* zName: */ "database_list",
|
|
/* ePragTyp: */ PragTyp_DATABASE_LIST,
|
|
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
|
|
- /* ColNames: */ 35, 3,
|
|
+ /* ColNames: */ 41, 3,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
|
|
{/* zName: */ "default_cache_size",
|
|
/* ePragTyp: */ PragTyp_DEFAULT_CACHE_SIZE,
|
|
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq|PragFlg_NoColumns1,
|
|
- /* ColNames: */ 45, 1,
|
|
+ /* ColNames: */ 49, 1,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
|
@@ -121332,7 +125003,7 @@
|
|
{/* zName: */ "foreign_key_check",
|
|
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
|
|
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
|
|
- /* ColNames: */ 31, 4,
|
|
+ /* ColNames: */ 37, 4,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_FOREIGN_KEY)
|
|
@@ -121371,26 +125042,19 @@
|
|
/* iArg: */ SQLITE_FullFSync },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
|
-#if defined(SQLITE_INTROSPECTION_PRAGMAS)
|
|
+#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
|
|
{/* zName: */ "function_list",
|
|
/* ePragTyp: */ PragTyp_FUNCTION_LIST,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
- /* ColNames: */ 41, 2,
|
|
+ /* ColNames: */ 21, 6,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#endif
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- {/* zName: */ "hexkey",
|
|
- /* ePragTyp: */ PragTyp_KEY,
|
|
- /* ePragFlg: */ 0,
|
|
- /* ColNames: */ 0, 0,
|
|
- /* iArg: */ 2 },
|
|
- {/* zName: */ "hexrekey",
|
|
- /* ePragTyp: */ PragTyp_KEY,
|
|
- /* ePragFlg: */ 0,
|
|
+ {/* zName: */ "hard_heap_limit",
|
|
+ /* ePragTyp: */ PragTyp_HARD_HEAP_LIMIT,
|
|
+ /* ePragFlg: */ PragFlg_Result0,
|
|
/* ColNames: */ 0, 0,
|
|
- /* iArg: */ 3 },
|
|
-#endif
|
|
+ /* iArg: */ 0 },
|
|
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
|
#if !defined(SQLITE_OMIT_CHECK)
|
|
{/* zName: */ "ignore_check_constraints",
|
|
@@ -121416,7 +125080,7 @@
|
|
{/* zName: */ "index_list",
|
|
/* ePragTyp: */ PragTyp_INDEX_LIST,
|
|
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result1|PragFlg_SchemaOpt,
|
|
- /* ColNames: */ 26, 5,
|
|
+ /* ColNames: */ 32, 5,
|
|
/* iArg: */ 0 },
|
|
{/* zName: */ "index_xinfo",
|
|
/* ePragTyp: */ PragTyp_INDEX_INFO,
|
|
@@ -121443,24 +125107,12 @@
|
|
/* ColNames: */ 0, 0,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- {/* zName: */ "key",
|
|
- /* ePragTyp: */ PragTyp_KEY,
|
|
- /* ePragFlg: */ 0,
|
|
- /* ColNames: */ 0, 0,
|
|
- /* iArg: */ 0 },
|
|
-#endif
|
|
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
|
{/* zName: */ "legacy_alter_table",
|
|
/* ePragTyp: */ PragTyp_FLAG,
|
|
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
|
/* ColNames: */ 0, 0,
|
|
/* iArg: */ SQLITE_LegacyAlter },
|
|
- {/* zName: */ "legacy_file_format",
|
|
- /* ePragTyp: */ PragTyp_FLAG,
|
|
- /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
|
- /* ColNames: */ 0, 0,
|
|
- /* iArg: */ SQLITE_LegacyFileFmt },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && SQLITE_ENABLE_LOCKING_STYLE
|
|
{/* zName: */ "lock_proxy_file",
|
|
@@ -121473,7 +125125,7 @@
|
|
{/* zName: */ "lock_status",
|
|
/* ePragTyp: */ PragTyp_LOCK_STATUS,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
- /* ColNames: */ 43, 2,
|
|
+ /* ColNames: */ 47, 2,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
|
@@ -121495,7 +125147,7 @@
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
-#if defined(SQLITE_INTROSPECTION_PRAGMAS)
|
|
+#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
|
|
{/* zName: */ "module_list",
|
|
/* ePragTyp: */ PragTyp_MODULE_LIST,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
@@ -121530,7 +125182,7 @@
|
|
/* iArg: */ SQLITE_ParserTrace },
|
|
#endif
|
|
#endif
|
|
-#if defined(SQLITE_INTROSPECTION_PRAGMAS)
|
|
+#if !defined(SQLITE_OMIT_INTROSPECTION_PRAGMAS)
|
|
{/* zName: */ "pragma_list",
|
|
/* ePragTyp: */ PragTyp_PRAGMA_LIST,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
@@ -121562,15 +125214,6 @@
|
|
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
|
/* ColNames: */ 0, 0,
|
|
/* iArg: */ SQLITE_RecTriggers },
|
|
-#endif
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- {/* zName: */ "rekey",
|
|
- /* ePragTyp: */ PragTyp_KEY,
|
|
- /* ePragFlg: */ 0,
|
|
- /* ColNames: */ 0, 0,
|
|
- /* iArg: */ 1 },
|
|
-#endif
|
|
-#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
|
{/* zName: */ "reverse_unordered_selects",
|
|
/* ePragTyp: */ PragTyp_FLAG,
|
|
/* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
|
@@ -121621,7 +125264,7 @@
|
|
{/* zName: */ "stats",
|
|
/* ePragTyp: */ PragTyp_STATS,
|
|
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_SchemaReq,
|
|
- /* ColNames: */ 21, 5,
|
|
+ /* ColNames: */ 27, 5,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
|
|
@@ -121654,24 +125297,19 @@
|
|
/* ePragFlg: */ PragFlg_NoColumns1,
|
|
/* ColNames: */ 0, 0,
|
|
/* iArg: */ 0 },
|
|
-#endif
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- {/* zName: */ "textkey",
|
|
- /* ePragTyp: */ PragTyp_KEY,
|
|
- /* ePragFlg: */ 0,
|
|
- /* ColNames: */ 0, 0,
|
|
- /* iArg: */ 4 },
|
|
- {/* zName: */ "textrekey",
|
|
- /* ePragTyp: */ PragTyp_KEY,
|
|
- /* ePragFlg: */ 0,
|
|
- /* ColNames: */ 0, 0,
|
|
- /* iArg: */ 5 },
|
|
#endif
|
|
{/* zName: */ "threads",
|
|
/* ePragTyp: */ PragTyp_THREADS,
|
|
/* ePragFlg: */ PragFlg_Result0,
|
|
/* ColNames: */ 0, 0,
|
|
/* iArg: */ 0 },
|
|
+#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
|
+ {/* zName: */ "trusted_schema",
|
|
+ /* ePragTyp: */ PragTyp_FLAG,
|
|
+ /* ePragFlg: */ PragFlg_Result0|PragFlg_NoColumns1,
|
|
+ /* ColNames: */ 0, 0,
|
|
+ /* iArg: */ SQLITE_TrustedSchema },
|
|
+#endif
|
|
#if !defined(SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS)
|
|
{/* zName: */ "user_version",
|
|
/* ePragTyp: */ PragTyp_HEADER_VALUE,
|
|
@@ -121717,7 +125355,7 @@
|
|
{/* zName: */ "wal_checkpoint",
|
|
/* ePragTyp: */ PragTyp_WAL_CHECKPOINT,
|
|
/* ePragFlg: */ PragFlg_NeedSchema,
|
|
- /* ColNames: */ 38, 3,
|
|
+ /* ColNames: */ 44, 3,
|
|
/* iArg: */ 0 },
|
|
#endif
|
|
#if !defined(SQLITE_OMIT_FLAG_PRAGMAS)
|
|
@@ -121728,7 +125366,7 @@
|
|
/* iArg: */ SQLITE_WriteSchema|SQLITE_NoSchemaError },
|
|
#endif
|
|
};
|
|
-/* Number of pragmas: 62 on by default, 81 total. */
|
|
+/* Number of pragmas: 67 on by default, 77 total. */
|
|
|
|
/************** End of pragma.h **********************************************/
|
|
/************** Continuing where we left off in pragma.c *********************/
|
|
@@ -121998,6 +125636,55 @@
|
|
return lwr>upr ? 0 : &aPragmaName[mid];
|
|
}
|
|
|
|
+/*
|
|
+** Create zero or more entries in the output for the SQL functions
|
|
+** defined by FuncDef p.
|
|
+*/
|
|
+static void pragmaFunclistLine(
|
|
+ Vdbe *v, /* The prepared statement being created */
|
|
+ FuncDef *p, /* A particular function definition */
|
|
+ int isBuiltin, /* True if this is a built-in function */
|
|
+ int showInternFuncs /* True if showing internal functions */
|
|
+){
|
|
+ for(; p; p=p->pNext){
|
|
+ const char *zType;
|
|
+ static const u32 mask =
|
|
+ SQLITE_DETERMINISTIC |
|
|
+ SQLITE_DIRECTONLY |
|
|
+ SQLITE_SUBTYPE |
|
|
+ SQLITE_INNOCUOUS |
|
|
+ SQLITE_FUNC_INTERNAL
|
|
+ ;
|
|
+ static const char *azEnc[] = { 0, "utf8", "utf16le", "utf16be" };
|
|
+
|
|
+ assert( SQLITE_FUNC_ENCMASK==0x3 );
|
|
+ assert( strcmp(azEnc[SQLITE_UTF8],"utf8")==0 );
|
|
+ assert( strcmp(azEnc[SQLITE_UTF16LE],"utf16le")==0 );
|
|
+ assert( strcmp(azEnc[SQLITE_UTF16BE],"utf16be")==0 );
|
|
+
|
|
+ if( p->xSFunc==0 ) continue;
|
|
+ if( (p->funcFlags & SQLITE_FUNC_INTERNAL)!=0
|
|
+ && showInternFuncs==0
|
|
+ ){
|
|
+ continue;
|
|
+ }
|
|
+ if( p->xValue!=0 ){
|
|
+ zType = "w";
|
|
+ }else if( p->xFinalize!=0 ){
|
|
+ zType = "a";
|
|
+ }else{
|
|
+ zType = "s";
|
|
+ }
|
|
+ sqlite3VdbeMultiLoad(v, 1, "sissii",
|
|
+ p->zName, isBuiltin,
|
|
+ zType, azEnc[p->funcFlags&SQLITE_FUNC_ENCMASK],
|
|
+ p->nArg,
|
|
+ (p->funcFlags & mask) ^ SQLITE_INNOCUOUS
|
|
+ );
|
|
+ }
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
** Helper subroutine for PRAGMA integrity_check:
|
|
**
|
|
@@ -122209,7 +125896,7 @@
|
|
** buffer that the pager module resizes using sqlite3_realloc().
|
|
*/
|
|
db->nextPagesize = sqlite3Atoi(zRight);
|
|
- if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,-1,0) ){
|
|
+ if( SQLITE_NOMEM==sqlite3BtreeSetPageSize(pBt, db->nextPagesize,0,0) ){
|
|
sqlite3OomFault(db);
|
|
}
|
|
}
|
|
@@ -122803,10 +126490,19 @@
|
|
sqlite3CodeVerifySchema(pParse, iTabDb);
|
|
sqlite3ViewGetColumnNames(pParse, pTab);
|
|
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
|
|
- int isHidden = IsHiddenColumn(pCol);
|
|
- if( isHidden && pPragma->iArg==0 ){
|
|
- nHidden++;
|
|
- continue;
|
|
+ int isHidden = 0;
|
|
+ if( pCol->colFlags & COLFLAG_NOINSERT ){
|
|
+ if( pPragma->iArg==0 ){
|
|
+ nHidden++;
|
|
+ continue;
|
|
+ }
|
|
+ if( pCol->colFlags & COLFLAG_VIRTUAL ){
|
|
+ isHidden = 2; /* GENERATED ALWAYS AS ... VIRTUAL */
|
|
+ }else if( pCol->colFlags & COLFLAG_STORED ){
|
|
+ isHidden = 3; /* GENERATED ALWAYS AS ... STORED */
|
|
+ }else{ assert( pCol->colFlags & COLFLAG_HIDDEN );
|
|
+ isHidden = 1; /* HIDDEN */
|
|
+ }
|
|
}
|
|
if( (pCol->colFlags & COLFLAG_PRIMKEY)==0 ){
|
|
k = 0;
|
|
@@ -122815,13 +126511,13 @@
|
|
}else{
|
|
for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
|
|
}
|
|
- assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN );
|
|
+ assert( pCol->pDflt==0 || pCol->pDflt->op==TK_SPAN || isHidden>=2 );
|
|
sqlite3VdbeMultiLoad(v, 1, pPragma->iArg ? "issisii" : "issisi",
|
|
i-nHidden,
|
|
pCol->zName,
|
|
sqlite3ColumnType(pCol,""),
|
|
pCol->notNull ? 1 : 0,
|
|
- pCol->pDflt ? pCol->pDflt->u.zToken : 0,
|
|
+ pCol->pDflt && isHidden<2 ? pCol->pDflt->u.zToken : 0,
|
|
k,
|
|
isHidden);
|
|
}
|
|
@@ -122860,6 +126556,15 @@
|
|
Index *pIdx;
|
|
Table *pTab;
|
|
pIdx = sqlite3FindIndex(db, zRight, zDb);
|
|
+ if( pIdx==0 ){
|
|
+ /* If there is no index named zRight, check to see if there is a
|
|
+ ** WITHOUT ROWID table named zRight, and if there is, show the
|
|
+ ** structure of the PRIMARY KEY index for that table. */
|
|
+ pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
|
|
+ if( pTab && !HasRowid(pTab) ){
|
|
+ pIdx = sqlite3PrimaryKeyIndex(pTab);
|
|
+ }
|
|
+ }
|
|
if( pIdx ){
|
|
int iIdxDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
|
|
int i;
|
|
@@ -122939,21 +126644,21 @@
|
|
}
|
|
break;
|
|
|
|
-#ifdef SQLITE_INTROSPECTION_PRAGMAS
|
|
+#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
|
|
case PragTyp_FUNCTION_LIST: {
|
|
int i;
|
|
HashElem *j;
|
|
FuncDef *p;
|
|
- pParse->nMem = 2;
|
|
+ int showInternFunc = (db->mDbFlags & DBFLAG_InternalFunc)!=0;
|
|
+ pParse->nMem = 6;
|
|
for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
|
|
for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash ){
|
|
- if( p->funcFlags & SQLITE_FUNC_INTERNAL ) continue;
|
|
- sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 1);
|
|
+ pragmaFunclistLine(v, p, 1, showInternFunc);
|
|
}
|
|
}
|
|
for(j=sqliteHashFirst(&db->aFunc); j; j=sqliteHashNext(j)){
|
|
p = (FuncDef*)sqliteHashData(j);
|
|
- sqlite3VdbeMultiLoad(v, 1, "si", p->zName, 0);
|
|
+ pragmaFunclistLine(v, p, 0, showInternFunc);
|
|
}
|
|
}
|
|
break;
|
|
@@ -123271,7 +126976,7 @@
|
|
loopTop = sqlite3VdbeAddOp2(v, OP_AddImm, 7, 1);
|
|
if( !isQuick ){
|
|
/* Sanity check on record header decoding */
|
|
- sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
|
|
+ sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nNVCol-1,3);
|
|
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
|
}
|
|
/* Verify that all NOT NULL columns really are NOT NULL */
|
|
@@ -123281,7 +126986,9 @@
|
|
if( j==pTab->iPKey ) continue;
|
|
if( pTab->aCol[j].notNull==0 ) continue;
|
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
|
|
- sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
|
+ if( sqlite3VdbeGetOp(v,-1)->opcode==OP_Column ){
|
|
+ sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
|
+ }
|
|
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
|
|
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
|
pTab->aCol[j].zName);
|
|
@@ -123363,7 +127070,6 @@
|
|
}
|
|
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
|
|
sqlite3VdbeJumpHere(v, loopTop-1);
|
|
-#ifndef SQLITE_OMIT_BTREECOUNT
|
|
if( !isQuick ){
|
|
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
|
|
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
|
@@ -123377,7 +127083,6 @@
|
|
sqlite3VdbeJumpHere(v, addr);
|
|
}
|
|
}
|
|
-#endif /* SQLITE_OMIT_BTREECOUNT */
|
|
}
|
|
}
|
|
{
|
|
@@ -123458,14 +127163,12 @@
|
|
** will be overwritten when the schema is next loaded. If it does not
|
|
** already exists, it will be created to use the new encoding value.
|
|
*/
|
|
- if(
|
|
- !(DbHasProperty(db, 0, DB_SchemaLoaded)) ||
|
|
- DbHasProperty(db, 0, DB_Empty)
|
|
- ){
|
|
+ if( (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
|
|
for(pEnc=&encnames[0]; pEnc->zName; pEnc++){
|
|
if( 0==sqlite3StrICmp(zRight, pEnc->zName) ){
|
|
- SCHEMA_ENC(db) = ENC(db) =
|
|
- pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
|
|
+ u8 enc = pEnc->enc ? pEnc->enc : SQLITE_UTF16NATIVE;
|
|
+ SCHEMA_ENC(db) = enc;
|
|
+ sqlite3SetTextEncoding(db, enc);
|
|
break;
|
|
}
|
|
}
|
|
@@ -123774,6 +127477,27 @@
|
|
break;
|
|
}
|
|
|
|
+ /*
|
|
+ ** PRAGMA hard_heap_limit
|
|
+ ** PRAGMA hard_heap_limit = N
|
|
+ **
|
|
+ ** Invoke sqlite3_hard_heap_limit64() to query or set the hard heap
|
|
+ ** limit. The hard heap limit can be activated or lowered by this
|
|
+ ** pragma, but not raised or deactivated. Only the
|
|
+ ** sqlite3_hard_heap_limit64() C-language API can raise or deactivate
|
|
+ ** the hard heap limit. This allows an application to set a heap limit
|
|
+ ** constraint that cannot be relaxed by an untrusted SQL script.
|
|
+ */
|
|
+ case PragTyp_HARD_HEAP_LIMIT: {
|
|
+ sqlite3_int64 N;
|
|
+ if( zRight && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK ){
|
|
+ sqlite3_int64 iPrior = sqlite3_hard_heap_limit64(-1);
|
|
+ if( N>0 && (iPrior==0 || iPrior>N) ) sqlite3_hard_heap_limit64(N);
|
|
+ }
|
|
+ returnSingleInt(v, sqlite3_hard_heap_limit64(-1));
|
|
+ break;
|
|
+ }
|
|
+
|
|
/*
|
|
** PRAGMA threads
|
|
** PRAGMA threads = N
|
|
@@ -123793,6 +127517,25 @@
|
|
break;
|
|
}
|
|
|
|
+ /*
|
|
+ ** PRAGMA analysis_limit
|
|
+ ** PRAGMA analysis_limit = N
|
|
+ **
|
|
+ ** Configure the maximum number of rows that ANALYZE will examine
|
|
+ ** in each index that it looks at. Return the new limit.
|
|
+ */
|
|
+ case PragTyp_ANALYSIS_LIMIT: {
|
|
+ sqlite3_int64 N;
|
|
+ if( zRight
|
|
+ && sqlite3DecOrHexToI64(zRight, &N)==SQLITE_OK
|
|
+ && N>=0
|
|
+ ){
|
|
+ db->nAnalysisLimit = (int)(N&0x7fffffff);
|
|
+ }
|
|
+ returnSingleInt(v, db->nAnalysisLimit);
|
|
+ break;
|
|
+ }
|
|
+
|
|
#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
/*
|
|
** Report the current state of file logs for all databases
|
|
@@ -123821,59 +127564,11 @@
|
|
}
|
|
#endif
|
|
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- /* Pragma iArg
|
|
- ** ---------- ------
|
|
- ** key 0
|
|
- ** rekey 1
|
|
- ** hexkey 2
|
|
- ** hexrekey 3
|
|
- ** textkey 4
|
|
- ** textrekey 5
|
|
- */
|
|
- case PragTyp_KEY: {
|
|
- if( zRight ){
|
|
- char zBuf[40];
|
|
- const char *zKey = zRight;
|
|
- int n;
|
|
- if( pPragma->iArg==2 || pPragma->iArg==3 ){
|
|
- u8 iByte;
|
|
- int i;
|
|
- for(i=0, iByte=0; i<sizeof(zBuf)*2 && sqlite3Isxdigit(zRight[i]); i++){
|
|
- iByte = (iByte<<4) + sqlite3HexToInt(zRight[i]);
|
|
- if( (i&1)!=0 ) zBuf[i/2] = iByte;
|
|
- }
|
|
- zKey = zBuf;
|
|
- n = i/2;
|
|
- }else{
|
|
- n = pPragma->iArg<4 ? sqlite3Strlen30(zRight) : -1;
|
|
- }
|
|
- if( (pPragma->iArg & 1)==0 ){
|
|
- rc = sqlite3_key_v2(db, zDb, zKey, n);
|
|
- }else{
|
|
- rc = sqlite3_rekey_v2(db, zDb, zKey, n);
|
|
- }
|
|
- if( rc==SQLITE_OK && n!=0 ){
|
|
- sqlite3VdbeSetNumCols(v, 1);
|
|
- sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "ok", SQLITE_STATIC);
|
|
- returnSingleText(v, "ok");
|
|
- }
|
|
- }
|
|
- break;
|
|
- }
|
|
-#endif
|
|
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_ENABLE_CEROD)
|
|
+#if defined(SQLITE_ENABLE_CEROD)
|
|
case PragTyp_ACTIVATE_EXTENSIONS: if( zRight ){
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( sqlite3StrNICmp(zRight, "see-", 4)==0 ){
|
|
- sqlite3_activate_see(&zRight[4]);
|
|
- }
|
|
-#endif
|
|
-#ifdef SQLITE_ENABLE_CEROD
|
|
if( sqlite3StrNICmp(zRight, "cerod-", 6)==0 ){
|
|
sqlite3_activate_cerod(&zRight[6]);
|
|
}
|
|
-#endif
|
|
}
|
|
break;
|
|
#endif
|
|
@@ -124267,6 +127962,18 @@
|
|
return 0;
|
|
}
|
|
|
|
+/* forward declaration */
|
|
+static int sqlite3Prepare(
|
|
+ sqlite3 *db, /* Database handle. */
|
|
+ const char *zSql, /* UTF-8 encoded SQL statement. */
|
|
+ int nBytes, /* Length of zSql in bytes. */
|
|
+ u32 prepFlags, /* Zero or more SQLITE_PREPARE_* flags */
|
|
+ Vdbe *pReprepare, /* VM being reprepared */
|
|
+ sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
|
+ const char **pzTail /* OUT: End of parsed string */
|
|
+);
|
|
+
|
|
+
|
|
/*
|
|
** This is the callback routine for the code that initializes the
|
|
** database. See sqlite3Init() below for additional information.
|
|
@@ -124274,9 +127981,11 @@
|
|
**
|
|
** Each callback contains the following information:
|
|
**
|
|
-** argv[0] = name of thing being created
|
|
-** argv[1] = root page number for table or index. 0 for trigger or view.
|
|
-** argv[2] = SQL text for the CREATE statement.
|
|
+** argv[0] = type of object: "table", "index", "trigger", or "view".
|
|
+** argv[1] = name of thing being created
|
|
+** argv[2] = associated table if an index or trigger
|
|
+** argv[3] = root page number for table or index. 0 for trigger or view.
|
|
+** argv[4] = SQL text for the CREATE statement.
|
|
**
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
|
|
@@ -124284,21 +127993,21 @@
|
|
sqlite3 *db = pData->db;
|
|
int iDb = pData->iDb;
|
|
|
|
- assert( argc==3 );
|
|
+ assert( argc==5 );
|
|
UNUSED_PARAMETER2(NotUsed, argc);
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
- DbClearProperty(db, iDb, DB_Empty);
|
|
+ db->mDbFlags |= DBFLAG_EncodingFixed;
|
|
pData->nInitRow++;
|
|
if( db->mallocFailed ){
|
|
- corruptSchema(pData, argv[0], 0);
|
|
+ corruptSchema(pData, argv[1], 0);
|
|
return 1;
|
|
}
|
|
|
|
assert( iDb>=0 && iDb<db->nDb );
|
|
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
|
|
- if( argv[1]==0 ){
|
|
- corruptSchema(pData, argv[0], 0);
|
|
- }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
|
|
+ if( argv[3]==0 ){
|
|
+ corruptSchema(pData, argv[1], 0);
|
|
+ }else if( sqlite3_strnicmp(argv[4],"create ",7)==0 ){
|
|
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
|
|
** But because db->init.busy is set to 1, no VDBE code is generated
|
|
** or executed. All the parser does is build the internal data
|
|
@@ -124311,9 +128020,11 @@
|
|
|
|
assert( db->init.busy );
|
|
db->init.iDb = iDb;
|
|
- db->init.newTnum = sqlite3Atoi(argv[1]);
|
|
+ db->init.newTnum = sqlite3Atoi(argv[3]);
|
|
db->init.orphanTrigger = 0;
|
|
- TESTONLY(rcp = ) sqlite3_prepare(db, argv[2], -1, &pStmt, 0);
|
|
+ db->init.azInit = argv;
|
|
+ pStmt = 0;
|
|
+ TESTONLY(rcp = ) sqlite3Prepare(db, argv[4], -1, 0, 0, &pStmt, 0);
|
|
rc = db->errCode;
|
|
assert( (rc&0xFF)==(rcp&0xFF) );
|
|
db->init.iDb = saved_iDb;
|
|
@@ -124322,17 +128033,17 @@
|
|
if( db->init.orphanTrigger ){
|
|
assert( iDb==1 );
|
|
}else{
|
|
- pData->rc = rc;
|
|
+ if( rc > pData->rc ) pData->rc = rc;
|
|
if( rc==SQLITE_NOMEM ){
|
|
sqlite3OomFault(db);
|
|
}else if( rc!=SQLITE_INTERRUPT && (rc&0xFF)!=SQLITE_LOCKED ){
|
|
- corruptSchema(pData, argv[0], sqlite3_errmsg(db));
|
|
+ corruptSchema(pData, argv[1], sqlite3_errmsg(db));
|
|
}
|
|
}
|
|
}
|
|
sqlite3_finalize(pStmt);
|
|
- }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
|
|
- corruptSchema(pData, argv[0], 0);
|
|
+ }else if( argv[1]==0 || (argv[4]!=0 && argv[4][0]!=0) ){
|
|
+ corruptSchema(pData, argv[1], 0);
|
|
}else{
|
|
/* If the SQL column is blank it means this is an index that
|
|
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
|
|
@@ -124341,13 +128052,13 @@
|
|
** to do here is record the root page number for that index.
|
|
*/
|
|
Index *pIndex;
|
|
- pIndex = sqlite3FindIndex(db, argv[0], db->aDb[iDb].zDbSName);
|
|
+ pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
|
|
if( pIndex==0
|
|
- || sqlite3GetInt32(argv[1],&pIndex->tnum)==0
|
|
+ || sqlite3GetInt32(argv[3],&pIndex->tnum)==0
|
|
|| pIndex->tnum<2
|
|
|| sqlite3IndexHasDuplicateRootPage(pIndex)
|
|
){
|
|
- corruptSchema(pData, argv[0], pIndex?"invalid rootpage":"orphan index");
|
|
+ corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index");
|
|
}
|
|
}
|
|
return 0;
|
|
@@ -124368,11 +128079,12 @@
|
|
int size;
|
|
#endif
|
|
Db *pDb;
|
|
- char const *azArg[4];
|
|
+ char const *azArg[6];
|
|
int meta[5];
|
|
InitData initData;
|
|
const char *zMasterName;
|
|
int openedTransaction = 0;
|
|
+ int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed);
|
|
|
|
assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
|
|
assert( iDb>=0 && iDb<db->nDb );
|
|
@@ -124387,18 +128099,21 @@
|
|
** table name will be inserted automatically by the parser so we can just
|
|
** use the abbreviation "x" here. The parser will also automatically tag
|
|
** the schema table as read-only. */
|
|
- azArg[0] = zMasterName = SCHEMA_TABLE(iDb);
|
|
- azArg[1] = "1";
|
|
- azArg[2] = "CREATE TABLE x(type text,name text,tbl_name text,"
|
|
+ azArg[0] = "table";
|
|
+ azArg[1] = zMasterName = SCHEMA_TABLE(iDb);
|
|
+ azArg[2] = azArg[1];
|
|
+ azArg[3] = "1";
|
|
+ azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
|
|
"rootpage int,sql text)";
|
|
- azArg[3] = 0;
|
|
+ azArg[5] = 0;
|
|
initData.db = db;
|
|
initData.iDb = iDb;
|
|
initData.rc = SQLITE_OK;
|
|
initData.pzErrMsg = pzErrMsg;
|
|
initData.mInitFlags = mFlags;
|
|
initData.nInitRow = 0;
|
|
- sqlite3InitCallback(&initData, 3, (char **)azArg, 0);
|
|
+ sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
|
|
+ db->mDbFlags &= mask;
|
|
if( initData.rc ){
|
|
rc = initData.rc;
|
|
goto error_out;
|
|
@@ -124458,27 +128173,25 @@
|
|
** as sqlite3.enc.
|
|
*/
|
|
if( meta[BTREE_TEXT_ENCODING-1] ){ /* text encoding */
|
|
- if( iDb==0 ){
|
|
-#ifndef SQLITE_OMIT_UTF16
|
|
+ if( iDb==0 && (db->mDbFlags & DBFLAG_EncodingFixed)==0 ){
|
|
u8 encoding;
|
|
+#ifndef SQLITE_OMIT_UTF16
|
|
/* If opening the main database, set ENC(db). */
|
|
encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3;
|
|
if( encoding==0 ) encoding = SQLITE_UTF8;
|
|
- ENC(db) = encoding;
|
|
#else
|
|
- ENC(db) = SQLITE_UTF8;
|
|
+ encoding = SQLITE_UTF8;
|
|
#endif
|
|
+ sqlite3SetTextEncoding(db, encoding);
|
|
}else{
|
|
/* If opening an attached database, the encoding much match ENC(db) */
|
|
- if( meta[BTREE_TEXT_ENCODING-1]!=ENC(db) ){
|
|
+ if( (meta[BTREE_TEXT_ENCODING-1] & 3)!=ENC(db) ){
|
|
sqlite3SetString(pzErrMsg, db, "attached databases must use the same"
|
|
" text encoding as main database");
|
|
rc = SQLITE_ERROR;
|
|
goto initone_error_out;
|
|
}
|
|
}
|
|
- }else{
|
|
- DbSetProperty(db, iDb, DB_Empty);
|
|
}
|
|
pDb->pSchema->enc = ENC(db);
|
|
|
|
@@ -124524,7 +128237,7 @@
|
|
{
|
|
char *zSql;
|
|
zSql = sqlite3MPrintf(db,
|
|
- "SELECT name, rootpage, sql FROM \"%w\".%s ORDER BY rowid",
|
|
+ "SELECT*FROM\"%w\".%s ORDER BY rowid",
|
|
db->aDb[iDb].zDbSName, zMasterName);
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
{
|
|
@@ -124590,8 +128303,7 @@
|
|
** error occurs, write an error message into *pzErrMsg.
|
|
**
|
|
** After a database is initialized, the DB_SchemaLoaded bit is set
|
|
-** bit is set in the flags field of the Db structure. If the database
|
|
-** file was of zero-length, then the DB_Empty flag is also set.
|
|
+** bit is set in the flags field of the Db structure.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
|
int i, rc;
|
|
@@ -124732,6 +128444,7 @@
|
|
if( db ){
|
|
assert( db->lookaside.bDisable >= pParse->disableLookaside );
|
|
db->lookaside.bDisable -= pParse->disableLookaside;
|
|
+ db->lookaside.sz = db->lookaside.bDisable ? 0 : db->lookaside.szTrue;
|
|
}
|
|
pParse->disableLookaside = 0;
|
|
}
|
|
@@ -124765,7 +128478,7 @@
|
|
*/
|
|
if( prepFlags & SQLITE_PREPARE_PERSISTENT ){
|
|
sParse.disableLookaside++;
|
|
- db->lookaside.bDisable++;
|
|
+ DisableLookaside;
|
|
}
|
|
sParse.disableVtab = (prepFlags & SQLITE_PREPARE_NO_VTAB)!=0;
|
|
|
|
@@ -124792,16 +128505,18 @@
|
|
** but it does *not* override schema lock detection, so this all still
|
|
** works even if READ_UNCOMMITTED is set.
|
|
*/
|
|
- for(i=0; i<db->nDb; i++) {
|
|
- Btree *pBt = db->aDb[i].pBt;
|
|
- if( pBt ){
|
|
- assert( sqlite3BtreeHoldsMutex(pBt) );
|
|
- rc = sqlite3BtreeSchemaLocked(pBt);
|
|
- if( rc ){
|
|
- const char *zDb = db->aDb[i].zDbSName;
|
|
- sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
|
|
- testcase( db->flags & SQLITE_ReadUncommit );
|
|
- goto end_prepare;
|
|
+ if( !db->noSharedCache ){
|
|
+ for(i=0; i<db->nDb; i++) {
|
|
+ Btree *pBt = db->aDb[i].pBt;
|
|
+ if( pBt ){
|
|
+ assert( sqlite3BtreeHoldsMutex(pBt) );
|
|
+ rc = sqlite3BtreeSchemaLocked(pBt);
|
|
+ if( rc ){
|
|
+ const char *zDb = db->aDb[i].zDbSName;
|
|
+ sqlite3ErrorWithMsg(db, rc, "database schema is locked: %s", zDb);
|
|
+ testcase( db->flags & SQLITE_ReadUncommit );
|
|
+ goto end_prepare;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -124832,46 +128547,25 @@
|
|
}
|
|
assert( 0==sParse.nQueryLoop );
|
|
|
|
- if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
|
|
+ if( sParse.rc==SQLITE_DONE ){
|
|
+ sParse.rc = SQLITE_OK;
|
|
+ }
|
|
if( sParse.checkSchema ){
|
|
schemaIsValid(&sParse);
|
|
}
|
|
- if( db->mallocFailed ){
|
|
- sParse.rc = SQLITE_NOMEM_BKPT;
|
|
- }
|
|
if( pzTail ){
|
|
*pzTail = sParse.zTail;
|
|
}
|
|
- rc = sParse.rc;
|
|
-
|
|
-#ifndef SQLITE_OMIT_EXPLAIN
|
|
- if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
|
|
- static const char * const azColName[] = {
|
|
- "addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
|
|
- "id", "parent", "notused", "detail"
|
|
- };
|
|
- int iFirst, mx;
|
|
- if( sParse.explain==2 ){
|
|
- sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
|
|
- iFirst = 8;
|
|
- mx = 12;
|
|
- }else{
|
|
- sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
|
|
- iFirst = 0;
|
|
- mx = 8;
|
|
- }
|
|
- for(i=iFirst; i<mx; i++){
|
|
- sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
|
|
- azColName[i], SQLITE_STATIC);
|
|
- }
|
|
- }
|
|
-#endif
|
|
|
|
if( db->init.busy==0 ){
|
|
sqlite3VdbeSetSql(sParse.pVdbe, zSql, (int)(sParse.zTail-zSql), prepFlags);
|
|
}
|
|
- if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
|
|
- sqlite3VdbeFinalize(sParse.pVdbe);
|
|
+ if( db->mallocFailed ){
|
|
+ sParse.rc = SQLITE_NOMEM_BKPT;
|
|
+ }
|
|
+ rc = sParse.rc;
|
|
+ if( rc!=SQLITE_OK ){
|
|
+ if( sParse.pVdbe ) sqlite3VdbeFinalize(sParse.pVdbe);
|
|
assert(!(*ppStmt));
|
|
}else{
|
|
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
|
|
@@ -125226,7 +128920,10 @@
|
|
|
|
/*
|
|
** Delete all the content of a Select structure. Deallocate the structure
|
|
-** itself only if bFree is true.
|
|
+** itself depending on the value of bFree
|
|
+**
|
|
+** If bFree==1, call sqlite3DbFree() on the p object.
|
|
+** If bFree==0, Leave the first Select object unfreed
|
|
*/
|
|
static void clearSelect(sqlite3 *db, Select *p, int bFree){
|
|
while( p ){
|
|
@@ -125329,6 +129026,21 @@
|
|
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
|
|
}
|
|
|
|
+/*
|
|
+** Delete all the substructure for p, but keep p allocated. Redefine
|
|
+** p to be a single SELECT where every column of the result set has a
|
|
+** value of NULL.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3SelectReset(Parse *pParse, Select *p){
|
|
+ if( ALWAYS(p) ){
|
|
+ clearSelect(pParse->db, p, 0);
|
|
+ memset(&p->iLimit, 0, sizeof(Select) - offsetof(Select,iLimit));
|
|
+ p->pEList = sqlite3ExprListAppend(pParse, 0,
|
|
+ sqlite3ExprAlloc(pParse->db,TK_NULL,0,0));
|
|
+ p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(SrcList));
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Return a pointer to the right-most SELECT statement in a compound.
|
|
*/
|
|
@@ -125437,7 +129149,8 @@
|
|
int N, /* Number of tables in pSrc->a[] to search */
|
|
const char *zCol, /* Name of the column we are looking for */
|
|
int *piTab, /* Write index of pSrc->a[] here */
|
|
- int *piCol /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
|
|
+ int *piCol, /* Write index of pSrc->a[*piTab].pTab->aCol[] here */
|
|
+ int bIgnoreHidden /* True to ignore hidden columns */
|
|
){
|
|
int i; /* For looping over tables in pSrc */
|
|
int iCol; /* Index of column matching zCol */
|
|
@@ -125445,7 +129158,9 @@
|
|
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
|
|
for(i=0; i<N; i++){
|
|
iCol = columnIndex(pSrc->a[i].pTab, zCol);
|
|
- if( iCol>=0 ){
|
|
+ if( iCol>=0
|
|
+ && (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
|
|
+ ){
|
|
if( piTab ){
|
|
*piTab = i;
|
|
*piCol = iCol;
|
|
@@ -125526,7 +129241,7 @@
|
|
** after the t1 loop and rows with t1.x!=5 will never appear in
|
|
** the output, which is incorrect.
|
|
*/
|
|
-static void setJoinExpr(Expr *p, int iTable){
|
|
+SQLITE_PRIVATE void sqlite3SetJoinExpr(Expr *p, int iTable){
|
|
while( p ){
|
|
ExprSetProperty(p, EP_FromJoin);
|
|
assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) );
|
|
@@ -125535,15 +129250,15 @@
|
|
if( p->op==TK_FUNCTION && p->x.pList ){
|
|
int i;
|
|
for(i=0; i<p->x.pList->nExpr; i++){
|
|
- setJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
|
+ sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable);
|
|
}
|
|
}
|
|
- setJoinExpr(p->pLeft, iTable);
|
|
+ sqlite3SetJoinExpr(p->pLeft, iTable);
|
|
p = p->pRight;
|
|
}
|
|
}
|
|
|
|
-/* Undo the work of setJoinExpr(). In the expression tree p, convert every
|
|
+/* Undo the work of sqlite3SetJoinExpr(). In the expression p, convert every
|
|
** term that is marked with EP_FromJoin and iRightJoinTable==iTable into
|
|
** an ordinary term that omits the EP_FromJoin mark.
|
|
**
|
|
@@ -125610,10 +129325,11 @@
|
|
int iLeft; /* Matching left table */
|
|
int iLeftCol; /* Matching column in the left table */
|
|
|
|
+ if( IsHiddenColumn(&pRightTab->aCol[j]) ) continue;
|
|
zName = pRightTab->aCol[j].zName;
|
|
- if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol) ){
|
|
+ if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){
|
|
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j,
|
|
- isOuter, &p->pWhere);
|
|
+ isOuter, &p->pWhere);
|
|
}
|
|
}
|
|
}
|
|
@@ -125630,7 +129346,7 @@
|
|
** an AND operator.
|
|
*/
|
|
if( pRight->pOn ){
|
|
- if( isOuter ) setJoinExpr(pRight->pOn, pRight->iCursor);
|
|
+ if( isOuter ) sqlite3SetJoinExpr(pRight->pOn, pRight->iCursor);
|
|
p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->pOn);
|
|
pRight->pOn = 0;
|
|
}
|
|
@@ -125653,7 +129369,7 @@
|
|
zName = pList->a[j].zName;
|
|
iRightCol = columnIndex(pRightTab, zName);
|
|
if( iRightCol<0
|
|
- || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol)
|
|
+ || !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
|
|
){
|
|
sqlite3ErrorMsg(pParse, "cannot join using column %s - column "
|
|
"not present in both tables", zName);
|
|
@@ -125805,11 +129521,12 @@
|
|
if( pParse->db->mallocFailed ) return;
|
|
pOp->p2 = nKey + nData;
|
|
pKI = pOp->p4.pKeyInfo;
|
|
- memset(pKI->aSortOrder, 0, pKI->nKeyField); /* Makes OP_Jump testable */
|
|
+ memset(pKI->aSortFlags, 0, pKI->nKeyField); /* Makes OP_Jump testable */
|
|
sqlite3VdbeChangeP4(v, -1, (char*)pKI, P4_KEYINFO);
|
|
testcase( pKI->nAllField > pKI->nKeyField+2 );
|
|
pOp->p4.pKeyInfo = sqlite3KeyInfoFromExprList(pParse,pSort->pOrderBy,nOBSat,
|
|
pKI->nAllField-pKI->nKeyField-1);
|
|
+ pOp = 0; /* Ensure pOp not used after sqltie3VdbeAddOp3() */
|
|
addrJmp = sqlite3VdbeCurrentAddr(v);
|
|
sqlite3VdbeAddOp3(v, OP_Jump, addrJmp+1, 0, addrJmp+1); VdbeCoverage(v);
|
|
pSort->labelBkOut = sqlite3VdbeMakeLabel(pParse);
|
|
@@ -126058,7 +129775,7 @@
|
|
if( srcTab>=0 ){
|
|
for(i=0; i<nResultCol; i++){
|
|
sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);
|
|
- VdbeComment((v, "%s", p->pEList->a[i].zName));
|
|
+ VdbeComment((v, "%s", p->pEList->a[i].zEName));
|
|
}
|
|
}else if( eDest!=SRT_Exists ){
|
|
#ifdef SQLITE_ENABLE_SORTER_REFERENCES
|
|
@@ -126172,6 +129889,7 @@
|
|
pOp->opcode = OP_Null;
|
|
pOp->p1 = 1;
|
|
pOp->p2 = regPrev;
|
|
+ pOp = 0; /* Ensure pOp is not used after sqlite3VdbeAddOp() */
|
|
|
|
iJump = sqlite3VdbeCurrentAddr(v) + nResultCol;
|
|
for(i=0; i<nResultCol; i++){
|
|
@@ -126416,7 +130134,7 @@
|
|
int nExtra = (N+X)*(sizeof(CollSeq*)+1) - sizeof(CollSeq*);
|
|
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
|
|
if( p ){
|
|
- p->aSortOrder = (u8*)&p->aColl[N+X];
|
|
+ p->aSortFlags = (u8*)&p->aColl[N+X];
|
|
p->nKeyField = (u16)N;
|
|
p->nAllField = (u16)(N+X);
|
|
p->enc = ENC(db);
|
|
@@ -126493,7 +130211,7 @@
|
|
assert( sqlite3KeyInfoIsWriteable(pInfo) );
|
|
for(i=iStart, pItem=pList->a+iStart; i<nExpr; i++, pItem++){
|
|
pInfo->aColl[i-iStart] = sqlite3ExprNNCollSeq(pParse, pItem->pExpr);
|
|
- pInfo->aSortOrder[i-iStart] = pItem->sortOrder;
|
|
+ pInfo->aSortFlags[i-iStart] = pItem->sortFlags;
|
|
}
|
|
}
|
|
return pInfo;
|
|
@@ -126678,7 +130396,7 @@
|
|
iRead = iCol--;
|
|
}
|
|
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, iRead, regRow+i);
|
|
- VdbeComment((v, "%s", aOutEx[i].zName?aOutEx[i].zName : aOutEx[i].zSpan));
|
|
+ VdbeComment((v, "%s", aOutEx[i].zEName));
|
|
}
|
|
}
|
|
switch( eDest ){
|
|
@@ -126785,8 +130503,6 @@
|
|
|
|
assert( pExpr!=0 );
|
|
assert( pNC->pSrcList!=0 );
|
|
- assert( pExpr->op!=TK_AGG_COLUMN ); /* This routine runes before aggregates
|
|
- ** are processed */
|
|
switch( pExpr->op ){
|
|
case TK_COLUMN: {
|
|
/* The expression is a column. Locate the table the column is being
|
|
@@ -127014,9 +130730,9 @@
|
|
assert( p!=0 );
|
|
assert( p->op!=TK_AGG_COLUMN ); /* Agg processing has not run yet */
|
|
assert( p->op!=TK_COLUMN || p->y.pTab!=0 ); /* Covering idx not yet coded */
|
|
- if( pEList->a[i].zName ){
|
|
+ if( pEList->a[i].zEName && pEList->a[i].eEName==ENAME_NAME ){
|
|
/* An AS clause always takes first priority */
|
|
- char *zName = pEList->a[i].zName;
|
|
+ char *zName = pEList->a[i].zEName;
|
|
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
|
|
}else if( srcName && p->op==TK_COLUMN ){
|
|
char *zCol;
|
|
@@ -127038,7 +130754,7 @@
|
|
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, SQLITE_TRANSIENT);
|
|
}
|
|
}else{
|
|
- const char *z = pEList->a[i].zSpan;
|
|
+ const char *z = pEList->a[i].zEName;
|
|
z = z==0 ? sqlite3MPrintf(db, "column%d", i+1) : sqlite3DbStrDup(db, z);
|
|
sqlite3VdbeSetColName(v, i, COLNAME_NAME, z, SQLITE_DYNAMIC);
|
|
}
|
|
@@ -127100,15 +130816,14 @@
|
|
for(i=0, pCol=aCol; i<nCol && !db->mallocFailed; i++, pCol++){
|
|
/* Get an appropriate name for the column
|
|
*/
|
|
- if( (zName = pEList->a[i].zName)!=0 ){
|
|
+ if( (zName = pEList->a[i].zEName)!=0 && pEList->a[i].eEName==ENAME_NAME ){
|
|
/* If the column contains an "AS <name>" phrase, use <name> as the name */
|
|
}else{
|
|
- Expr *pColExpr = sqlite3ExprSkipCollate(pEList->a[i].pExpr);
|
|
+ Expr *pColExpr = sqlite3ExprSkipCollateAndLikely(pEList->a[i].pExpr);
|
|
while( pColExpr->op==TK_DOT ){
|
|
pColExpr = pColExpr->pRight;
|
|
assert( pColExpr!=0 );
|
|
}
|
|
- assert( pColExpr->op!=TK_AGG_COLUMN );
|
|
if( pColExpr->op==TK_COLUMN ){
|
|
/* For columns use the column name name */
|
|
int iCol = pColExpr->iColumn;
|
|
@@ -127121,10 +130836,10 @@
|
|
zName = pColExpr->u.zToken;
|
|
}else{
|
|
/* Use the original text of the column expression as its name */
|
|
- zName = pEList->a[i].zSpan;
|
|
+ zName = pEList->a[i].zEName;
|
|
}
|
|
}
|
|
- if( zName ){
|
|
+ if( zName && !sqlite3IsTrueOrFalse(zName) ){
|
|
zName = sqlite3DbStrDup(db, zName);
|
|
}else{
|
|
zName = sqlite3MPrintf(db,"column%d",i+1);
|
|
@@ -127144,6 +130859,7 @@
|
|
if( cnt>3 ) sqlite3_randomness(sizeof(cnt), &cnt);
|
|
}
|
|
pCol->zName = zName;
|
|
+ pCol->hName = sqlite3StrIHash(zName);
|
|
sqlite3ColumnPropertiesFromName(0, pCol);
|
|
if( zName && sqlite3HashInsert(&ht, zName, pCol)==pCol ){
|
|
sqlite3OomFault(db);
|
|
@@ -127176,7 +130892,8 @@
|
|
SQLITE_PRIVATE void sqlite3SelectAddColumnTypeAndCollation(
|
|
Parse *pParse, /* Parsing contexts */
|
|
Table *pTab, /* Add column type information to this table */
|
|
- Select *pSelect /* SELECT used to determine types and collations */
|
|
+ Select *pSelect, /* SELECT used to determine types and collations */
|
|
+ char aff /* Default affinity for columns */
|
|
){
|
|
sqlite3 *db = pParse->db;
|
|
NameContext sNC;
|
|
@@ -127209,7 +130926,7 @@
|
|
pCol->colFlags |= COLFLAG_HASTYPE;
|
|
}
|
|
}
|
|
- if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_BLOB;
|
|
+ if( pCol->affinity<=SQLITE_AFF_NONE ) pCol->affinity = aff;
|
|
pColl = sqlite3ExprCollSeq(pParse, p);
|
|
if( pColl && pCol->zColl==0 ){
|
|
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
|
|
@@ -127222,7 +130939,7 @@
|
|
** Given a SELECT statement, generate a Table structure that describes
|
|
** the result set of that SELECT.
|
|
*/
|
|
-SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
|
|
+SQLITE_PRIVATE Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){
|
|
Table *pTab;
|
|
sqlite3 *db = pParse->db;
|
|
u64 savedFlags;
|
|
@@ -127242,7 +130959,7 @@
|
|
pTab->zName = 0;
|
|
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
|
|
sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
|
|
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect);
|
|
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff);
|
|
pTab->iPKey = -1;
|
|
if( db->mallocFailed ){
|
|
sqlite3DeleteTable(db, pTab);
|
|
@@ -127396,7 +131113,7 @@
|
|
}
|
|
assert( sqlite3KeyInfoIsWriteable(pRet) );
|
|
pRet->aColl[i] = pColl;
|
|
- pRet->aSortOrder[i] = pOrderBy->a[i].sortOrder;
|
|
+ pRet->aSortFlags[i] = pOrderBy->a[i].sortFlags;
|
|
}
|
|
}
|
|
|
|
@@ -127615,6 +131332,9 @@
|
|
assert( p->selFlags & SF_Values );
|
|
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
|
|
assert( p->pNext==0 || p->pEList->nExpr==p->pNext->pEList->nExpr );
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ if( p->pWin ) return -1;
|
|
+#endif
|
|
if( p->pPrior==0 ) break;
|
|
assert( p->pPrior->pNext==p );
|
|
p = p->pPrior;
|
|
@@ -127705,7 +131425,8 @@
|
|
*/
|
|
if( p->selFlags & SF_MultiValue ){
|
|
rc = multiSelectValues(pParse, p, &dest);
|
|
- goto multi_select_end;
|
|
+ if( rc>=0 ) goto multi_select_end;
|
|
+ rc = SQLITE_OK;
|
|
}
|
|
|
|
/* Make sure all SELECTs in the statement have the same number of elements
|
|
@@ -127850,9 +131571,9 @@
|
|
** it is that we currently need.
|
|
*/
|
|
assert( unionTab==dest.iSDParm || dest.eDest!=priorOp );
|
|
- if( dest.eDest!=priorOp ){
|
|
+ assert( p->pEList || db->mallocFailed );
|
|
+ if( dest.eDest!=priorOp && db->mallocFailed==0 ){
|
|
int iCont, iBreak, iStart;
|
|
- assert( p->pEList );
|
|
iBreak = sqlite3VdbeMakeLabel(pParse);
|
|
iCont = sqlite3VdbeMakeLabel(pParse);
|
|
computeLimitRegisters(pParse, p, iBreak);
|
|
@@ -127921,6 +131642,7 @@
|
|
/* Generate code to take the intersection of the two temporary
|
|
** tables.
|
|
*/
|
|
+ if( rc ) break;
|
|
assert( p->pEList );
|
|
iBreak = sqlite3VdbeMakeLabel(pParse);
|
|
iCont = sqlite3VdbeMakeLabel(pParse);
|
|
@@ -127948,6 +131670,7 @@
|
|
}
|
|
#endif
|
|
}
|
|
+ if( pParse->nErr ) goto multi_select_end;
|
|
|
|
/* Compute collating sequences used by
|
|
** temporary tables needed to implement the compound select.
|
|
@@ -128107,11 +131830,14 @@
|
|
|
|
/* If this is a scalar select that is part of an expression, then
|
|
** store the results in the appropriate memory cell and break out
|
|
- ** of the scan loop.
|
|
+ ** of the scan loop. Note that the select might return multiple columns
|
|
+ ** if it is the RHS of a row-value IN operator.
|
|
*/
|
|
case SRT_Mem: {
|
|
- assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
|
|
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
|
|
+ if( pParse->nErr==0 ){
|
|
+ testcase( pIn->nSdst>1 );
|
|
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, pIn->nSdst);
|
|
+ }
|
|
/* The LIMIT clause will jump out of the loop for us */
|
|
break;
|
|
}
|
|
@@ -128368,7 +132094,7 @@
|
|
assert( sqlite3KeyInfoIsWriteable(pKeyDup) );
|
|
for(i=0; i<nExpr; i++){
|
|
pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
|
|
- pKeyDup->aSortOrder[i] = 0;
|
|
+ pKeyDup->aSortFlags[i] = 0;
|
|
}
|
|
}
|
|
}
|
|
@@ -128587,7 +132313,10 @@
|
|
){
|
|
pExpr->iRightJoinTable = pSubst->iNewTable;
|
|
}
|
|
- if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
|
|
+ if( pExpr->op==TK_COLUMN
|
|
+ && pExpr->iTable==pSubst->iTable
|
|
+ && !ExprHasProperty(pExpr, EP_FixedCol)
|
|
+ ){
|
|
if( pExpr->iColumn<0 ){
|
|
pExpr->op = TK_NULL;
|
|
}else{
|
|
@@ -128605,6 +132334,7 @@
|
|
ifNullRow.op = TK_IF_NULL_ROW;
|
|
ifNullRow.pLeft = pCopy;
|
|
ifNullRow.iTable = pSubst->iNewTable;
|
|
+ ifNullRow.flags = EP_Skip;
|
|
pCopy = &ifNullRow;
|
|
}
|
|
testcase( ExprHasProperty(pCopy, EP_Subquery) );
|
|
@@ -128618,6 +132348,18 @@
|
|
}
|
|
sqlite3ExprDelete(db, pExpr);
|
|
pExpr = pNew;
|
|
+
|
|
+ /* Ensure that the expression now has an implicit collation sequence,
|
|
+ ** just as it did when it was a column of a view or sub-query. */
|
|
+ if( pExpr ){
|
|
+ if( pExpr->op!=TK_COLUMN && pExpr->op!=TK_COLLATE ){
|
|
+ CollSeq *pColl = sqlite3ExprCollSeq(pSubst->pParse, pExpr);
|
|
+ pExpr = sqlite3ExprAddCollateString(pSubst->pParse, pExpr,
|
|
+ (pColl ? pColl->zName : "BINARY")
|
|
+ );
|
|
+ }
|
|
+ ExprClearProperty(pExpr, EP_Collate);
|
|
+ }
|
|
}
|
|
}
|
|
}else{
|
|
@@ -128631,6 +132373,14 @@
|
|
}else{
|
|
substExprList(pSubst, pExpr->x.pList);
|
|
}
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ Window *pWin = pExpr->y.pWin;
|
|
+ pWin->pFilter = substExpr(pSubst, pWin->pFilter);
|
|
+ substExprList(pSubst, pWin->pPartition);
|
|
+ substExprList(pSubst, pWin->pOrderBy);
|
|
+ }
|
|
+#endif
|
|
}
|
|
return pExpr;
|
|
}
|
|
@@ -128671,6 +132421,38 @@
|
|
}
|
|
#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
|
|
|
+#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
|
+/*
|
|
+** pSelect is a SELECT statement and pSrcItem is one item in the FROM
|
|
+** clause of that SELECT.
|
|
+**
|
|
+** This routine scans the entire SELECT statement and recomputes the
|
|
+** pSrcItem->colUsed mask.
|
|
+*/
|
|
+static int recomputeColumnsUsedExpr(Walker *pWalker, Expr *pExpr){
|
|
+ struct SrcList_item *pItem;
|
|
+ if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
|
|
+ pItem = pWalker->u.pSrcItem;
|
|
+ if( pItem->iCursor!=pExpr->iTable ) return WRC_Continue;
|
|
+ if( pExpr->iColumn<0 ) return WRC_Continue;
|
|
+ pItem->colUsed |= sqlite3ExprColUsed(pExpr);
|
|
+ return WRC_Continue;
|
|
+}
|
|
+static void recomputeColumnsUsed(
|
|
+ Select *pSelect, /* The complete SELECT statement */
|
|
+ struct SrcList_item *pSrcItem /* Which FROM clause item to recompute */
|
|
+){
|
|
+ Walker w;
|
|
+ if( NEVER(pSrcItem->pTab==0) ) return;
|
|
+ memset(&w, 0, sizeof(w));
|
|
+ w.xExprCallback = recomputeColumnsUsedExpr;
|
|
+ w.xSelectCallback = sqlite3SelectWalkNoop;
|
|
+ w.u.pSrcItem = pSrcItem;
|
|
+ pSrcItem->colUsed = 0;
|
|
+ sqlite3WalkSelect(&w, pSelect);
|
|
+}
|
|
+#endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
|
|
+
|
|
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
|
|
/*
|
|
** This routine attempts to flatten subqueries as a performance optimization.
|
|
@@ -128716,6 +132498,7 @@
|
|
** (3b) the FROM clause of the subquery may not contain a virtual
|
|
** table and
|
|
** (3c) the outer query may not be an aggregate.
|
|
+** (3d) the outer query may not be DISTINCT.
|
|
**
|
|
** (4) The subquery can not be DISTINCT.
|
|
**
|
|
@@ -128766,6 +132549,7 @@
|
|
** (17d1) aggregate, or
|
|
** (17d2) DISTINCT, or
|
|
** (17d3) a join.
|
|
+** (17e) the subquery may not contain window functions
|
|
**
|
|
** The parent and sub-query may contain WHERE clauses. Subject to
|
|
** rules (11), (13) and (14), they may also contain ORDER BY,
|
|
@@ -128912,8 +132696,11 @@
|
|
*/
|
|
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
|
|
isLeftJoin = 1;
|
|
- if( pSubSrc->nSrc>1 || isAgg || IsVirtual(pSubSrc->a[0].pTab) ){
|
|
- /* (3a) (3c) (3b) */
|
|
+ if( pSubSrc->nSrc>1 /* (3a) */
|
|
+ || isAgg /* (3b) */
|
|
+ || IsVirtual(pSubSrc->a[0].pTab) /* (3c) */
|
|
+ || (p->selFlags & SF_Distinct)!=0 /* (3d) */
|
|
+ ){
|
|
return 0;
|
|
}
|
|
}
|
|
@@ -128947,6 +132734,9 @@
|
|
if( (pSub1->selFlags & (SF_Distinct|SF_Aggregate))!=0 /* (17b) */
|
|
|| (pSub1->pPrior && pSub1->op!=TK_ALL) /* (17a) */
|
|
|| pSub1->pSrc->nSrc<1 /* (17c) */
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ || pSub1->pWin /* (17e) */
|
|
+#endif
|
|
){
|
|
return 0;
|
|
}
|
|
@@ -129091,6 +132881,7 @@
|
|
for(pParent=p; pParent; pParent=pParent->pPrior, pSub=pSub->pPrior){
|
|
int nSubSrc;
|
|
u8 jointype = 0;
|
|
+ assert( pSub!=0 );
|
|
pSubSrc = pSub->pSrc; /* FROM clause of subquery */
|
|
nSubSrc = pSubSrc->nSrc; /* Number of terms in subquery FROM clause */
|
|
pSrc = pParent->pSrc; /* FROM clause of the outer query */
|
|
@@ -129172,7 +132963,7 @@
|
|
pWhere = pSub->pWhere;
|
|
pSub->pWhere = 0;
|
|
if( isLeftJoin>0 ){
|
|
- setJoinExpr(pWhere, iNewParent);
|
|
+ sqlite3SetJoinExpr(pWhere, iNewParent);
|
|
}
|
|
pParent->pWhere = sqlite3ExprAnd(pParse, pWhere, pParent->pWhere);
|
|
if( db->mallocFailed==0 ){
|
|
@@ -129200,6 +132991,12 @@
|
|
pParent->pLimit = pSub->pLimit;
|
|
pSub->pLimit = 0;
|
|
}
|
|
+
|
|
+ /* Recompute the SrcList_item.colUsed masks for the flattened
|
|
+ ** tables. */
|
|
+ for(i=0; i<nSubSrc; i++){
|
|
+ recomputeColumnsUsed(pParent, &pSrc->a[i+iFrom]);
|
|
+ }
|
|
}
|
|
|
|
/* Finially, delete what is left of the subquery and return
|
|
@@ -129232,23 +133029,35 @@
|
|
|
|
/*
|
|
** Add a new entry to the pConst object. Except, do not add duplicate
|
|
-** pColumn entires.
|
|
+** pColumn entires. Also, do not add if doing so would not be appropriate.
|
|
+**
|
|
+** The caller guarantees the pColumn is a column and pValue is a constant.
|
|
+** This routine has to do some additional checks before completing the
|
|
+** insert.
|
|
*/
|
|
static void constInsert(
|
|
- WhereConst *pConst, /* The WhereConst into which we are inserting */
|
|
- Expr *pColumn, /* The COLUMN part of the constraint */
|
|
- Expr *pValue /* The VALUE part of the constraint */
|
|
+ WhereConst *pConst, /* The WhereConst into which we are inserting */
|
|
+ Expr *pColumn, /* The COLUMN part of the constraint */
|
|
+ Expr *pValue, /* The VALUE part of the constraint */
|
|
+ Expr *pExpr /* Overall expression: COLUMN=VALUE or VALUE=COLUMN */
|
|
){
|
|
int i;
|
|
assert( pColumn->op==TK_COLUMN );
|
|
+ assert( sqlite3ExprIsConstant(pValue) );
|
|
+
|
|
+ if( ExprHasProperty(pColumn, EP_FixedCol) ) return;
|
|
+ if( sqlite3ExprAffinity(pValue)!=0 ) return;
|
|
+ if( !sqlite3IsBinary(sqlite3ExprCompareCollSeq(pConst->pParse,pExpr)) ){
|
|
+ return;
|
|
+ }
|
|
|
|
/* 2018-10-25 ticket [cf5ed20f]
|
|
** Make sure the same pColumn is not inserted more than once */
|
|
for(i=0; i<pConst->nConst; i++){
|
|
- const Expr *pExpr = pConst->apExpr[i*2];
|
|
- assert( pExpr->op==TK_COLUMN );
|
|
- if( pExpr->iTable==pColumn->iTable
|
|
- && pExpr->iColumn==pColumn->iColumn
|
|
+ const Expr *pE2 = pConst->apExpr[i*2];
|
|
+ assert( pE2->op==TK_COLUMN );
|
|
+ if( pE2->iTable==pColumn->iTable
|
|
+ && pE2->iColumn==pColumn->iColumn
|
|
){
|
|
return; /* Already present. Return without doing anything. */
|
|
}
|
|
@@ -129260,7 +133069,6 @@
|
|
if( pConst->apExpr==0 ){
|
|
pConst->nConst = 0;
|
|
}else{
|
|
- if( ExprHasProperty(pValue, EP_FixedCol) ) pValue = pValue->pLeft;
|
|
pConst->apExpr[pConst->nConst*2-2] = pColumn;
|
|
pConst->apExpr[pConst->nConst*2-1] = pValue;
|
|
}
|
|
@@ -129286,19 +133094,11 @@
|
|
pLeft = pExpr->pLeft;
|
|
assert( pRight!=0 );
|
|
assert( pLeft!=0 );
|
|
- if( pRight->op==TK_COLUMN
|
|
- && !ExprHasProperty(pRight, EP_FixedCol)
|
|
- && sqlite3ExprIsConstant(pLeft)
|
|
- && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
|
|
- ){
|
|
- constInsert(pConst, pRight, pLeft);
|
|
- }else
|
|
- if( pLeft->op==TK_COLUMN
|
|
- && !ExprHasProperty(pLeft, EP_FixedCol)
|
|
- && sqlite3ExprIsConstant(pRight)
|
|
- && sqlite3IsBinary(sqlite3BinaryCompareCollSeq(pConst->pParse,pLeft,pRight))
|
|
- ){
|
|
- constInsert(pConst, pLeft, pRight);
|
|
+ if( pRight->op==TK_COLUMN && sqlite3ExprIsConstant(pLeft) ){
|
|
+ constInsert(pConst,pRight,pLeft,pExpr);
|
|
+ }
|
|
+ if( pLeft->op==TK_COLUMN && sqlite3ExprIsConstant(pRight) ){
|
|
+ constInsert(pConst,pLeft,pRight,pExpr);
|
|
}
|
|
}
|
|
|
|
@@ -129312,7 +133112,11 @@
|
|
int i;
|
|
WhereConst *pConst;
|
|
if( pExpr->op!=TK_COLUMN ) return WRC_Continue;
|
|
- if( ExprHasProperty(pExpr, EP_FixedCol) ) return WRC_Continue;
|
|
+ if( ExprHasProperty(pExpr, EP_FixedCol|EP_FromJoin) ){
|
|
+ testcase( ExprHasProperty(pExpr, EP_FixedCol) );
|
|
+ testcase( ExprHasProperty(pExpr, EP_FromJoin) );
|
|
+ return WRC_Continue;
|
|
+ }
|
|
pConst = pWalker->u.pConst;
|
|
for(i=0; i<pConst->nConst; i++){
|
|
Expr *pColumn = pConst->apExpr[i*2];
|
|
@@ -129334,10 +133138,9 @@
|
|
** The WHERE-clause constant propagation optimization.
|
|
**
|
|
** If the WHERE clause contains terms of the form COLUMN=CONSTANT or
|
|
-** CONSTANT=COLUMN that must be tree (in other words, if the terms top-level
|
|
-** AND-connected terms that are not part of a ON clause from a LEFT JOIN)
|
|
-** then throughout the query replace all other occurrences of COLUMN
|
|
-** with CONSTANT within the WHERE clause.
|
|
+** CONSTANT=COLUMN that are top-level AND-connected terms that are not
|
|
+** part of a ON clause from a LEFT JOIN, then throughout the query
|
|
+** replace all other occurrences of COLUMN with CONSTANT.
|
|
**
|
|
** For example, the query:
|
|
**
|
|
@@ -129541,24 +133344,29 @@
|
|
ExprList *pEList = pFunc->x.pList; /* Arguments to agg function */
|
|
const char *zFunc; /* Name of aggregate function pFunc */
|
|
ExprList *pOrderBy;
|
|
- u8 sortOrder;
|
|
+ u8 sortFlags = 0;
|
|
|
|
assert( *ppMinMax==0 );
|
|
assert( pFunc->op==TK_AGG_FUNCTION );
|
|
- if( pEList==0 || pEList->nExpr!=1 ) return eRet;
|
|
+ assert( !IsWindowFunc(pFunc) );
|
|
+ if( pEList==0 || pEList->nExpr!=1 || ExprHasProperty(pFunc, EP_WinFunc) ){
|
|
+ return eRet;
|
|
+ }
|
|
zFunc = pFunc->u.zToken;
|
|
if( sqlite3StrICmp(zFunc, "min")==0 ){
|
|
eRet = WHERE_ORDERBY_MIN;
|
|
- sortOrder = SQLITE_SO_ASC;
|
|
+ if( sqlite3ExprCanBeNull(pEList->a[0].pExpr) ){
|
|
+ sortFlags = KEYINFO_ORDER_BIGNULL;
|
|
+ }
|
|
}else if( sqlite3StrICmp(zFunc, "max")==0 ){
|
|
eRet = WHERE_ORDERBY_MAX;
|
|
- sortOrder = SQLITE_SO_DESC;
|
|
+ sortFlags = KEYINFO_ORDER_DESC;
|
|
}else{
|
|
return eRet;
|
|
}
|
|
*ppMinMax = pOrderBy = sqlite3ExprListDup(db, pEList, 0);
|
|
assert( pOrderBy!=0 || db->mallocFailed );
|
|
- if( pOrderBy ) pOrderBy->a[0].sortOrder = sortOrder;
|
|
+ if( pOrderBy ) pOrderBy->a[0].sortFlags = sortFlags;
|
|
return eRet;
|
|
}
|
|
|
|
@@ -129592,7 +133400,7 @@
|
|
if( pExpr->op!=TK_AGG_FUNCTION ) return 0;
|
|
if( NEVER(pAggInfo->nFunc==0) ) return 0;
|
|
if( (pAggInfo->aFunc[0].pFunc->funcFlags&SQLITE_FUNC_COUNT)==0 ) return 0;
|
|
- if( pExpr->flags&EP_Distinct ) return 0;
|
|
+ if( ExprHasProperty(pExpr, EP_Distinct|EP_WinFunc) ) return 0;
|
|
|
|
return pTab;
|
|
}
|
|
@@ -129683,6 +133491,9 @@
|
|
p->pPrior = 0;
|
|
p->pNext = 0;
|
|
p->pWith = 0;
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ p->pWinDefn = 0;
|
|
+#endif
|
|
p->selFlags &= ~SF_Compound;
|
|
assert( (p->selFlags & SF_Converted)==0 );
|
|
p->selFlags |= SF_Converted;
|
|
@@ -129782,6 +133593,9 @@
|
|
With *pWith; /* WITH clause that pCte belongs to */
|
|
|
|
assert( pFrom->pTab==0 );
|
|
+ if( pParse->nErr ){
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
|
|
pCte = searchWith(pParse->pWith, pFrom, &pWith);
|
|
if( pCte ){
|
|
@@ -129902,7 +133716,7 @@
|
|
if( OK_IF_ALWAYS_TRUE(pParse->pWith) && p->pPrior==0 ){
|
|
With *pWith = findRightmost(p)->pWith;
|
|
if( pWith!=0 ){
|
|
- assert( pParse->pWith==pWith );
|
|
+ assert( pParse->pWith==pWith || pParse->nErr );
|
|
pParse->pWith = pWith->pOuter;
|
|
}
|
|
}
|
|
@@ -130033,12 +133847,26 @@
|
|
if( !IsVirtual(pTab) && cannotBeFunction(pParse, pFrom) ){
|
|
return WRC_Abort;
|
|
}
|
|
-#if !defined(SQLITE_OMIT_VIEW) || !defined (SQLITE_OMIT_VIRTUALTABLE)
|
|
+#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
|
|
if( IsVirtual(pTab) || pTab->pSelect ){
|
|
i16 nCol;
|
|
u8 eCodeOrig = pWalker->eCode;
|
|
if( sqlite3ViewGetColumnNames(pParse, pTab) ) return WRC_Abort;
|
|
assert( pFrom->pSelect==0 );
|
|
+ if( pTab->pSelect && (db->flags & SQLITE_EnableView)==0 ){
|
|
+ sqlite3ErrorMsg(pParse, "access to view \"%s\" prohibited",
|
|
+ pTab->zName);
|
|
+ }
|
|
+#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
+ if( IsVirtual(pTab)
|
|
+ && pFrom->fg.fromDDL
|
|
+ && ALWAYS(pTab->pVTable!=0)
|
|
+ && pTab->pVTable->eVtabRisk > ((db->flags & SQLITE_TrustedSchema)!=0)
|
|
+ ){
|
|
+ sqlite3ErrorMsg(pParse, "unsafe use of virtual table \"%s\"",
|
|
+ pTab->zName);
|
|
+ }
|
|
+#endif
|
|
pFrom->pSelect = sqlite3SelectDup(db, pTab->pSelect, 0);
|
|
nCol = pTab->nCol;
|
|
pTab->nCol = -1;
|
|
@@ -130058,7 +133886,7 @@
|
|
|
|
/* Process NATURAL keywords, and ON and USING clauses of joins.
|
|
*/
|
|
- if( db->mallocFailed || sqliteProcessJoin(pParse, p) ){
|
|
+ if( pParse->nErr || db->mallocFailed || sqliteProcessJoin(pParse, p) ){
|
|
return WRC_Abort;
|
|
}
|
|
|
|
@@ -130105,10 +133933,9 @@
|
|
*/
|
|
pNew = sqlite3ExprListAppend(pParse, pNew, a[k].pExpr);
|
|
if( pNew ){
|
|
- pNew->a[pNew->nExpr-1].zName = a[k].zName;
|
|
- pNew->a[pNew->nExpr-1].zSpan = a[k].zSpan;
|
|
- a[k].zName = 0;
|
|
- a[k].zSpan = 0;
|
|
+ pNew->a[pNew->nExpr-1].zEName = a[k].zEName;
|
|
+ pNew->a[pNew->nExpr-1].eEName = a[k].eEName;
|
|
+ a[k].zEName = 0;
|
|
}
|
|
a[k].pExpr = 0;
|
|
}else{
|
|
@@ -130147,7 +133974,7 @@
|
|
|
|
assert( zName );
|
|
if( zTName && pSub
|
|
- && sqlite3MatchSpanName(pSub->pEList->a[j].zSpan, 0, zTName, 0)==0
|
|
+ && sqlite3MatchEName(&pSub->pEList->a[j], 0, zTName, 0)==0
|
|
){
|
|
continue;
|
|
}
|
|
@@ -130165,7 +133992,7 @@
|
|
|
|
if( i>0 && zTName==0 ){
|
|
if( (pFrom->fg.jointype & JT_NATURAL)!=0
|
|
- && tableAndColumnIndex(pTabList, i, zName, 0, 0)
|
|
+ && tableAndColumnIndex(pTabList, i, zName, 0, 0, 1)
|
|
){
|
|
/* In a NATURAL join, omit the join columns from the
|
|
** table to the right of the join */
|
|
@@ -130198,17 +134025,18 @@
|
|
pNew = sqlite3ExprListAppend(pParse, pNew, pExpr);
|
|
sqlite3TokenInit(&sColname, zColname);
|
|
sqlite3ExprListSetName(pParse, pNew, &sColname, 0);
|
|
- if( pNew && (p->selFlags & SF_NestedFrom)!=0 ){
|
|
+ if( pNew && (p->selFlags & SF_NestedFrom)!=0 && !IN_RENAME_OBJECT ){
|
|
struct ExprList_item *pX = &pNew->a[pNew->nExpr-1];
|
|
+ sqlite3DbFree(db, pX->zEName);
|
|
if( pSub ){
|
|
- pX->zSpan = sqlite3DbStrDup(db, pSub->pEList->a[j].zSpan);
|
|
- testcase( pX->zSpan==0 );
|
|
+ pX->zEName = sqlite3DbStrDup(db, pSub->pEList->a[j].zEName);
|
|
+ testcase( pX->zEName==0 );
|
|
}else{
|
|
- pX->zSpan = sqlite3MPrintf(db, "%s.%s.%s",
|
|
+ pX->zEName = sqlite3MPrintf(db, "%s.%s.%s",
|
|
zSchemaName, zTabName, zColname);
|
|
- testcase( pX->zSpan==0 );
|
|
+ testcase( pX->zEName==0 );
|
|
}
|
|
- pX->bSpanIsTab = 1;
|
|
+ pX->eEName = ENAME_TAB;
|
|
}
|
|
sqlite3DbFree(db, zToFree);
|
|
}
|
|
@@ -130237,29 +134065,6 @@
|
|
return WRC_Continue;
|
|
}
|
|
|
|
-/*
|
|
-** No-op routine for the parse-tree walker.
|
|
-**
|
|
-** When this routine is the Walker.xExprCallback then expression trees
|
|
-** are walked without any actions being taken at each node. Presumably,
|
|
-** when this routine is used for Walker.xExprCallback then
|
|
-** Walker.xSelectCallback is set to do something useful for every
|
|
-** subquery in the parser tree.
|
|
-*/
|
|
-SQLITE_PRIVATE int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
|
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
- return WRC_Continue;
|
|
-}
|
|
-
|
|
-/*
|
|
-** No-op routine for the parse-tree walker for SELECT statements.
|
|
-** subquery in the parser tree.
|
|
-*/
|
|
-SQLITE_PRIVATE int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
|
|
- UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
|
- return WRC_Continue;
|
|
-}
|
|
-
|
|
#if SQLITE_DEBUG
|
|
/*
|
|
** Always assert. This xSelectCallback2 implementation proves that the
|
|
@@ -130332,7 +134137,8 @@
|
|
Select *pSel = pFrom->pSelect;
|
|
if( pSel ){
|
|
while( pSel->pPrior ) pSel = pSel->pPrior;
|
|
- sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel);
|
|
+ sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel,
|
|
+ SQLITE_AFF_NONE);
|
|
}
|
|
}
|
|
}
|
|
@@ -130400,6 +134206,7 @@
|
|
struct AggInfo_func *pFunc;
|
|
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
|
|
if( nReg==0 ) return;
|
|
+ if( pParse->nErr ) return;
|
|
#ifdef SQLITE_DEBUG
|
|
/* Verify that all AggInfo registers are within the range specified by
|
|
** AggInfo.mnReg..AggInfo.mxReg */
|
|
@@ -130472,6 +134279,25 @@
|
|
int regAgg;
|
|
ExprList *pList = pF->pExpr->x.pList;
|
|
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
|
|
+ assert( !IsWindowFunc(pF->pExpr) );
|
|
+ if( ExprHasProperty(pF->pExpr, EP_WinFunc) ){
|
|
+ Expr *pFilter = pF->pExpr->y.pWin->pFilter;
|
|
+ if( pAggInfo->nAccumulator
|
|
+ && (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
|
|
+ ){
|
|
+ if( regHit==0 ) regHit = ++pParse->nMem;
|
|
+ /* If this is the first row of the group (regAcc==0), clear the
|
|
+ ** "magnet" register regHit so that the accumulator registers
|
|
+ ** are populated if the FILTER clause jumps over the the
|
|
+ ** invocation of min() or max() altogether. Or, if this is not
|
|
+ ** the first row (regAcc==1), set the magnet register so that the
|
|
+ ** accumulators are not populated unless the min()/max() is invoked and
|
|
+ ** indicates that they should be. */
|
|
+ sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit);
|
|
+ }
|
|
+ addrNext = sqlite3VdbeMakeLabel(pParse);
|
|
+ sqlite3ExprIfFalse(pParse, pFilter, addrNext, SQLITE_JUMPIFNULL);
|
|
+ }
|
|
if( pList ){
|
|
nArg = pList->nExpr;
|
|
regAgg = sqlite3GetTempRange(pParse, nArg);
|
|
@@ -130481,7 +134307,9 @@
|
|
regAgg = 0;
|
|
}
|
|
if( pF->iDistinct>=0 ){
|
|
- addrNext = sqlite3VdbeMakeLabel(pParse);
|
|
+ if( addrNext==0 ){
|
|
+ addrNext = sqlite3VdbeMakeLabel(pParse);
|
|
+ }
|
|
testcase( nArg==0 ); /* Error condition */
|
|
testcase( nArg>1 ); /* Also an error */
|
|
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
|
|
@@ -130517,9 +134345,10 @@
|
|
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
|
|
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
|
|
}
|
|
+
|
|
pAggInfo->directMode = 0;
|
|
if( addrHitTest ){
|
|
- sqlite3VdbeJumpHere(v, addrHitTest);
|
|
+ sqlite3VdbeJumpHereOrPopInst(v, addrHitTest);
|
|
}
|
|
}
|
|
|
|
@@ -130562,7 +134391,7 @@
|
|
Select *pS = pWalker->u.pSelect;
|
|
if( sqlite3ExprIsConstantOrGroupBy(pWalker->pParse, pExpr, pS->pGroupBy) ){
|
|
sqlite3 *db = pWalker->pParse->db;
|
|
- Expr *pNew = sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[1], 0);
|
|
+ Expr *pNew = sqlite3Expr(db, TK_INTEGER, "1");
|
|
if( pNew ){
|
|
Expr *pWhere = pS->pWhere;
|
|
SWAP(Expr, *pNew, *pExpr);
|
|
@@ -130812,11 +134641,13 @@
|
|
}
|
|
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- if( sqlite3WindowRewrite(pParse, p) ){
|
|
+ rc = sqlite3WindowRewrite(pParse, p);
|
|
+ if( rc ){
|
|
+ assert( db->mallocFailed || pParse->nErr>0 );
|
|
goto select_end;
|
|
}
|
|
#if SELECTTRACE_ENABLED
|
|
- if( sqlite3SelectTrace & 0x108 ){
|
|
+ if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
|
|
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
|
|
sqlite3TreeViewSelect(0, p, 0);
|
|
}
|
|
@@ -130984,7 +134815,7 @@
|
|
** assume the column name is non-NULL and segfault. The use of an empty
|
|
** string for the fake column name seems safer.
|
|
*/
|
|
- if( pItem->colUsed==0 ){
|
|
+ if( pItem->colUsed==0 && pItem->zName!=0 ){
|
|
sqlite3AuthCheck(pParse, SQLITE_READ, pItem->zName, "", pItem->zDatabase);
|
|
}
|
|
|
|
@@ -130998,8 +134829,15 @@
|
|
** technically harmless for it to be generated multiple times. The
|
|
** following assert() will detect if something changes to cause
|
|
** the same subquery to be coded multiple times, as a signal to the
|
|
- ** developers to try to optimize the situation. */
|
|
- assert( pItem->addrFillSub==0 );
|
|
+ ** developers to try to optimize the situation.
|
|
+ **
|
|
+ ** Update 2019-07-24:
|
|
+ ** See ticket https://sqlite.org/src/tktview/c52b09c7f38903b1311cec40.
|
|
+ ** The dbsqlfuzz fuzzer found a case where the same subquery gets
|
|
+ ** coded twice. So this assert() now becomes a testcase(). It should
|
|
+ ** be very rare, though.
|
|
+ */
|
|
+ testcase( pItem->addrFillSub!=0 );
|
|
|
|
/* Increment Parse.nHeight by the height of the largest expression
|
|
** tree referred to by this, the parent select. The child select
|
|
@@ -131073,7 +134911,7 @@
|
|
int retAddr;
|
|
struct SrcList_item *pPrior;
|
|
|
|
- assert( pItem->addrFillSub==0 );
|
|
+ testcase( pItem->addrFillSub==0 ); /* Ticket c52b09c7f38903b1311 */
|
|
pItem->regReturn = ++pParse->nMem;
|
|
topAddr = sqlite3VdbeAddOp2(v, OP_Integer, 0, pItem->regReturn);
|
|
pItem->addrFillSub = topAddr+1;
|
|
@@ -131141,9 +134979,13 @@
|
|
*/
|
|
if( (p->selFlags & (SF_Distinct|SF_Aggregate))==SF_Distinct
|
|
&& sqlite3ExprListCompare(sSort.pOrderBy, pEList, -1)==0
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ && p->pWin==0
|
|
+#endif
|
|
){
|
|
p->selFlags &= ~SF_Distinct;
|
|
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
|
+ p->selFlags |= SF_Aggregate;
|
|
/* Notice that even thought SF_Distinct has been cleared from p->selFlags,
|
|
** the sDistinct.isTnct is still set. Hence, isTnct represents the
|
|
** original setting of the SF_Distinct flag, not the current setting */
|
|
@@ -131218,7 +135060,7 @@
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
Window *pWin = p->pWin; /* Master window object (or NULL) */
|
|
if( pWin ){
|
|
- sqlite3WindowCodeInit(pParse, pWin);
|
|
+ sqlite3WindowCodeInit(pParse, p);
|
|
}
|
|
#endif
|
|
assert( WHERE_USE_LIMIT==SF_FixedLimit );
|
|
@@ -131313,23 +135155,35 @@
|
|
}
|
|
assert( 66==sqlite3LogEst(100) );
|
|
if( p->nSelectRow>66 ) p->nSelectRow = 66;
|
|
+
|
|
+ /* If there is both a GROUP BY and an ORDER BY clause and they are
|
|
+ ** identical, then it may be possible to disable the ORDER BY clause
|
|
+ ** on the grounds that the GROUP BY will cause elements to come out
|
|
+ ** in the correct order. It also may not - the GROUP BY might use a
|
|
+ ** database index that causes rows to be grouped together as required
|
|
+ ** but not actually sorted. Either way, record the fact that the
|
|
+ ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
|
|
+ ** variable. */
|
|
+ if( sSort.pOrderBy && pGroupBy->nExpr==sSort.pOrderBy->nExpr ){
|
|
+ int ii;
|
|
+ /* The GROUP BY processing doesn't care whether rows are delivered in
|
|
+ ** ASC or DESC order - only that each group is returned contiguously.
|
|
+ ** So set the ASC/DESC flags in the GROUP BY to match those in the
|
|
+ ** ORDER BY to maximize the chances of rows being delivered in an
|
|
+ ** order that makes the ORDER BY redundant. */
|
|
+ for(ii=0; ii<pGroupBy->nExpr; ii++){
|
|
+ u8 sortFlags = sSort.pOrderBy->a[ii].sortFlags & KEYINFO_ORDER_DESC;
|
|
+ pGroupBy->a[ii].sortFlags = sortFlags;
|
|
+ }
|
|
+ if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
|
|
+ orderByGrp = 1;
|
|
+ }
|
|
+ }
|
|
}else{
|
|
assert( 0==sqlite3LogEst(1) );
|
|
p->nSelectRow = 0;
|
|
}
|
|
|
|
- /* If there is both a GROUP BY and an ORDER BY clause and they are
|
|
- ** identical, then it may be possible to disable the ORDER BY clause
|
|
- ** on the grounds that the GROUP BY will cause elements to come out
|
|
- ** in the correct order. It also may not - the GROUP BY might use a
|
|
- ** database index that causes rows to be grouped together as required
|
|
- ** but not actually sorted. Either way, record the fact that the
|
|
- ** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
|
|
- ** variable. */
|
|
- if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
|
|
- orderByGrp = 1;
|
|
- }
|
|
-
|
|
/* Create a label to jump to when we want to abort the query */
|
|
addrEnd = sqlite3VdbeMakeLabel(pParse);
|
|
|
|
@@ -131364,9 +135218,16 @@
|
|
minMaxFlag = WHERE_ORDERBY_NORMAL;
|
|
}
|
|
for(i=0; i<sAggInfo.nFunc; i++){
|
|
- assert( !ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_xIsSelect) );
|
|
+ Expr *pExpr = sAggInfo.aFunc[i].pExpr;
|
|
+ assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
|
sNC.ncFlags |= NC_InAggFunc;
|
|
- sqlite3ExprAnalyzeAggList(&sNC, sAggInfo.aFunc[i].pExpr->x.pList);
|
|
+ sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ assert( !IsWindowFunc(pExpr) );
|
|
+ if( ExprHasProperty(pExpr, EP_WinFunc) ){
|
|
+ sqlite3ExprAnalyzeAggregates(&sNC, pExpr->y.pWin->pFilter);
|
|
+ }
|
|
+#endif
|
|
sNC.ncFlags &= ~NC_InAggFunc;
|
|
}
|
|
sAggInfo.mxReg = pParse->nMem;
|
|
@@ -131374,7 +135235,7 @@
|
|
#if SELECTTRACE_ENABLED
|
|
if( sqlite3SelectTrace & 0x400 ){
|
|
int ii;
|
|
- SELECTTRACE(0x400,pParse,p,("After aggregate analysis:\n"));
|
|
+ SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", &sAggInfo));
|
|
sqlite3TreeViewSelect(0, p, 0);
|
|
for(ii=0; ii<sAggInfo.nColumn; ii++){
|
|
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
|
|
@@ -131615,7 +135476,6 @@
|
|
|
|
} /* endif pGroupBy. Begin aggregate queries without GROUP BY: */
|
|
else {
|
|
-#ifndef SQLITE_OMIT_BTREECOUNT
|
|
Table *pTab;
|
|
if( (pTab = isSimpleCount(p, &sAggInfo))!=0 ){
|
|
/* If isSimpleCount() returns a pointer to a Table structure, then
|
|
@@ -131651,13 +135511,15 @@
|
|
** passed to keep OP_OpenRead happy.
|
|
*/
|
|
if( !HasRowid(pTab) ) pBest = sqlite3PrimaryKeyIndex(pTab);
|
|
- for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
|
- if( pIdx->bUnordered==0
|
|
- && pIdx->szIdxRow<pTab->szTabRow
|
|
- && pIdx->pPartIdxWhere==0
|
|
- && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
|
|
- ){
|
|
- pBest = pIdx;
|
|
+ if( !p->pSrc->a[0].fg.notIndexed ){
|
|
+ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
|
+ if( pIdx->bUnordered==0
|
|
+ && pIdx->szIdxRow<pTab->szTabRow
|
|
+ && pIdx->pPartIdxWhere==0
|
|
+ && (!pBest || pIdx->szIdxRow<pBest->szIdxRow)
|
|
+ ){
|
|
+ pBest = pIdx;
|
|
+ }
|
|
}
|
|
}
|
|
if( pBest ){
|
|
@@ -131673,18 +135535,21 @@
|
|
sqlite3VdbeAddOp2(v, OP_Count, iCsr, sAggInfo.aFunc[0].iMem);
|
|
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
|
|
explainSimpleCount(pParse, pTab, pBest);
|
|
- }else
|
|
-#endif /* SQLITE_OMIT_BTREECOUNT */
|
|
- {
|
|
+ }else{
|
|
int regAcc = 0; /* "populate accumulators" flag */
|
|
|
|
- /* If there are accumulator registers but no min() or max() functions,
|
|
- ** allocate register regAcc. Register regAcc will contain 0 the first
|
|
- ** time the inner loop runs, and 1 thereafter. The code generated
|
|
- ** by updateAccumulator() only updates the accumulator registers if
|
|
- ** regAcc contains 0. */
|
|
+ /* If there are accumulator registers but no min() or max() functions
|
|
+ ** without FILTER clauses, allocate register regAcc. Register regAcc
|
|
+ ** will contain 0 the first time the inner loop runs, and 1 thereafter.
|
|
+ ** The code generated by updateAccumulator() uses this to ensure
|
|
+ ** that the accumulator registers are (a) updated only once if
|
|
+ ** there are no min() or max functions or (b) always updated for the
|
|
+ ** first row visited by the aggregate, so that they are updated at
|
|
+ ** least once even if the FILTER clause means the min() or max()
|
|
+ ** function visits zero rows. */
|
|
if( sAggInfo.nAccumulator ){
|
|
for(i=0; i<sAggInfo.nFunc; i++){
|
|
+ if( ExprHasProperty(sAggInfo.aFunc[i].pExpr, EP_WinFunc) ) continue;
|
|
if( sAggInfo.aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ) break;
|
|
}
|
|
if( i==sAggInfo.nFunc ){
|
|
@@ -131833,7 +135698,7 @@
|
|
if( p->nData + need > p->nAlloc ){
|
|
char **azNew;
|
|
p->nAlloc = p->nAlloc*2 + need;
|
|
- azNew = sqlite3_realloc64( p->azResult, sizeof(char*)*p->nAlloc );
|
|
+ azNew = sqlite3Realloc( p->azResult, sizeof(char*)*p->nAlloc );
|
|
if( azNew==0 ) goto malloc_failed;
|
|
p->azResult = azNew;
|
|
}
|
|
@@ -131942,7 +135807,7 @@
|
|
}
|
|
if( res.nAlloc>res.nData ){
|
|
char **azNew;
|
|
- azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
|
|
+ azNew = sqlite3Realloc( res.azResult, sizeof(char*)*res.nData );
|
|
if( azNew==0 ){
|
|
sqlite3_free_table(&res.azResult[1]);
|
|
db->errCode = SQLITE_NOMEM;
|
|
@@ -132155,7 +136020,11 @@
|
|
/* Check that the trigger name is not reserved and that no trigger of the
|
|
** specified name exists */
|
|
zName = sqlite3NameFromToken(db, pName);
|
|
- if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
|
+ if( zName==0 ){
|
|
+ assert( db->mallocFailed );
|
|
+ goto trigger_cleanup;
|
|
+ }
|
|
+ if( sqlite3CheckObjectName(pParse, zName, "trigger", pTab->zName) ){
|
|
goto trigger_cleanup;
|
|
}
|
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
|
@@ -132318,6 +136187,7 @@
|
|
Trigger *pLink = pTrig;
|
|
Hash *pHash = &db->aDb[iDb].pSchema->trigHash;
|
|
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
|
+ assert( pLink!=0 );
|
|
pTrig = sqlite3HashInsert(pHash, zName, pTrig);
|
|
if( pTrig ){
|
|
sqlite3OomFault(db);
|
|
@@ -132436,6 +136306,9 @@
|
|
pTriggerStep->pIdList = pColumn;
|
|
pTriggerStep->pUpsert = pUpsert;
|
|
pTriggerStep->orconf = orconf;
|
|
+ if( pUpsert ){
|
|
+ sqlite3HasExplicitNulls(pParse, pUpsert->pUpsertTarget);
|
|
+ }
|
|
}else{
|
|
testcase( pColumn );
|
|
sqlite3IdListDelete(db, pColumn);
|
|
@@ -132550,7 +136423,7 @@
|
|
assert( zDb!=0 || sqlite3BtreeHoldsAllMutexes(db) );
|
|
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
|
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
|
- if( zDb && sqlite3StrICmp(db->aDb[j].zDbSName, zDb) ) continue;
|
|
+ if( zDb && sqlite3DbIsNamed(db, j, zDb)==0 ) continue;
|
|
assert( sqlite3SchemaMutexHeld(db, j, 0) );
|
|
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName);
|
|
if( pTrigger ) break;
|
|
@@ -132591,10 +136464,9 @@
|
|
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
|
|
assert( iDb>=0 && iDb<db->nDb );
|
|
pTable = tableOfTrigger(pTrigger);
|
|
- assert( pTable );
|
|
- assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
|
|
+ assert( (pTable && pTable->pSchema==pTrigger->pSchema) || iDb==1 );
|
|
#ifndef SQLITE_OMIT_AUTHORIZATION
|
|
- {
|
|
+ if( pTable ){
|
|
int code = SQLITE_DROP_TRIGGER;
|
|
const char *zDb = db->aDb[iDb].zDbSName;
|
|
const char *zTab = SCHEMA_TABLE(iDb);
|
|
@@ -132608,7 +136480,6 @@
|
|
|
|
/* Generate code to destroy the database record of the trigger.
|
|
*/
|
|
- assert( pTable!=0 );
|
|
if( (v = sqlite3GetVdbe(pParse))!=0 ){
|
|
sqlite3NestedParse(pParse,
|
|
"DELETE FROM %Q.%s WHERE name=%Q AND type='trigger'",
|
|
@@ -132632,9 +136503,15 @@
|
|
if( ALWAYS(pTrigger) ){
|
|
if( pTrigger->pSchema==pTrigger->pTabSchema ){
|
|
Table *pTab = tableOfTrigger(pTrigger);
|
|
- Trigger **pp;
|
|
- for(pp=&pTab->pTrigger; *pp!=pTrigger; pp=&((*pp)->pNext));
|
|
- *pp = (*pp)->pNext;
|
|
+ if( pTab ){
|
|
+ Trigger **pp;
|
|
+ for(pp=&pTab->pTrigger; *pp; pp=&((*pp)->pNext)){
|
|
+ if( *pp==pTrigger ){
|
|
+ *pp = (*pp)->pNext;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|
|
sqlite3DeleteTrigger(db, pTrigger);
|
|
db->mDbFlags |= DBFLAG_SchemaChange;
|
|
@@ -132654,7 +136531,7 @@
|
|
int e;
|
|
if( pIdList==0 || NEVER(pEList==0) ) return 1;
|
|
for(e=0; e<pEList->nExpr; e++){
|
|
- if( sqlite3IdListIndex(pIdList, pEList->a[e].zName)>=0 ) return 1;
|
|
+ if( sqlite3IdListIndex(pIdList, pEList->a[e].zEName)>=0 ) return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
@@ -133220,10 +137097,10 @@
|
|
** function is capable of transforming these types of expressions into
|
|
** sqlite3_value objects.
|
|
**
|
|
-** If parameter iReg is not negative, code an OP_RealAffinity instruction
|
|
-** on register iReg. This is used when an equivalent integer value is
|
|
-** stored in place of an 8-byte floating point value in order to save
|
|
-** space.
|
|
+** If column as REAL affinity and the table is an ordinary b-tree table
|
|
+** (not a virtual table) then the value might have been stored as an
|
|
+** integer. In that case, add an OP_RealAffinity opcode to make sure
|
|
+** it has been converted into REAL.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3ColumnDefault(Vdbe *v, Table *pTab, int i, int iReg){
|
|
assert( pTab!=0 );
|
|
@@ -133240,7 +137117,7 @@
|
|
}
|
|
}
|
|
#ifndef SQLITE_OMIT_FLOATING_POINT
|
|
- if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
|
|
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL && !IsVirtual(pTab) ){
|
|
sqlite3VdbeAddOp1(v, OP_RealAffinity, iReg);
|
|
}
|
|
#endif
|
|
@@ -133314,7 +137191,7 @@
|
|
Expr *pLimit, /* LIMIT clause. May be null */
|
|
Upsert *pUpsert /* ON CONFLICT clause, or null */
|
|
){
|
|
- int i, j; /* Loop counters */
|
|
+ int i, j, k; /* Loop counters */
|
|
Table *pTab; /* The table to be updated */
|
|
int addrTop = 0; /* VDBE instruction address of the start of the loop */
|
|
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
|
@@ -133358,6 +137235,7 @@
|
|
int iPk = 0; /* First of nPk cells holding PRIMARY KEY value */
|
|
i16 nPk = 0; /* Number of components of the PRIMARY KEY */
|
|
int bReplace = 0; /* True if REPLACE conflict resolution might happen */
|
|
+ int bFinishSeek = 1; /* The OP_FinishSeek opcode is needed */
|
|
|
|
/* Register Allocations */
|
|
int regRowCount = 0; /* A count of rows changed */
|
|
@@ -133456,6 +137334,10 @@
|
|
sNC.uNC.pUpsert = pUpsert;
|
|
sNC.ncFlags = NC_UUpsert;
|
|
|
|
+ /* Begin generating code. */
|
|
+ v = sqlite3GetVdbe(pParse);
|
|
+ if( v==0 ) goto update_cleanup;
|
|
+
|
|
/* Resolve the column names in all the expressions of the
|
|
** of the UPDATE statement. Also find the column index
|
|
** for each column to be updated in the pChanges array. For each
|
|
@@ -133468,24 +137350,34 @@
|
|
goto update_cleanup;
|
|
}
|
|
for(j=0; j<pTab->nCol; j++){
|
|
- if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zName)==0 ){
|
|
+ if( sqlite3StrICmp(pTab->aCol[j].zName, pChanges->a[i].zEName)==0 ){
|
|
if( j==pTab->iPKey ){
|
|
chngRowid = 1;
|
|
pRowidExpr = pChanges->a[i].pExpr;
|
|
}else if( pPk && (pTab->aCol[j].colFlags & COLFLAG_PRIMKEY)!=0 ){
|
|
chngPk = 1;
|
|
}
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ else if( pTab->aCol[j].colFlags & COLFLAG_GENERATED ){
|
|
+ testcase( pTab->aCol[j].colFlags & COLFLAG_VIRTUAL );
|
|
+ testcase( pTab->aCol[j].colFlags & COLFLAG_STORED );
|
|
+ sqlite3ErrorMsg(pParse,
|
|
+ "cannot UPDATE generated column \"%s\"",
|
|
+ pTab->aCol[j].zName);
|
|
+ goto update_cleanup;
|
|
+ }
|
|
+#endif
|
|
aXRef[j] = i;
|
|
break;
|
|
}
|
|
}
|
|
if( j>=pTab->nCol ){
|
|
- if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zName) ){
|
|
+ if( pPk==0 && sqlite3IsRowid(pChanges->a[i].zEName) ){
|
|
j = -1;
|
|
chngRowid = 1;
|
|
pRowidExpr = pChanges->a[i].pExpr;
|
|
}else{
|
|
- sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zName);
|
|
+ sqlite3ErrorMsg(pParse, "no such column: %s", pChanges->a[i].zEName);
|
|
pParse->checkSchema = 1;
|
|
goto update_cleanup;
|
|
}
|
|
@@ -133509,6 +137401,33 @@
|
|
assert( chngPk==0 || chngPk==1 );
|
|
chngKey = chngRowid + chngPk;
|
|
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ /* Mark generated columns as changing if their generator expressions
|
|
+ ** reference any changing column. The actual aXRef[] value for
|
|
+ ** generated expressions is not used, other than to check to see that it
|
|
+ ** is non-negative, so the value of aXRef[] for generated columns can be
|
|
+ ** set to any non-negative number. We use 99999 so that the value is
|
|
+ ** obvious when looking at aXRef[] in a symbolic debugger.
|
|
+ */
|
|
+ if( pTab->tabFlags & TF_HasGenerated ){
|
|
+ int bProgress;
|
|
+ testcase( pTab->tabFlags & TF_HasVirtual );
|
|
+ testcase( pTab->tabFlags & TF_HasStored );
|
|
+ do{
|
|
+ bProgress = 0;
|
|
+ for(i=0; i<pTab->nCol; i++){
|
|
+ if( aXRef[i]>=0 ) continue;
|
|
+ if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 ) continue;
|
|
+ if( sqlite3ExprReferencesUpdatedColumn(pTab->aCol[i].pDflt,
|
|
+ aXRef, chngRowid) ){
|
|
+ aXRef[i] = 99999;
|
|
+ bProgress = 1;
|
|
+ }
|
|
+ }
|
|
+ }while( bProgress );
|
|
+ }
|
|
+#endif
|
|
+
|
|
/* The SET expressions are not actually used inside the WHERE loop.
|
|
** So reset the colUsed mask. Unless this is a virtual table. In that
|
|
** case, set all bits of the colUsed mask (to ensure that the virtual
|
|
@@ -133553,9 +137472,6 @@
|
|
memset(aToOpen, 1, nIdx+1);
|
|
}
|
|
|
|
- /* Begin generating code. */
|
|
- v = sqlite3GetVdbe(pParse);
|
|
- if( v==0 ) goto update_cleanup;
|
|
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
|
|
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
|
|
|
|
@@ -133653,6 +137569,7 @@
|
|
pWInfo = 0;
|
|
eOnePass = ONEPASS_SINGLE;
|
|
sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
|
|
+ bFinishSeek = 0;
|
|
}else{
|
|
/* Begin the database scan.
|
|
**
|
|
@@ -133679,6 +137596,7 @@
|
|
** strategy that uses an index for which one or more columns are being
|
|
** updated. */
|
|
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
|
+ bFinishSeek = sqlite3WhereUsesDeferredSeek(pWInfo);
|
|
if( eOnePass!=ONEPASS_SINGLE ){
|
|
sqlite3MultiWrite(pParse);
|
|
if( eOnePass==ONEPASS_MULTI ){
|
|
@@ -133709,7 +137627,8 @@
|
|
** is not required) and leave the PK fields in the array of registers. */
|
|
for(i=0; i<nPk; i++){
|
|
assert( pPk->aiColumn[i]>=0 );
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,pPk->aiColumn[i],iPk+i);
|
|
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur,
|
|
+ pPk->aiColumn[i], iPk+i);
|
|
}
|
|
if( eOnePass ){
|
|
if( addrOpen ) sqlite3VdbeChangeToNoop(v, addrOpen);
|
|
@@ -133741,7 +137660,9 @@
|
|
}
|
|
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, 0, iBaseCur,
|
|
aToOpen, 0, 0);
|
|
- if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
|
+ if( addrOnce ){
|
|
+ sqlite3VdbeJumpHereOrPopInst(v, addrOnce);
|
|
+ }
|
|
}
|
|
|
|
/* Top of the update loop */
|
|
@@ -133790,14 +137711,16 @@
|
|
pTrigger, pChanges, 0, TRIGGER_BEFORE|TRIGGER_AFTER, pTab, onError
|
|
);
|
|
for(i=0; i<pTab->nCol; i++){
|
|
+ u32 colFlags = pTab->aCol[i].colFlags;
|
|
+ k = sqlite3TableColumnToStorage(pTab, i) + regOld;
|
|
if( oldmask==0xffffffff
|
|
|| (i<32 && (oldmask & MASKBIT32(i))!=0)
|
|
- || (pTab->aCol[i].colFlags & COLFLAG_PRIMKEY)!=0
|
|
+ || (colFlags & COLFLAG_PRIMKEY)!=0
|
|
){
|
|
testcase( oldmask!=0xffffffff && i==31 );
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regOld+i);
|
|
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
|
|
}else{
|
|
- sqlite3VdbeAddOp2(v, OP_Null, 0, regOld+i);
|
|
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
|
|
}
|
|
}
|
|
if( chngRowid==0 && pPk==0 ){
|
|
@@ -133821,13 +137744,15 @@
|
|
newmask = sqlite3TriggerColmask(
|
|
pParse, pTrigger, pChanges, 1, TRIGGER_BEFORE, pTab, onError
|
|
);
|
|
- for(i=0; i<pTab->nCol; i++){
|
|
+ for(i=0, k=regNew; i<pTab->nCol; i++, k++){
|
|
if( i==pTab->iPKey ){
|
|
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
|
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
|
|
+ }else if( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)!=0 ){
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
|
|
}else{
|
|
j = aXRef[i];
|
|
if( j>=0 ){
|
|
- sqlite3ExprCode(pParse, pChanges->a[j].pExpr, regNew+i);
|
|
+ sqlite3ExprCode(pParse, pChanges->a[j].pExpr, k);
|
|
}else if( 0==(tmask&TRIGGER_BEFORE) || i>31 || (newmask & MASKBIT32(i)) ){
|
|
/* This branch loads the value of a column that will not be changed
|
|
** into a register. This is done if there are no BEFORE triggers, or
|
|
@@ -133836,12 +137761,20 @@
|
|
*/
|
|
testcase( i==31 );
|
|
testcase( i==32 );
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
|
|
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
|
|
+ bFinishSeek = 0;
|
|
}else{
|
|
- sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
|
+ sqlite3VdbeAddOp2(v, OP_Null, 0, k);
|
|
}
|
|
}
|
|
}
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( pTab->tabFlags & TF_HasGenerated ){
|
|
+ testcase( pTab->tabFlags & TF_HasVirtual );
|
|
+ testcase( pTab->tabFlags & TF_HasStored );
|
|
+ sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
|
|
+ }
|
|
+#endif
|
|
|
|
/* Fire any BEFORE UPDATE triggers. This happens before constraints are
|
|
** verified. One could argue that this is wrong.
|
|
@@ -133874,38 +137807,58 @@
|
|
** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
|
|
** for an example.
|
|
*/
|
|
- for(i=0; i<pTab->nCol; i++){
|
|
- if( aXRef[i]<0 && i!=pTab->iPKey ){
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, regNew+i);
|
|
+ for(i=0, k=regNew; i<pTab->nCol; i++, k++){
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_GENERATED ){
|
|
+ if( pTab->aCol[i].colFlags & COLFLAG_VIRTUAL ) k--;
|
|
+ }else if( aXRef[i]<0 && i!=pTab->iPKey ){
|
|
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, i, k);
|
|
}
|
|
}
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ if( pTab->tabFlags & TF_HasGenerated ){
|
|
+ testcase( pTab->tabFlags & TF_HasVirtual );
|
|
+ testcase( pTab->tabFlags & TF_HasStored );
|
|
+ sqlite3ComputeGeneratedColumns(pParse, regNew, pTab);
|
|
+ }
|
|
+#endif
|
|
}
|
|
|
|
if( !isView ){
|
|
- int addr1 = 0; /* Address of jump instruction */
|
|
-
|
|
/* Do constraint checks. */
|
|
assert( regOldRowid>0 );
|
|
sqlite3GenerateConstraintChecks(pParse, pTab, aRegIdx, iDataCur, iIdxCur,
|
|
regNewRowid, regOldRowid, chngKey, onError, labelContinue, &bReplace,
|
|
aXRef, 0);
|
|
|
|
- /* Do FK constraint checks. */
|
|
- if( hasFK ){
|
|
- sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
|
|
- }
|
|
-
|
|
- /* Delete the index entries associated with the current record. */
|
|
+ /* If REPLACE conflict handling may have been used, or if the PK of the
|
|
+ ** row is changing, then the GenerateConstraintChecks() above may have
|
|
+ ** moved cursor iDataCur. Reseek it. */
|
|
if( bReplace || chngKey ){
|
|
if( pPk ){
|
|
- addr1 = sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, 0, regKey, nKey);
|
|
+ sqlite3VdbeAddOp4Int(v, OP_NotFound,iDataCur,labelContinue,regKey,nKey);
|
|
}else{
|
|
- addr1 = sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, 0, regOldRowid);
|
|
+ sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, labelContinue,regOldRowid);
|
|
}
|
|
VdbeCoverageNeverTaken(v);
|
|
}
|
|
+
|
|
+ /* Do FK constraint checks. */
|
|
+ if( hasFK ){
|
|
+ sqlite3FkCheck(pParse, pTab, regOldRowid, 0, aXRef, chngKey);
|
|
+ }
|
|
+
|
|
+ /* Delete the index entries associated with the current record. */
|
|
sqlite3GenerateRowIndexDelete(pParse, pTab, iDataCur, iIdxCur, aRegIdx, -1);
|
|
|
|
+ /* We must run the OP_FinishSeek opcode to resolve a prior
|
|
+ ** OP_DeferredSeek if there is any possibility that there have been
|
|
+ ** no OP_Column opcodes since the OP_DeferredSeek was issued. But
|
|
+ ** we want to avoid the OP_FinishSeek if possible, as running it
|
|
+ ** costs CPU cycles. */
|
|
+ if( bFinishSeek ){
|
|
+ sqlite3VdbeAddOp1(v, OP_FinishSeek, iDataCur);
|
|
+ }
|
|
+
|
|
/* If changing the rowid value, or if there are foreign key constraints
|
|
** to process, delete the old record. Otherwise, add a noop OP_Delete
|
|
** to invoke the pre-update hook.
|
|
@@ -133933,9 +137886,6 @@
|
|
sqlite3VdbeAddOp2(v, OP_Delete, iDataCur, 0);
|
|
}
|
|
#endif
|
|
- if( bReplace || chngKey ){
|
|
- sqlite3VdbeJumpHere(v, addr1);
|
|
- }
|
|
|
|
if( hasFK ){
|
|
sqlite3FkCheck(pParse, pTab, 0, regNewRowid, aXRef, chngKey);
|
|
@@ -134085,6 +138035,7 @@
|
|
|
|
/* Populate the argument registers. */
|
|
for(i=0; i<pTab->nCol; i++){
|
|
+ assert( (pTab->aCol[i].colFlags & COLFLAG_GENERATED)==0 );
|
|
if( aXRef[i]>=0 ){
|
|
sqlite3ExprCode(pParse, pChanges->a[aXRef[i]].pExpr, regArg+2+i);
|
|
}else{
|
|
@@ -134374,6 +138325,7 @@
|
|
sqlite3 *db = pParse->db;
|
|
SrcList *pSrc; /* FROM clause for the UPDATE */
|
|
int iDataCur;
|
|
+ int i;
|
|
|
|
assert( v!=0 );
|
|
assert( pUpsert!=0 );
|
|
@@ -134390,12 +138342,11 @@
|
|
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
|
int nPk = pPk->nKeyCol;
|
|
int iPk = pParse->nMem+1;
|
|
- int i;
|
|
pParse->nMem += nPk;
|
|
for(i=0; i<nPk; i++){
|
|
int k;
|
|
assert( pPk->aiColumn[i]>=0 );
|
|
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
|
|
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[i]);
|
|
sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
|
|
VdbeComment((v, "%s.%s", pIdx->zName,
|
|
pTab->aCol[pPk->aiColumn[i]].zName));
|
|
@@ -134405,12 +138356,19 @@
|
|
VdbeCoverage(v);
|
|
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
|
|
"corrupt database", P4_STATIC);
|
|
+ sqlite3MayAbort(pParse);
|
|
sqlite3VdbeJumpHere(v, i);
|
|
}
|
|
}
|
|
/* pUpsert does not own pUpsertSrc - the outer INSERT statement does. So
|
|
** we have to make a copy before passing it down into sqlite3Update() */
|
|
pSrc = sqlite3SrcListDup(db, pUpsert->pUpsertSrc, 0);
|
|
+ /* excluded.* columns of type REAL need to be converted to a hard real */
|
|
+ for(i=0; i<pTab->nCol; i++){
|
|
+ if( pTab->aCol[i].affinity==SQLITE_AFF_REAL ){
|
|
+ sqlite3VdbeAddOp1(v, OP_RealAffinity, pUpsert->regData+i);
|
|
+ }
|
|
+ }
|
|
sqlite3Update(pParse, pSrc, pUpsert->pUpsertSet,
|
|
pUpsert->pUpsertWhere, OE_Abort, 0, 0, pUpsert);
|
|
pUpsert->pUpsertSet = 0; /* Will have been deleted by sqlite3Update() */
|
|
@@ -134657,18 +138615,7 @@
|
|
}
|
|
db->mDbFlags |= DBFLAG_VacuumInto;
|
|
}
|
|
- nRes = sqlite3BtreeGetOptimalReserve(pMain);
|
|
-
|
|
- /* A VACUUM cannot change the pagesize of an encrypted database. */
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
- if( db->nextPagesize ){
|
|
- extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
|
|
- int nKey;
|
|
- char *zKey;
|
|
- sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
|
|
- if( nKey ) db->nextPagesize = 0;
|
|
- }
|
|
-#endif
|
|
+ nRes = sqlite3BtreeGetRequestedReserve(pMain);
|
|
|
|
sqlite3BtreeSetCacheSize(pTemp, db->aDb[iDb].pSchema->cache_size);
|
|
sqlite3BtreeSetSpillSize(pTemp, sqlite3BtreeSetSpillSize(pMain,0));
|
|
@@ -134812,7 +138759,7 @@
|
|
db->nChange = saved_nChange;
|
|
db->nTotalChange = saved_nTotalChange;
|
|
db->mTrace = saved_mTrace;
|
|
- sqlite3BtreeSetPageSize(pMain, -1, -1, 1);
|
|
+ sqlite3BtreeSetPageSize(pMain, -1, 0, 1);
|
|
|
|
/* Currently there is an SQL level transaction open on the vacuum
|
|
** database. No locks are held on any other files (since the main file
|
|
@@ -134874,6 +138821,9 @@
|
|
** Construct and install a Module object for a virtual table. When this
|
|
** routine is called, it is guaranteed that all appropriate locks are held
|
|
** and the module is not already part of the connection.
|
|
+**
|
|
+** If there already exists a module with zName, replace it with the new one.
|
|
+** If pModule==0, then delete the module zName if it exists.
|
|
*/
|
|
SQLITE_PRIVATE Module *sqlite3VtabCreateModule(
|
|
sqlite3 *db, /* Database in which module is registered */
|
|
@@ -134883,25 +138833,36 @@
|
|
void (*xDestroy)(void *) /* Module destructor function */
|
|
){
|
|
Module *pMod;
|
|
- int nName = sqlite3Strlen30(zName);
|
|
- pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
|
|
- if( pMod==0 ){
|
|
- sqlite3OomFault(db);
|
|
+ Module *pDel;
|
|
+ char *zCopy;
|
|
+ if( pModule==0 ){
|
|
+ zCopy = (char*)zName;
|
|
+ pMod = 0;
|
|
}else{
|
|
- Module *pDel;
|
|
- char *zCopy = (char *)(&pMod[1]);
|
|
+ int nName = sqlite3Strlen30(zName);
|
|
+ pMod = (Module *)sqlite3Malloc(sizeof(Module) + nName + 1);
|
|
+ if( pMod==0 ){
|
|
+ sqlite3OomFault(db);
|
|
+ return 0;
|
|
+ }
|
|
+ zCopy = (char *)(&pMod[1]);
|
|
memcpy(zCopy, zName, nName+1);
|
|
pMod->zName = zCopy;
|
|
pMod->pModule = pModule;
|
|
pMod->pAux = pAux;
|
|
pMod->xDestroy = xDestroy;
|
|
pMod->pEpoTab = 0;
|
|
- pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
|
|
- assert( pDel==0 || pDel==pMod );
|
|
- if( pDel ){
|
|
+ pMod->nRefModule = 1;
|
|
+ }
|
|
+ pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
|
|
+ if( pDel ){
|
|
+ if( pDel==pMod ){
|
|
sqlite3OomFault(db);
|
|
sqlite3DbFree(db, pDel);
|
|
pMod = 0;
|
|
+ }else{
|
|
+ sqlite3VtabEponymousTableClear(db, pDel);
|
|
+ sqlite3VtabModuleUnref(db, pDel);
|
|
}
|
|
}
|
|
return pMod;
|
|
@@ -134922,11 +138883,7 @@
|
|
int rc = SQLITE_OK;
|
|
|
|
sqlite3_mutex_enter(db->mutex);
|
|
- if( sqlite3HashFind(&db->aModule, zName) ){
|
|
- rc = SQLITE_MISUSE_BKPT;
|
|
- }else{
|
|
- (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
|
|
- }
|
|
+ (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy);
|
|
rc = sqlite3ApiExit(db, rc);
|
|
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux);
|
|
sqlite3_mutex_leave(db->mutex);
|
|
@@ -134965,6 +138922,44 @@
|
|
return createModule(db, zName, pModule, pAux, xDestroy);
|
|
}
|
|
|
|
+/*
|
|
+** External API to drop all virtual-table modules, except those named
|
|
+** on the azNames list.
|
|
+*/
|
|
+SQLITE_API int sqlite3_drop_modules(sqlite3 *db, const char** azNames){
|
|
+ HashElem *pThis, *pNext;
|
|
+#ifdef SQLITE_ENABLE_API_ARMOR
|
|
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
|
+#endif
|
|
+ for(pThis=sqliteHashFirst(&db->aModule); pThis; pThis=pNext){
|
|
+ Module *pMod = (Module*)sqliteHashData(pThis);
|
|
+ pNext = sqliteHashNext(pThis);
|
|
+ if( azNames ){
|
|
+ int ii;
|
|
+ for(ii=0; azNames[ii]!=0 && strcmp(azNames[ii],pMod->zName)!=0; ii++){}
|
|
+ if( azNames[ii]!=0 ) continue;
|
|
+ }
|
|
+ createModule(db, pMod->zName, 0, 0, 0);
|
|
+ }
|
|
+ return SQLITE_OK;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Decrement the reference count on a Module object. Destroy the
|
|
+** module when the reference count reaches zero.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3VtabModuleUnref(sqlite3 *db, Module *pMod){
|
|
+ assert( pMod->nRefModule>0 );
|
|
+ pMod->nRefModule--;
|
|
+ if( pMod->nRefModule==0 ){
|
|
+ if( pMod->xDestroy ){
|
|
+ pMod->xDestroy(pMod->pAux);
|
|
+ }
|
|
+ assert( pMod->pEpoTab==0 );
|
|
+ sqlite3DbFree(db, pMod);
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Lock the virtual table so that it cannot be disconnected.
|
|
** Locks nest. Every lock should have a corresponding unlock.
|
|
@@ -135004,6 +138999,7 @@
|
|
pVTab->nRef--;
|
|
if( pVTab->nRef==0 ){
|
|
sqlite3_vtab *p = pVTab->pVtab;
|
|
+ sqlite3VtabModuleUnref(pVTab->db, pVTab->pMod);
|
|
if( p ){
|
|
p->pModule->xDisconnect(p);
|
|
}
|
|
@@ -135098,12 +139094,12 @@
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3VtabUnlockList(sqlite3 *db){
|
|
VTable *p = db->pDisconnect;
|
|
- db->pDisconnect = 0;
|
|
|
|
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
|
assert( sqlite3_mutex_held(db->mutex) );
|
|
|
|
if( p ){
|
|
+ db->pDisconnect = 0;
|
|
sqlite3ExpirePreparedStatements(db, 0);
|
|
do {
|
|
VTable *pNext = p->pNext;
|
|
@@ -135250,6 +139246,8 @@
|
|
int iReg;
|
|
Vdbe *v;
|
|
|
|
+ sqlite3MayAbort(pParse);
|
|
+
|
|
/* Compute the complete text of the CREATE VIRTUAL TABLE statement */
|
|
if( pEnd ){
|
|
pParse->sNameToken.n = (int)(pEnd->z - pParse->sNameToken.z) + pEnd->n;
|
|
@@ -135275,13 +139273,13 @@
|
|
zStmt,
|
|
pParse->regRowid
|
|
);
|
|
- sqlite3DbFree(db, zStmt);
|
|
v = sqlite3GetVdbe(pParse);
|
|
sqlite3ChangeCookie(pParse, iDb);
|
|
|
|
sqlite3VdbeAddOp0(v, OP_Expire);
|
|
- zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
|
|
+ zWhere = sqlite3MPrintf(db, "name=%Q AND sql=%Q", pTab->zName, zStmt);
|
|
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
|
|
+ sqlite3DbFree(db, zStmt);
|
|
|
|
iReg = ++pParse->nMem;
|
|
sqlite3VdbeLoadString(v, iReg, pTab->zName);
|
|
@@ -135378,6 +139376,7 @@
|
|
}
|
|
pVTable->db = db;
|
|
pVTable->pMod = pMod;
|
|
+ pVTable->eVtabRisk = SQLITE_VTABRISK_Normal;
|
|
|
|
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
|
pTab->azModuleArg[1] = db->aDb[iDb].zDbSName;
|
|
@@ -135408,6 +139407,7 @@
|
|
** the sqlite3_vtab object if successful. */
|
|
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
|
|
pVTable->pVtab->pModule = pMod->pModule;
|
|
+ pMod->nRefModule++;
|
|
pVTable->nRef = 1;
|
|
if( sCtx.bDeclared==0 ){
|
|
const char *zFormat = "vtable constructor did not declare schema: %s";
|
|
@@ -135416,7 +139416,7 @@
|
|
rc = SQLITE_ERROR;
|
|
}else{
|
|
int iCol;
|
|
- u8 oooHidden = 0;
|
|
+ u16 oooHidden = 0;
|
|
/* If everything went according to plan, link the new VTable structure
|
|
** into the linked list headed by pTab->pVTable. Then loop through the
|
|
** columns of the table to see if any of them contain the token "hidden".
|
|
@@ -135682,7 +139682,8 @@
|
|
}
|
|
p = vtabDisconnectAll(db, pTab);
|
|
xDestroy = p->pMod->pModule->xDestroy;
|
|
- assert( xDestroy!=0 ); /* Checked before the virtual table is created */
|
|
+ if( xDestroy==0 ) xDestroy = p->pMod->pModule->xDisconnect;
|
|
+ assert( xDestroy!=0 );
|
|
pTab->nTabRef++;
|
|
rc = xDestroy(p->pVtab);
|
|
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
|
|
@@ -135965,7 +139966,7 @@
|
|
if( pTab==pToplevel->apVtabLock[i] ) return;
|
|
}
|
|
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
|
|
- apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
|
|
+ apVtabLock = sqlite3Realloc(pToplevel->apVtabLock, n);
|
|
if( apVtabLock ){
|
|
pToplevel->apVtabLock = apVtabLock;
|
|
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
|
|
@@ -136065,28 +140066,38 @@
|
|
SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
|
|
va_list ap;
|
|
int rc = SQLITE_OK;
|
|
+ VtabCtx *p;
|
|
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
|
|
#endif
|
|
sqlite3_mutex_enter(db->mutex);
|
|
- va_start(ap, op);
|
|
- switch( op ){
|
|
- case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
|
|
- VtabCtx *p = db->pVtabCtx;
|
|
- if( !p ){
|
|
- rc = SQLITE_MISUSE_BKPT;
|
|
- }else{
|
|
- assert( p->pTab==0 || IsVirtual(p->pTab) );
|
|
+ p = db->pVtabCtx;
|
|
+ if( !p ){
|
|
+ rc = SQLITE_MISUSE_BKPT;
|
|
+ }else{
|
|
+ assert( p->pTab==0 || IsVirtual(p->pTab) );
|
|
+ va_start(ap, op);
|
|
+ switch( op ){
|
|
+ case SQLITE_VTAB_CONSTRAINT_SUPPORT: {
|
|
p->pVTable->bConstraint = (u8)va_arg(ap, int);
|
|
+ break;
|
|
+ }
|
|
+ case SQLITE_VTAB_INNOCUOUS: {
|
|
+ p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low;
|
|
+ break;
|
|
+ }
|
|
+ case SQLITE_VTAB_DIRECTONLY: {
|
|
+ p->pVTable->eVtabRisk = SQLITE_VTABRISK_High;
|
|
+ break;
|
|
+ }
|
|
+ default: {
|
|
+ rc = SQLITE_MISUSE_BKPT;
|
|
+ break;
|
|
}
|
|
- break;
|
|
}
|
|
- default:
|
|
- rc = SQLITE_MISUSE_BKPT;
|
|
- break;
|
|
+ va_end(ap);
|
|
}
|
|
- va_end(ap);
|
|
|
|
if( rc!=SQLITE_OK ) sqlite3Error(db, rc);
|
|
sqlite3_mutex_leave(db->mutex);
|
|
@@ -136192,13 +140203,15 @@
|
|
int addrCont; /* Jump here to continue with the next loop cycle */
|
|
int addrFirst; /* First instruction of interior of the loop */
|
|
int addrBody; /* Beginning of the body of this loop */
|
|
+ int regBignull; /* big-null flag reg. True if a NULL-scan is needed */
|
|
+ int addrBignull; /* Jump here for next part of big-null scan */
|
|
#ifndef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
|
u32 iLikeRepCntr; /* LIKE range processing counter register (times 2) */
|
|
int addrLikeRep; /* LIKE range processing address */
|
|
#endif
|
|
u8 iFrom; /* Which entry in the FROM clause */
|
|
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
|
|
- int p1, p2; /* Operands of the opcode used to ends the loop */
|
|
+ int p1, p2; /* Operands of the opcode used to end the loop */
|
|
union { /* Information that depends on pWLoop->wsFlags */
|
|
struct {
|
|
int nIn; /* Number of entries in aInLoop[] */
|
|
@@ -136249,7 +140262,7 @@
|
|
u16 nEq; /* Number of equality constraints */
|
|
u16 nBtm; /* Size of BTM vector */
|
|
u16 nTop; /* Size of TOP vector */
|
|
- u16 nIdxCol; /* Index column used for ORDER BY */
|
|
+ u16 nDistinctCol; /* Index columns used to sort for DISTINCT */
|
|
Index *pIndex; /* Index used, or NULL */
|
|
} btree;
|
|
struct { /* Information for virtual tables */
|
|
@@ -136393,23 +140406,29 @@
|
|
/*
|
|
** Allowed values of WhereTerm.wtFlags
|
|
*/
|
|
-#define TERM_DYNAMIC 0x01 /* Need to call sqlite3ExprDelete(db, pExpr) */
|
|
-#define TERM_VIRTUAL 0x02 /* Added by the optimizer. Do not code */
|
|
-#define TERM_CODED 0x04 /* This term is already coded */
|
|
-#define TERM_COPIED 0x08 /* Has a child */
|
|
-#define TERM_ORINFO 0x10 /* Need to free the WhereTerm.u.pOrInfo object */
|
|
-#define TERM_ANDINFO 0x20 /* Need to free the WhereTerm.u.pAndInfo obj */
|
|
-#define TERM_OR_OK 0x40 /* Used during OR-clause processing */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
-# define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */
|
|
-#else
|
|
-# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
|
|
-#endif
|
|
-#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
|
|
-#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
|
|
-#define TERM_LIKE 0x400 /* The original LIKE operator */
|
|
-#define TERM_IS 0x800 /* Term.pExpr is an IS operator */
|
|
+#define TERM_DYNAMIC 0x0001 /* Need to call sqlite3ExprDelete(db, pExpr) */
|
|
+#define TERM_VIRTUAL 0x0002 /* Added by the optimizer. Do not code */
|
|
+#define TERM_CODED 0x0004 /* This term is already coded */
|
|
+#define TERM_COPIED 0x0008 /* Has a child */
|
|
+#define TERM_ORINFO 0x0010 /* Need to free the WhereTerm.u.pOrInfo object */
|
|
+#define TERM_ANDINFO 0x0020 /* Need to free the WhereTerm.u.pAndInfo obj */
|
|
+#define TERM_OR_OK 0x0040 /* Used during OR-clause processing */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+# define TERM_VNULL 0x0080 /* Manufactured x>NULL or x<=NULL term */
|
|
+#else
|
|
+# define TERM_VNULL 0x0000 /* Disabled if not using stat4 */
|
|
+#endif
|
|
+#define TERM_LIKEOPT 0x0100 /* Virtual terms from the LIKE optimization */
|
|
+#define TERM_LIKECOND 0x0200 /* Conditionally this LIKE operator term */
|
|
+#define TERM_LIKE 0x0400 /* The original LIKE operator */
|
|
+#define TERM_IS 0x0800 /* Term.pExpr is an IS operator */
|
|
#define TERM_VARSELECT 0x1000 /* Term.pExpr contains a correlated sub-query */
|
|
+#define TERM_HEURTRUTH 0x2000 /* Heuristic truthProb used */
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+# define TERM_HIGHTRUTH 0x4000 /* Term excludes few rows */
|
|
+#else
|
|
+# define TERM_HIGHTRUTH 0 /* Only used with STAT4 */
|
|
+#endif
|
|
|
|
/*
|
|
** An instance of the WhereScan object is used as an iterator for locating
|
|
@@ -136520,17 +140539,20 @@
|
|
ExprList *pOrderBy; /* ORDER BY clause */
|
|
WhereLoop *pNew; /* Template WhereLoop */
|
|
WhereOrSet *pOrSet; /* Record best loops here, if not NULL */
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
UnpackedRecord *pRec; /* Probe for stat4 (if required) */
|
|
int nRecValid; /* Number of valid fields currently in pRec */
|
|
#endif
|
|
- unsigned int bldFlags; /* SQLITE_BLDF_* flags */
|
|
+ unsigned char bldFlags1; /* First set of SQLITE_BLDF_* flags */
|
|
+ unsigned char bldFlags2; /* Second set of SQLITE_BLDF_* flags */
|
|
unsigned int iPlanLimit; /* Search limiter */
|
|
};
|
|
|
|
/* Allowed values for WhereLoopBuider.bldFlags */
|
|
-#define SQLITE_BLDF_INDEXED 0x0001 /* An index is used */
|
|
-#define SQLITE_BLDF_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
|
|
+#define SQLITE_BLDF1_INDEXED 0x0001 /* An index is used */
|
|
+#define SQLITE_BLDF1_UNIQUE 0x0002 /* All keys of a UNIQUE index used */
|
|
+
|
|
+#define SQLITE_BLDF2_2NDPASS 0x0004 /* Second builder pass needed */
|
|
|
|
/* The WhereLoopBuilder.iPlanLimit is used to limit the number of
|
|
** index+constraint combinations the query planner will consider for a
|
|
@@ -136552,6 +140574,20 @@
|
|
# define SQLITE_QUERY_PLANNER_LIMIT_INCR 1000
|
|
#endif
|
|
|
|
+/*
|
|
+** Each instance of this object records a change to a single node
|
|
+** in an expression tree to cause that node to point to a column
|
|
+** of an index rather than an expression or a virtual column. All
|
|
+** such transformations need to be undone at the end of WHERE clause
|
|
+** processing.
|
|
+*/
|
|
+typedef struct WhereExprMod WhereExprMod;
|
|
+struct WhereExprMod {
|
|
+ WhereExprMod *pNext; /* Next translation on a list of them all */
|
|
+ Expr *pExpr; /* The Expr node that was transformed */
|
|
+ Expr orig; /* Original value of the Expr node */
|
|
+};
|
|
+
|
|
/*
|
|
** The WHERE clause processing routine has two halves. The
|
|
** first part does the start of the WHERE loop and the second
|
|
@@ -136568,23 +140604,25 @@
|
|
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
|
ExprList *pResultSet; /* Result set of the query */
|
|
Expr *pWhere; /* The complete WHERE clause */
|
|
- LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
|
|
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
|
|
int iContinue; /* Jump here to continue with next record */
|
|
int iBreak; /* Jump here to break out of the loop */
|
|
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
|
|
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
|
+ LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
|
|
u8 nLevel; /* Number of nested loop */
|
|
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
|
|
- u8 sorted; /* True if really sorted (not just grouped) */
|
|
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
|
|
- u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
|
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
|
|
- u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
|
|
+ unsigned bDeferredSeek :1; /* Uses OP_DeferredSeek */
|
|
+ unsigned untestedTerms :1; /* Not all WHERE terms resolved by outer loop */
|
|
+ unsigned bOrderedInnerLoop:1;/* True if only the inner-most loop is ordered */
|
|
+ unsigned sorted :1; /* True if really sorted (not just grouped) */
|
|
+ LogEst nRowOut; /* Estimated number of output rows */
|
|
int iTop; /* The very beginning of the WHERE loop */
|
|
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
|
+ WhereExprMod *pExprMods; /* Expression modifications */
|
|
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
|
- LogEst nRowOut; /* Estimated number of output rows */
|
|
WhereClause sWC; /* Decomposition of the WHERE clause */
|
|
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
|
|
WhereLevel a[1]; /* Information about each nest loop in WHERE */
|
|
@@ -136598,6 +140636,8 @@
|
|
SQLITE_PRIVATE Bitmask sqlite3WhereGetMask(WhereMaskSet*,int);
|
|
#ifdef WHERETRACE_ENABLED
|
|
SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC);
|
|
+SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm);
|
|
+SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC);
|
|
#endif
|
|
SQLITE_PRIVATE WhereTerm *sqlite3WhereFindTerm(
|
|
WhereClause *pWC, /* The WHERE clause to be searched */
|
|
@@ -136707,6 +140747,7 @@
|
|
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
|
|
#define WHERE_PARTIALIDX 0x00020000 /* The automatic index is partial */
|
|
#define WHERE_IN_EARLYOUT 0x00040000 /* Perhaps quit IN loops early */
|
|
+#define WHERE_BIGNULL_SORT 0x00080000 /* Column nEq of index is BIGNULL */
|
|
|
|
#endif /* !defined(SQLITE_WHEREINT_H) */
|
|
|
|
@@ -137011,9 +141052,9 @@
|
|
** Code an OP_Affinity opcode to apply the column affinity string zAff
|
|
** to the n registers starting at base.
|
|
**
|
|
-** As an optimization, SQLITE_AFF_BLOB entries (which are no-ops) at the
|
|
-** beginning and end of zAff are ignored. If all entries in zAff are
|
|
-** SQLITE_AFF_BLOB, then no code gets generated.
|
|
+** As an optimization, SQLITE_AFF_BLOB and SQLITE_AFF_NONE entries (which
|
|
+** are no-ops) at the beginning and end of zAff are ignored. If all entries
|
|
+** in zAff are SQLITE_AFF_BLOB or SQLITE_AFF_NONE, then no code gets generated.
|
|
**
|
|
** This routine makes its own copy of zAff so that the caller is free
|
|
** to modify zAff after this routine returns.
|
|
@@ -137026,15 +141067,16 @@
|
|
}
|
|
assert( v!=0 );
|
|
|
|
- /* Adjust base and n to skip over SQLITE_AFF_BLOB entries at the beginning
|
|
- ** and end of the affinity string.
|
|
+ /* Adjust base and n to skip over SQLITE_AFF_BLOB and SQLITE_AFF_NONE
|
|
+ ** entries at the beginning and end of the affinity string.
|
|
*/
|
|
- while( n>0 && zAff[0]==SQLITE_AFF_BLOB ){
|
|
+ assert( SQLITE_AFF_NONE<SQLITE_AFF_BLOB );
|
|
+ while( n>0 && zAff[0]<=SQLITE_AFF_BLOB ){
|
|
n--;
|
|
base++;
|
|
zAff++;
|
|
}
|
|
- while( n>1 && zAff[n-1]==SQLITE_AFF_BLOB ){
|
|
+ while( n>1 && zAff[n-1]<=SQLITE_AFF_BLOB ){
|
|
n--;
|
|
}
|
|
|
|
@@ -137107,7 +141149,8 @@
|
|
Expr *pX /* The IN expression to be reduced */
|
|
){
|
|
sqlite3 *db = pParse->db;
|
|
- Expr *pNew = sqlite3ExprDup(db, pX, 0);
|
|
+ Expr *pNew;
|
|
+ pNew = sqlite3ExprDup(db, pX, 0);
|
|
if( db->mallocFailed==0 ){
|
|
ExprList *pOrigRhs = pNew->x.pSelect->pEList; /* Original unmodified RHS */
|
|
ExprList *pOrigLhs = pNew->pLeft->x.pList; /* Original unmodified LHS */
|
|
@@ -137284,7 +141327,7 @@
|
|
if( i==iEq ){
|
|
pIn->iCur = iTab;
|
|
pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next;
|
|
- if( iEq>0 && (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
|
+ if( iEq>0 ){
|
|
pIn->iBase = iReg - i;
|
|
pIn->nPrefix = i;
|
|
pLoop->wsFlags |= WHERE_IN_EARLYOUT;
|
|
@@ -137515,7 +141558,7 @@
|
|
assert( pHint->pIdx!=0 );
|
|
if( pExpr->op==TK_COLUMN
|
|
&& pExpr->iTable==pHint->iTabCur
|
|
- && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0
|
|
+ && sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn)<0
|
|
){
|
|
pWalker->eCode = 1;
|
|
}
|
|
@@ -137583,7 +141626,7 @@
|
|
pExpr->iTable = reg;
|
|
}else if( pHint->pIdx!=0 ){
|
|
pExpr->iTable = pHint->iIdxCur;
|
|
- pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn);
|
|
+ pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
|
|
assert( pExpr->iColumn>=0 );
|
|
}
|
|
}else if( pExpr->op==TK_AGG_FUNCTION ){
|
|
@@ -137736,6 +141779,7 @@
|
|
assert( iIdxCur>0 );
|
|
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
|
|
|
|
+ pWInfo->bDeferredSeek = 1;
|
|
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
|
|
if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
|
|
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
|
|
@@ -137746,8 +141790,12 @@
|
|
if( ai ){
|
|
ai[0] = pTab->nCol;
|
|
for(i=0; i<pIdx->nColumn-1; i++){
|
|
+ int x1, x2;
|
|
assert( pIdx->aiColumn[i]<pTab->nCol );
|
|
- if( pIdx->aiColumn[i]>=0 ) ai[pIdx->aiColumn[i]+1] = i+1;
|
|
+ x1 = pIdx->aiColumn[i];
|
|
+ x2 = sqlite3TableColumnToStorage(pTab, x1);
|
|
+ testcase( x1!=x2 );
|
|
+ if( x1>=0 ) ai[x2+1] = i+1;
|
|
}
|
|
sqlite3VdbeChangeP4(v, -1, (char*)ai, P4_INTARRAY);
|
|
}
|
|
@@ -137798,8 +141846,24 @@
|
|
int iTabCur; /* The cursor of the corresponding table */
|
|
int iIdxCur; /* The cursor for the index */
|
|
int iIdxCol; /* The column for the index */
|
|
+ int iTabCol; /* The column for the table */
|
|
+ WhereInfo *pWInfo; /* Complete WHERE clause information */
|
|
+ sqlite3 *db; /* Database connection (for malloc()) */
|
|
} IdxExprTrans;
|
|
|
|
+/*
|
|
+** Preserve pExpr on the WhereETrans list of the WhereInfo.
|
|
+*/
|
|
+static void preserveExpr(IdxExprTrans *pTrans, Expr *pExpr){
|
|
+ WhereExprMod *pNew;
|
|
+ pNew = sqlite3DbMallocRaw(pTrans->db, sizeof(*pNew));
|
|
+ if( pNew==0 ) return;
|
|
+ pNew->pNext = pTrans->pWInfo->pExprMods;
|
|
+ pTrans->pWInfo->pExprMods = pNew;
|
|
+ pNew->pExpr = pExpr;
|
|
+ memcpy(&pNew->orig, pExpr, sizeof(*pExpr));
|
|
+}
|
|
+
|
|
/* The walker node callback used to transform matching expressions into
|
|
** a reference to an index column for an index on an expression.
|
|
**
|
|
@@ -137809,20 +141873,49 @@
|
|
static int whereIndexExprTransNode(Walker *p, Expr *pExpr){
|
|
IdxExprTrans *pX = p->u.pIdxTrans;
|
|
if( sqlite3ExprCompare(0, pExpr, pX->pIdxExpr, pX->iTabCur)==0 ){
|
|
+ preserveExpr(pX, pExpr);
|
|
+ pExpr->affExpr = sqlite3ExprAffinity(pExpr);
|
|
pExpr->op = TK_COLUMN;
|
|
pExpr->iTable = pX->iIdxCur;
|
|
pExpr->iColumn = pX->iIdxCol;
|
|
pExpr->y.pTab = 0;
|
|
+ testcase( ExprHasProperty(pExpr, EP_Skip) );
|
|
+ testcase( ExprHasProperty(pExpr, EP_Unlikely) );
|
|
+ ExprClearProperty(pExpr, EP_Skip|EP_Unlikely);
|
|
return WRC_Prune;
|
|
}else{
|
|
return WRC_Continue;
|
|
}
|
|
}
|
|
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+/* A walker node callback that translates a column reference to a table
|
|
+** into a corresponding column reference of an index.
|
|
+*/
|
|
+static int whereIndexExprTransColumn(Walker *p, Expr *pExpr){
|
|
+ if( pExpr->op==TK_COLUMN ){
|
|
+ IdxExprTrans *pX = p->u.pIdxTrans;
|
|
+ if( pExpr->iTable==pX->iTabCur && pExpr->iColumn==pX->iTabCol ){
|
|
+ assert( pExpr->y.pTab!=0 );
|
|
+ preserveExpr(pX, pExpr);
|
|
+ pExpr->affExpr = sqlite3TableColumnAffinity(pExpr->y.pTab,pExpr->iColumn);
|
|
+ pExpr->iTable = pX->iIdxCur;
|
|
+ pExpr->iColumn = pX->iIdxCol;
|
|
+ pExpr->y.pTab = 0;
|
|
+ }
|
|
+ }
|
|
+ return WRC_Continue;
|
|
+}
|
|
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
|
+
|
|
/*
|
|
** For an indexes on expression X, locate every instance of expression X
|
|
** in pExpr and change that subexpression into a reference to the appropriate
|
|
** column of the index.
|
|
+**
|
|
+** 2019-10-24: Updated to also translate references to a VIRTUAL column in
|
|
+** the table into references to the corresponding (stored) column of the
|
|
+** index.
|
|
*/
|
|
static void whereIndexExprTrans(
|
|
Index *pIdx, /* The Index */
|
|
@@ -137832,20 +141925,48 @@
|
|
){
|
|
int iIdxCol; /* Column number of the index */
|
|
ExprList *aColExpr; /* Expressions that are indexed */
|
|
+ Table *pTab;
|
|
Walker w;
|
|
IdxExprTrans x;
|
|
aColExpr = pIdx->aColExpr;
|
|
- if( aColExpr==0 ) return; /* Not an index on expressions */
|
|
+ if( aColExpr==0 && !pIdx->bHasVCol ){
|
|
+ /* The index does not reference any expressions or virtual columns
|
|
+ ** so no translations are needed. */
|
|
+ return;
|
|
+ }
|
|
+ pTab = pIdx->pTable;
|
|
memset(&w, 0, sizeof(w));
|
|
- w.xExprCallback = whereIndexExprTransNode;
|
|
w.u.pIdxTrans = &x;
|
|
x.iTabCur = iTabCur;
|
|
x.iIdxCur = iIdxCur;
|
|
- for(iIdxCol=0; iIdxCol<aColExpr->nExpr; iIdxCol++){
|
|
- if( pIdx->aiColumn[iIdxCol]!=XN_EXPR ) continue;
|
|
- assert( aColExpr->a[iIdxCol].pExpr!=0 );
|
|
+ x.pWInfo = pWInfo;
|
|
+ x.db = pWInfo->pParse->db;
|
|
+ for(iIdxCol=0; iIdxCol<pIdx->nColumn; iIdxCol++){
|
|
+ i16 iRef = pIdx->aiColumn[iIdxCol];
|
|
+ if( iRef==XN_EXPR ){
|
|
+ assert( aColExpr->a[iIdxCol].pExpr!=0 );
|
|
+ x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
|
|
+ if( sqlite3ExprIsConstant(x.pIdxExpr) ) continue;
|
|
+ w.xExprCallback = whereIndexExprTransNode;
|
|
+#ifndef SQLITE_OMIT_GENERATED_COLUMNS
|
|
+ }else if( iRef>=0
|
|
+ && (pTab->aCol[iRef].colFlags & COLFLAG_VIRTUAL)!=0
|
|
+ && (pTab->aCol[iRef].zColl==0
|
|
+ || sqlite3StrICmp(pTab->aCol[iRef].zColl, sqlite3StrBINARY)==0)
|
|
+ ){
|
|
+ /* Check to see if there are direct references to generated columns
|
|
+ ** that are contained in the index. Pulling the generated column
|
|
+ ** out of the index is an optimization only - the main table is always
|
|
+ ** available if the index cannot be used. To avoid unnecessary
|
|
+ ** complication, omit this optimization if the collating sequence for
|
|
+ ** the column is non-standard */
|
|
+ x.iTabCol = iRef;
|
|
+ w.xExprCallback = whereIndexExprTransColumn;
|
|
+#endif /* SQLITE_OMIT_GENERATED_COLUMNS */
|
|
+ }else{
|
|
+ continue;
|
|
+ }
|
|
x.iIdxCol = iIdxCol;
|
|
- x.pIdxExpr = aColExpr->a[iIdxCol].pExpr;
|
|
sqlite3WalkExpr(&w, pWInfo->pWhere);
|
|
sqlite3WalkExprList(&w, pWInfo->pOrderBy);
|
|
sqlite3WalkExprList(&w, pWInfo->pResultSet);
|
|
@@ -137917,6 +142038,21 @@
|
|
pLevel->notReady = notReady & ~sqlite3WhereGetMask(&pWInfo->sMaskSet, iCur);
|
|
bRev = (pWInfo->revMask>>iLevel)&1;
|
|
VdbeModuleComment((v, "Begin WHERE-loop%d: %s",iLevel,pTabItem->pTab->zName));
|
|
+#if WHERETRACE_ENABLED /* 0x20800 */
|
|
+ if( sqlite3WhereTrace & 0x800 ){
|
|
+ sqlite3DebugPrintf("Coding level %d of %d: notReady=%llx iFrom=%d\n",
|
|
+ iLevel, pWInfo->nLevel, (u64)notReady, pLevel->iFrom);
|
|
+ sqlite3WhereLoopPrint(pLoop, pWC);
|
|
+ }
|
|
+ if( sqlite3WhereTrace & 0x20000 ){
|
|
+ if( iLevel==0 ){
|
|
+ sqlite3DebugPrintf("WHERE clause being coded:\n");
|
|
+ sqlite3TreeViewExpr(0, pWInfo->pWhere, 0);
|
|
+ }
|
|
+ sqlite3DebugPrintf("All WHERE-clause terms before coding:\n");
|
|
+ sqlite3WhereClausePrint(pWC);
|
|
+ }
|
|
+#endif
|
|
|
|
/* Create labels for the "break" and "continue" instructions
|
|
** for the current loop. Jump to addrBrk to break out of a loop.
|
|
@@ -137996,9 +142132,12 @@
|
|
iIn = pLevel->u.in.nIn;
|
|
for(j=nConstraint-1; j>=0; j--){
|
|
pTerm = pLoop->aLTerm[j];
|
|
+ if( (pTerm->eOperator & WO_IN)!=0 ) iIn--;
|
|
if( j<16 && (pLoop->u.vtab.omitMask>>j)&1 ){
|
|
disableTerm(pLevel, pTerm);
|
|
- }else if( (pTerm->eOperator & WO_IN)!=0 ){
|
|
+ }else if( (pTerm->eOperator & WO_IN)!=0
|
|
+ && sqlite3ExprVectorSize(pTerm->pExpr->pLeft)==1
|
|
+ ){
|
|
Expr *pCompare; /* The comparison operator */
|
|
Expr *pRight; /* RHS of the comparison */
|
|
VdbeOp *pOp; /* Opcode to access the value of the IN constraint */
|
|
@@ -138009,8 +142148,8 @@
|
|
** encoding of the value in the register, so it *must* be reloaded. */
|
|
assert( pLevel->u.in.aInLoop!=0 || db->mallocFailed );
|
|
if( !db->mallocFailed ){
|
|
- assert( iIn>0 );
|
|
- pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[--iIn].addrInTop);
|
|
+ assert( iIn>=0 && iIn<pLevel->u.in.nIn );
|
|
+ pOp = sqlite3VdbeGetOp(v, pLevel->u.in.aInLoop[iIn].addrInTop);
|
|
assert( pOp->opcode==OP_Column || pOp->opcode==OP_Rowid );
|
|
assert( pOp->opcode!=OP_Column || pOp->p3==iReg+j+2 );
|
|
assert( pOp->opcode!=OP_Rowid || pOp->p2==iReg+j+2 );
|
|
@@ -138027,13 +142166,16 @@
|
|
pCompare->pRight = pRight = sqlite3Expr(db, TK_REGISTER, 0);
|
|
if( pRight ){
|
|
pRight->iTable = iReg+j+2;
|
|
- sqlite3ExprIfFalse(pParse, pCompare, pLevel->addrCont, 0);
|
|
+ sqlite3ExprIfFalse(
|
|
+ pParse, pCompare, pLevel->addrCont, SQLITE_JUMPIFNULL
|
|
+ );
|
|
}
|
|
pCompare->pLeft = 0;
|
|
sqlite3ExprDelete(db, pCompare);
|
|
}
|
|
}
|
|
}
|
|
+ assert( iIn==0 || db->mallocFailed );
|
|
/* These registers need to be preserved in case there is an IN operator
|
|
** loop. So we could deallocate the registers here (and potentially
|
|
** reuse them later) if (pLoop->wsFlags & WHERE_IN_ABLE)==0. But it seems
|
|
@@ -138241,32 +142383,12 @@
|
|
u8 bSeekPastNull = 0; /* True to seek past initial nulls */
|
|
u8 bStopAtNull = 0; /* Add condition to terminate at NULLs */
|
|
int omitTable; /* True if we use the index only */
|
|
-
|
|
+ int regBignull = 0; /* big-null flag register */
|
|
|
|
pIdx = pLoop->u.btree.pIndex;
|
|
iIdxCur = pLevel->iIdxCur;
|
|
assert( nEq>=pLoop->nSkip );
|
|
|
|
- /* If this loop satisfies a sort order (pOrderBy) request that
|
|
- ** was passed to this function to implement a "SELECT min(x) ..."
|
|
- ** query, then the caller will only allow the loop to run for
|
|
- ** a single iteration. This means that the first row returned
|
|
- ** should not have a NULL value stored in 'x'. If column 'x' is
|
|
- ** the first one after the nEq equality constraints in the index,
|
|
- ** this requires some special handling.
|
|
- */
|
|
- assert( pWInfo->pOrderBy==0
|
|
- || pWInfo->pOrderBy->nExpr==1
|
|
- || (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0 );
|
|
- if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0
|
|
- && pWInfo->nOBSat>0
|
|
- && (pIdx->nKeyCol>nEq)
|
|
- ){
|
|
- assert( pLoop->nSkip==0 );
|
|
- bSeekPastNull = 1;
|
|
- nExtraReg = 1;
|
|
- }
|
|
-
|
|
/* Find any inequality constraint terms for the start and end
|
|
** of the range.
|
|
*/
|
|
@@ -138307,6 +142429,28 @@
|
|
}
|
|
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
|
|
|
|
+ /* If the WHERE_BIGNULL_SORT flag is set, then index column nEq uses
|
|
+ ** a non-default "big-null" sort (either ASC NULLS LAST or DESC NULLS
|
|
+ ** FIRST). In both cases separate ordered scans are made of those
|
|
+ ** index entries for which the column is null and for those for which
|
|
+ ** it is not. For an ASC sort, the non-NULL entries are scanned first.
|
|
+ ** For DESC, NULL entries are scanned first.
|
|
+ */
|
|
+ if( (pLoop->wsFlags & (WHERE_TOP_LIMIT|WHERE_BTM_LIMIT))==0
|
|
+ && (pLoop->wsFlags & WHERE_BIGNULL_SORT)!=0
|
|
+ ){
|
|
+ assert( bSeekPastNull==0 && nExtraReg==0 && nBtm==0 && nTop==0 );
|
|
+ assert( pRangeEnd==0 && pRangeStart==0 );
|
|
+ testcase( pLoop->nSkip>0 );
|
|
+ nExtraReg = 1;
|
|
+ bSeekPastNull = 1;
|
|
+ pLevel->regBignull = regBignull = ++pParse->nMem;
|
|
+ if( pLevel->iLeftJoin ){
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer, 0, regBignull);
|
|
+ }
|
|
+ pLevel->addrBignull = sqlite3VdbeMakeLabel(pParse);
|
|
+ }
|
|
+
|
|
/* If we are doing a reverse order scan on an ascending index, or
|
|
** a forward order scan on a descending index, interchange the
|
|
** start and end terms (pRangeStart and pRangeEnd).
|
|
@@ -138329,7 +142473,7 @@
|
|
if( zStartAff && nTop ){
|
|
zEndAff = sqlite3DbStrDup(db, &zStartAff[nEq]);
|
|
}
|
|
- addrNxt = pLevel->addrNxt;
|
|
+ addrNxt = (regBignull ? pLevel->addrBignull : pLevel->addrNxt);
|
|
|
|
testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 );
|
|
testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 );
|
|
@@ -138363,10 +142507,14 @@
|
|
}
|
|
bSeekPastNull = 0;
|
|
}else if( bSeekPastNull ){
|
|
+ startEq = 0;
|
|
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
|
+ start_constraints = 1;
|
|
nConstraint++;
|
|
- startEq = 0;
|
|
+ }else if( regBignull ){
|
|
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
|
start_constraints = 1;
|
|
+ nConstraint++;
|
|
}
|
|
codeApplyAffinity(pParse, regBase, nConstraint - bSeekPastNull, zStartAff);
|
|
if( pLoop->nSkip>0 && nConstraint==pLoop->nSkip ){
|
|
@@ -138377,6 +142525,11 @@
|
|
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
|
|
sqlite3VdbeAddOp1(v, OP_SeekHit, iIdxCur);
|
|
}
|
|
+ if( regBignull ){
|
|
+ sqlite3VdbeAddOp2(v, OP_Integer, 1, regBignull);
|
|
+ VdbeComment((v, "NULL-scan pass ctr"));
|
|
+ }
|
|
+
|
|
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
|
assert( op!=0 );
|
|
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
|
@@ -138387,6 +142540,23 @@
|
|
VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
|
|
VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
|
|
VdbeCoverageIf(v, op==OP_SeekLT); testcase( op==OP_SeekLT );
|
|
+
|
|
+ assert( bSeekPastNull==0 || bStopAtNull==0 );
|
|
+ if( regBignull ){
|
|
+ assert( bSeekPastNull==1 || bStopAtNull==1 );
|
|
+ assert( bSeekPastNull==!bStopAtNull );
|
|
+ assert( bStopAtNull==startEq );
|
|
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+2);
|
|
+ op = aStartOp[(nConstraint>1)*4 + 2 + bRev];
|
|
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
|
|
+ nConstraint-startEq);
|
|
+ VdbeCoverage(v);
|
|
+ VdbeCoverageIf(v, op==OP_Rewind); testcase( op==OP_Rewind );
|
|
+ VdbeCoverageIf(v, op==OP_Last); testcase( op==OP_Last );
|
|
+ VdbeCoverageIf(v, op==OP_SeekGE); testcase( op==OP_SeekGE );
|
|
+ VdbeCoverageIf(v, op==OP_SeekLE); testcase( op==OP_SeekLE );
|
|
+ assert( op==OP_Rewind || op==OP_Last || op==OP_SeekGE || op==OP_SeekLE);
|
|
+ }
|
|
}
|
|
|
|
/* Load the value for the inequality constraint at the end of the
|
|
@@ -138418,8 +142588,10 @@
|
|
endEq = 1;
|
|
}
|
|
}else if( bStopAtNull ){
|
|
- sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
|
- endEq = 0;
|
|
+ if( regBignull==0 ){
|
|
+ sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
|
+ endEq = 0;
|
|
+ }
|
|
nConstraint++;
|
|
}
|
|
sqlite3DbFree(db, zStartAff);
|
|
@@ -138430,6 +142602,12 @@
|
|
|
|
/* Check if the index cursor is past the end of the range. */
|
|
if( nConstraint ){
|
|
+ if( regBignull ){
|
|
+ /* Except, skip the end-of-range check while doing the NULL-scan */
|
|
+ sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3);
|
|
+ VdbeComment((v, "If NULL-scan 2nd pass"));
|
|
+ VdbeCoverage(v);
|
|
+ }
|
|
op = aEndOp[bRev*2 + endEq];
|
|
sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint);
|
|
testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
|
|
@@ -138437,6 +142615,23 @@
|
|
testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
|
|
testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
|
|
}
|
|
+ if( regBignull ){
|
|
+ /* During a NULL-scan, check to see if we have reached the end of
|
|
+ ** the NULLs */
|
|
+ assert( bSeekPastNull==!bStopAtNull );
|
|
+ assert( bSeekPastNull+bStopAtNull==1 );
|
|
+ assert( nConstraint+bSeekPastNull>0 );
|
|
+ sqlite3VdbeAddOp2(v, OP_If, regBignull, sqlite3VdbeCurrentAddr(v)+2);
|
|
+ VdbeComment((v, "If NULL-scan 1st pass"));
|
|
+ VdbeCoverage(v);
|
|
+ op = aEndOp[bRev*2 + bSeekPastNull];
|
|
+ sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase,
|
|
+ nConstraint+bSeekPastNull);
|
|
+ testcase( op==OP_IdxGT ); VdbeCoverageIf(v, op==OP_IdxGT );
|
|
+ testcase( op==OP_IdxGE ); VdbeCoverageIf(v, op==OP_IdxGE );
|
|
+ testcase( op==OP_IdxLT ); VdbeCoverageIf(v, op==OP_IdxLT );
|
|
+ testcase( op==OP_IdxLE ); VdbeCoverageIf(v, op==OP_IdxLE );
|
|
+ }
|
|
|
|
if( pLoop->wsFlags & WHERE_IN_EARLYOUT ){
|
|
sqlite3VdbeAddOp2(v, OP_SeekHit, iIdxCur, 1);
|
|
@@ -138448,10 +142643,10 @@
|
|
if( omitTable ){
|
|
/* pIdx is a covering index. No need to access the main table. */
|
|
}else if( HasRowid(pIdx->pTable) ){
|
|
- if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE) || (
|
|
- (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)
|
|
- && (pWInfo->eOnePass==ONEPASS_SINGLE)
|
|
- )){
|
|
+ if( (pWInfo->wctrlFlags & WHERE_SEEK_TABLE)
|
|
+ || ( (pWInfo->wctrlFlags & WHERE_SEEK_UNIQ_TABLE)!=0
|
|
+ && (pWInfo->eOnePass==ONEPASS_SINGLE || pLoop->nLTerm==0) )
|
|
+ ){
|
|
iRowidReg = ++pParse->nMem;
|
|
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
|
|
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, 0, iRowidReg);
|
|
@@ -138463,40 +142658,53 @@
|
|
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
|
|
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
|
|
for(j=0; j<pPk->nKeyCol; j++){
|
|
- k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[j]);
|
|
+ k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
|
|
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, iRowidReg+j);
|
|
}
|
|
sqlite3VdbeAddOp4Int(v, OP_NotFound, iCur, addrCont,
|
|
iRowidReg, pPk->nKeyCol); VdbeCoverage(v);
|
|
}
|
|
|
|
- /* If pIdx is an index on one or more expressions, then look through
|
|
- ** all the expressions in pWInfo and try to transform matching expressions
|
|
- ** into reference to index columns.
|
|
- **
|
|
- ** Do not do this for the RHS of a LEFT JOIN. This is because the
|
|
- ** expression may be evaluated after OP_NullRow has been executed on
|
|
- ** the cursor. In this case it is important to do the full evaluation,
|
|
- ** as the result of the expression may not be NULL, even if all table
|
|
- ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
|
|
- **
|
|
- ** Also, do not do this when processing one index an a multi-index
|
|
- ** OR clause, since the transformation will become invalid once we
|
|
- ** move forward to the next index.
|
|
- ** https://sqlite.org/src/info/4e8e4857d32d401f
|
|
- */
|
|
- if( pLevel->iLeftJoin==0 && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
|
|
- whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
|
|
- }
|
|
-
|
|
- /* If a partial index is driving the loop, try to eliminate WHERE clause
|
|
- ** terms from the query that must be true due to the WHERE clause of
|
|
- ** the partial index
|
|
- */
|
|
- if( pIdx->pPartIdxWhere ){
|
|
- whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
|
|
+ if( pLevel->iLeftJoin==0 ){
|
|
+ /* If pIdx is an index on one or more expressions, then look through
|
|
+ ** all the expressions in pWInfo and try to transform matching expressions
|
|
+ ** into reference to index columns. Also attempt to translate references
|
|
+ ** to virtual columns in the table into references to (stored) columns
|
|
+ ** of the index.
|
|
+ **
|
|
+ ** Do not do this for the RHS of a LEFT JOIN. This is because the
|
|
+ ** expression may be evaluated after OP_NullRow has been executed on
|
|
+ ** the cursor. In this case it is important to do the full evaluation,
|
|
+ ** as the result of the expression may not be NULL, even if all table
|
|
+ ** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
|
|
+ **
|
|
+ ** Also, do not do this when processing one index an a multi-index
|
|
+ ** OR clause, since the transformation will become invalid once we
|
|
+ ** move forward to the next index.
|
|
+ ** https://sqlite.org/src/info/4e8e4857d32d401f
|
|
+ */
|
|
+ if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 ){
|
|
+ whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
|
|
+ }
|
|
+
|
|
+ /* If a partial index is driving the loop, try to eliminate WHERE clause
|
|
+ ** terms from the query that must be true due to the WHERE clause of
|
|
+ ** the partial index.
|
|
+ **
|
|
+ ** 2019-11-02 ticket 623eff57e76d45f6: This optimization does not work
|
|
+ ** for a LEFT JOIN.
|
|
+ */
|
|
+ if( pIdx->pPartIdxWhere ){
|
|
+ whereApplyPartialIndexConstraints(pIdx->pPartIdxWhere, iCur, pWC);
|
|
+ }
|
|
+ }else{
|
|
+ testcase( pIdx->pPartIdxWhere );
|
|
+ /* The following assert() is not a requirement, merely an observation:
|
|
+ ** The OR-optimization doesn't work for the right hand table of
|
|
+ ** a LEFT JOIN: */
|
|
+ assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0 );
|
|
}
|
|
-
|
|
+
|
|
/* Record the instruction used to terminate the loop. */
|
|
if( pLoop->wsFlags & WHERE_ONEROW ){
|
|
pLevel->op = OP_Noop;
|
|
@@ -138681,9 +142889,9 @@
|
|
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
|
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
|
|
int jmp1 = 0; /* Address of jump operation */
|
|
- assert( (pTabItem[0].fg.jointype & JT_LEFT)==0
|
|
- || ExprHasProperty(pOrExpr, EP_FromJoin)
|
|
- );
|
|
+ testcase( (pTabItem[0].fg.jointype & JT_LEFT)!=0
|
|
+ && !ExprHasProperty(pOrExpr, EP_FromJoin)
|
|
+ ); /* See TH3 vtab25.400 and ticket 614b25314c766238 */
|
|
if( pAndExpr ){
|
|
pAndExpr->pLeft = pOrExpr;
|
|
pOrExpr = pAndExpr;
|
|
@@ -138723,7 +142931,7 @@
|
|
r = sqlite3GetTempRange(pParse, nPk);
|
|
for(iPk=0; iPk<nPk; iPk++){
|
|
int iCol = pPk->aiColumn[iPk];
|
|
- sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol, r+iPk);
|
|
+ sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+iPk);
|
|
}
|
|
|
|
/* Check if the temp table already contains this key. If so,
|
|
@@ -138905,6 +143113,10 @@
|
|
VdbeNoopComment((v, "WhereTerm[%d] (%p) priority=%d",
|
|
pWC->nTerm-j, pTerm, iLoop));
|
|
}
|
|
+ if( sqlite3WhereTrace & 0x800 ){
|
|
+ sqlite3DebugPrintf("Coding auxiliary constraint:\n");
|
|
+ sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
|
|
+ }
|
|
#endif
|
|
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
|
|
if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
|
|
@@ -138928,8 +143140,14 @@
|
|
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
|
|
if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
|
|
if( pTerm->leftCursor!=iCur ) continue;
|
|
- if( pLevel->iLeftJoin ) continue;
|
|
+ if( pTabItem->fg.jointype & JT_LEFT ) continue;
|
|
pE = pTerm->pExpr;
|
|
+#ifdef WHERETRACE_ENABLED /* 0x800 */
|
|
+ if( sqlite3WhereTrace & 0x800 ){
|
|
+ sqlite3DebugPrintf("Coding transitive constraint:\n");
|
|
+ sqlite3WhereTermPrint(pTerm, pWC->nTerm-j);
|
|
+ }
|
|
+#endif
|
|
assert( !ExprHasProperty(pE, EP_FromJoin) );
|
|
assert( (pTerm->prereqRight & pLevel->notReady)!=0 );
|
|
pAlt = sqlite3WhereFindTerm(pWC, iCur, pTerm->u.leftColumn, notReady,
|
|
@@ -138972,6 +143190,17 @@
|
|
}
|
|
}
|
|
|
|
+#if WHERETRACE_ENABLED /* 0x20800 */
|
|
+ if( sqlite3WhereTrace & 0x20000 ){
|
|
+ sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n",
|
|
+ iLevel);
|
|
+ sqlite3WhereClausePrint(pWC);
|
|
+ }
|
|
+ if( sqlite3WhereTrace & 0x800 ){
|
|
+ sqlite3DebugPrintf("End Coding level %d: notReady=%llx\n",
|
|
+ iLevel, (u64)pLevel->notReady);
|
|
+ }
|
|
+#endif
|
|
return pLevel->notReady;
|
|
}
|
|
|
|
@@ -139063,7 +143292,7 @@
|
|
}else{
|
|
pTerm->truthProb = 1;
|
|
}
|
|
- pTerm->pExpr = sqlite3ExprSkipCollate(p);
|
|
+ pTerm->pExpr = sqlite3ExprSkipCollateAndLikely(p);
|
|
pTerm->wtFlags = wtFlags;
|
|
pTerm->pWC = pWC;
|
|
pTerm->iParent = -1;
|
|
@@ -139088,31 +143317,14 @@
|
|
/*
|
|
** Commute a comparison operator. Expressions of the form "X op Y"
|
|
** are converted into "Y op X".
|
|
-**
|
|
-** If left/right precedence rules come into play when determining the
|
|
-** collating sequence, then COLLATE operators are adjusted to ensure
|
|
-** that the collating sequence does not change. For example:
|
|
-** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on
|
|
-** the left hand side of a comparison overrides any collation sequence
|
|
-** attached to the right. For the same reason the EP_Collate flag
|
|
-** is not commuted.
|
|
-*/
|
|
-static void exprCommute(Parse *pParse, Expr *pExpr){
|
|
- u16 expRight = (pExpr->pRight->flags & EP_Collate);
|
|
- u16 expLeft = (pExpr->pLeft->flags & EP_Collate);
|
|
- assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN );
|
|
- if( expRight==expLeft ){
|
|
- /* Either X and Y both have COLLATE operator or neither do */
|
|
- if( expRight ){
|
|
- /* Both X and Y have COLLATE operators. Make sure X is always
|
|
- ** used by clearing the EP_Collate flag from Y. */
|
|
- pExpr->pRight->flags &= ~EP_Collate;
|
|
- }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){
|
|
- /* Neither X nor Y have COLLATE operators, but X has a non-default
|
|
- ** collating sequence. So add the EP_Collate marker on X to cause
|
|
- ** it to be searched first. */
|
|
- pExpr->pLeft->flags |= EP_Collate;
|
|
- }
|
|
+*/
|
|
+static u16 exprCommute(Parse *pParse, Expr *pExpr){
|
|
+ if( pExpr->pLeft->op==TK_VECTOR
|
|
+ || pExpr->pRight->op==TK_VECTOR
|
|
+ || sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight) !=
|
|
+ sqlite3BinaryCompareCollSeq(pParse, pExpr->pRight, pExpr->pLeft)
|
|
+ ){
|
|
+ pExpr->flags ^= EP_Commuted;
|
|
}
|
|
SWAP(Expr*,pExpr->pRight,pExpr->pLeft);
|
|
if( pExpr->op>=TK_GT ){
|
|
@@ -139123,6 +143335,7 @@
|
|
assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE );
|
|
pExpr->op = ((pExpr->op-TK_GT)^2)+TK_GT;
|
|
}
|
|
+ return 0;
|
|
}
|
|
|
|
/*
|
|
@@ -139254,6 +143467,7 @@
|
|
** 2019-05-02 https://sqlite.org/src/info/b043a54c3de54b28
|
|
** 2019-06-10 https://sqlite.org/src/info/fd76310a5e843e07
|
|
** 2019-06-14 https://sqlite.org/src/info/ce8717f0885af975
|
|
+ ** 2019-09-03 https://sqlite.org/src/info/0f0428096f17252a
|
|
*/
|
|
if( pLeft->op!=TK_COLUMN
|
|
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
|
|
@@ -139263,9 +143477,13 @@
|
|
double rDummy;
|
|
isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
|
|
if( isNum<=0 ){
|
|
- zNew[iTo-1]++;
|
|
- isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
|
|
- zNew[iTo-1]--;
|
|
+ if( iTo==1 && zNew[0]=='-' ){
|
|
+ isNum = +1;
|
|
+ }else{
|
|
+ zNew[iTo-1]++;
|
|
+ isNum = sqlite3AtoF(zNew, &rDummy, iTo, SQLITE_UTF8);
|
|
+ zNew[iTo-1]--;
|
|
+ }
|
|
}
|
|
if( isNum>0 ){
|
|
sqlite3ExprDelete(db, pPrefix);
|
|
@@ -139367,7 +143585,8 @@
|
|
** MATCH(expression,vtab_column)
|
|
*/
|
|
pCol = pList->a[1].pExpr;
|
|
- if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
|
|
+ testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
|
|
+ if( ExprIsVtab(pCol) ){
|
|
for(i=0; i<ArraySize(aOp); i++){
|
|
if( sqlite3StrICmp(pExpr->u.zToken, aOp[i].zOp)==0 ){
|
|
*peOp2 = aOp[i].eOp2;
|
|
@@ -139389,7 +143608,8 @@
|
|
** with function names in an arbitrary case.
|
|
*/
|
|
pCol = pList->a[0].pExpr;
|
|
- if( pCol->op==TK_COLUMN && IsVirtual(pCol->y.pTab) ){
|
|
+ testcase( pCol->op==TK_COLUMN && pCol->y.pTab==0 );
|
|
+ if( ExprIsVtab(pCol) ){
|
|
sqlite3_vtab *pVtab;
|
|
sqlite3_module *pMod;
|
|
void (*xNotUsed)(sqlite3_context*,int,sqlite3_value**);
|
|
@@ -139412,10 +143632,12 @@
|
|
int res = 0;
|
|
Expr *pLeft = pExpr->pLeft;
|
|
Expr *pRight = pExpr->pRight;
|
|
- if( pLeft->op==TK_COLUMN && IsVirtual(pLeft->y.pTab) ){
|
|
+ testcase( pLeft->op==TK_COLUMN && pLeft->y.pTab==0 );
|
|
+ if( ExprIsVtab(pLeft) ){
|
|
res++;
|
|
}
|
|
- if( pRight && pRight->op==TK_COLUMN && IsVirtual(pRight->y.pTab) ){
|
|
+ testcase( pRight && pRight->op==TK_COLUMN && pRight->y.pTab==0 );
|
|
+ if( pRight && ExprIsVtab(pRight) ){
|
|
res++;
|
|
SWAP(Expr*, pLeft, pRight);
|
|
}
|
|
@@ -139895,7 +144117,7 @@
|
|
){
|
|
return 0;
|
|
}
|
|
- pColl = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft, pExpr->pRight);
|
|
+ pColl = sqlite3ExprCompareCollSeq(pParse, pExpr);
|
|
if( sqlite3IsBinary(pColl) ) return 1;
|
|
return sqlite3ExprCollSeqMatch(pParse, pExpr->pLeft, pExpr->pRight);
|
|
}
|
|
@@ -140119,7 +144341,7 @@
|
|
pDup = pExpr;
|
|
pNew = pTerm;
|
|
}
|
|
- exprCommute(pParse, pDup);
|
|
+ pNew->wtFlags |= exprCommute(pParse, pDup);
|
|
pNew->leftCursor = aiCurCol[0];
|
|
pNew->u.leftColumn = aiCurCol[1];
|
|
testcase( (prereqLeft | extraRight) != prereqLeft );
|
|
@@ -140288,6 +144510,7 @@
|
|
0, sqlite3ExprDup(db, pRight, 0));
|
|
if( ExprHasProperty(pExpr, EP_FromJoin) && pNewExpr ){
|
|
ExprSetProperty(pNewExpr, EP_FromJoin);
|
|
+ pNewExpr->iRightJoinTable = pExpr->iRightJoinTable;
|
|
}
|
|
idxNew = whereClauseInsert(pWC, pNewExpr, TERM_VIRTUAL|TERM_DYNAMIC);
|
|
testcase( idxNew==0 );
|
|
@@ -140344,11 +144567,15 @@
|
|
** expression). The WhereTerm.iField variable identifies the index within
|
|
** the vector on the LHS that the virtual term represents.
|
|
**
|
|
- ** This only works if the RHS is a simple SELECT, not a compound
|
|
+ ** This only works if the RHS is a simple SELECT (not a compound) that does
|
|
+ ** not use window functions.
|
|
*/
|
|
if( pWC->op==TK_AND && pExpr->op==TK_IN && pTerm->iField==0
|
|
&& pExpr->pLeft->op==TK_VECTOR
|
|
&& pExpr->x.pSelect->pPrior==0
|
|
+#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
+ && pExpr->x.pSelect->pWin==0
|
|
+#endif
|
|
){
|
|
int i;
|
|
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
|
|
@@ -140360,8 +144587,8 @@
|
|
}
|
|
}
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
- /* When sqlite_stat3 histogram data is available an operator of the
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ /* When sqlite_stat4 histogram data is available an operator of the
|
|
** form "x IS NOT NULL" can sometimes be evaluated more efficiently
|
|
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
|
|
** virtual term of that form.
|
|
@@ -140372,7 +144599,7 @@
|
|
&& pExpr->pLeft->op==TK_COLUMN
|
|
&& pExpr->pLeft->iColumn>=0
|
|
&& !ExprHasProperty(pExpr, EP_FromJoin)
|
|
- && OptimizationEnabled(db, SQLITE_Stat34)
|
|
+ && OptimizationEnabled(db, SQLITE_Stat4)
|
|
){
|
|
Expr *pNewExpr;
|
|
Expr *pLeft = pExpr->pLeft;
|
|
@@ -140397,7 +144624,7 @@
|
|
pNewTerm->prereqAll = pTerm->prereqAll;
|
|
}
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
/* Prevent ON clause terms of a LEFT JOIN from being used to drive
|
|
** an index for tables to the left of the join.
|
|
@@ -140430,7 +144657,7 @@
|
|
** all terms of the WHERE clause.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3WhereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
|
|
- Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
|
|
+ Expr *pE2 = sqlite3ExprSkipCollateAndLikely(pExpr);
|
|
pWC->op = op;
|
|
if( pE2==0 ) return;
|
|
if( pE2->op!=op ){
|
|
@@ -140506,9 +144733,10 @@
|
|
mask |= sqlite3WhereExprListUsage(pMaskSet, p->x.pList);
|
|
}
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
- if( p->op==TK_FUNCTION && p->y.pWin ){
|
|
+ if( (p->op==TK_FUNCTION || p->op==TK_AGG_FUNCTION) && p->y.pWin ){
|
|
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pPartition);
|
|
mask |= sqlite3WhereExprListUsage(pMaskSet, p->y.pWin->pOrderBy);
|
|
+ mask |= sqlite3WhereExprUsage(pMaskSet, p->y.pWin->pFilter);
|
|
}
|
|
#endif
|
|
return mask;
|
|
@@ -140584,6 +144812,9 @@
|
|
pRhs = sqlite3PExpr(pParse, TK_UPLUS,
|
|
sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
|
|
pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
|
|
+ if( pItem->fg.jointype & JT_LEFT ){
|
|
+ sqlite3SetJoinExpr(pTerm, pItem->iCursor);
|
|
+ }
|
|
whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
|
|
}
|
|
}
|
|
@@ -140712,7 +144943,7 @@
|
|
|
|
/*
|
|
** Return ONEPASS_OFF (0) if an UPDATE or DELETE statement is unable to
|
|
-** operate directly on the rowis returned by a WHERE clause. Return
|
|
+** operate directly on the rowids returned by a WHERE clause. Return
|
|
** ONEPASS_SINGLE (1) if the statement can operation directly because only
|
|
** a single row is to be changed. Return ONEPASS_MULTI (2) if the one-pass
|
|
** optimization can be used on multiple
|
|
@@ -140739,6 +144970,14 @@
|
|
return pWInfo->eOnePass;
|
|
}
|
|
|
|
+/*
|
|
+** Return TRUE if the WHERE loop uses the OP_DeferredSeek opcode to move
|
|
+** the data cursor to the row selected by the index cursor.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3WhereUsesDeferredSeek(WhereInfo *pWInfo){
|
|
+ return pWInfo->bDeferredSeek;
|
|
+}
|
|
+
|
|
/*
|
|
** Move the content of pSrc into pDest
|
|
*/
|
|
@@ -140845,7 +145084,8 @@
|
|
){
|
|
if( (pTerm->eOperator & WO_EQUIV)!=0
|
|
&& pScan->nEquiv<ArraySize(pScan->aiCur)
|
|
- && (pX = sqlite3ExprSkipCollate(pTerm->pExpr->pRight))->op==TK_COLUMN
|
|
+ && (pX = sqlite3ExprSkipCollateAndLikely(pTerm->pExpr->pRight))->op
|
|
+ ==TK_COLUMN
|
|
){
|
|
int j;
|
|
for(j=0; j<pScan->nEquiv; j++){
|
|
@@ -140870,8 +145110,7 @@
|
|
continue;
|
|
}
|
|
assert(pX->pLeft);
|
|
- pColl = sqlite3BinaryCompareCollSeq(pParse,
|
|
- pX->pLeft, pX->pRight);
|
|
+ pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
|
if( pColl==0 ) pColl = pParse->db->pDfltColl;
|
|
if( sqlite3StrICmp(pColl->zName, pScan->zCollName) ){
|
|
continue;
|
|
@@ -141041,7 +145280,7 @@
|
|
const char *zColl = pIdx->azColl[iCol];
|
|
|
|
for(i=0; i<pList->nExpr; i++){
|
|
- Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr);
|
|
+ Expr *p = sqlite3ExprSkipCollateAndLikely(pList->a[i].pExpr);
|
|
if( p->op==TK_COLUMN
|
|
&& p->iColumn==pIdx->aiColumn[iCol]
|
|
&& p->iTable==iBase
|
|
@@ -141105,7 +145344,7 @@
|
|
** current SELECT is a correlated sub-query.
|
|
*/
|
|
for(i=0; i<pDistinct->nExpr; i++){
|
|
- Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr);
|
|
+ Expr *p = sqlite3ExprSkipCollateAndLikely(pDistinct->a[i].pExpr);
|
|
if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1;
|
|
}
|
|
|
|
@@ -141197,7 +145436,7 @@
|
|
** are no-ops.
|
|
*/
|
|
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED)
|
|
-static void TRACE_IDX_INPUTS(sqlite3_index_info *p){
|
|
+static void whereTraceIndexInfoInputs(sqlite3_index_info *p){
|
|
int i;
|
|
if( !sqlite3WhereTrace ) return;
|
|
for(i=0; i<p->nConstraint; i++){
|
|
@@ -141215,7 +145454,7 @@
|
|
p->aOrderBy[i].desc);
|
|
}
|
|
}
|
|
-static void TRACE_IDX_OUTPUTS(sqlite3_index_info *p){
|
|
+static void whereTraceIndexInfoOutputs(sqlite3_index_info *p){
|
|
int i;
|
|
if( !sqlite3WhereTrace ) return;
|
|
for(i=0; i<p->nConstraint; i++){
|
|
@@ -141231,8 +145470,8 @@
|
|
sqlite3DebugPrintf(" estimatedRows=%lld\n", p->estimatedRows);
|
|
}
|
|
#else
|
|
-#define TRACE_IDX_INPUTS(A)
|
|
-#define TRACE_IDX_OUTPUTS(A)
|
|
+#define whereTraceIndexInfoInputs(A)
|
|
+#define whereTraceIndexInfoOutputs(A)
|
|
#endif
|
|
|
|
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
|
|
@@ -141392,7 +145631,8 @@
|
|
Expr *pX = pTerm->pExpr;
|
|
idxCols |= cMask;
|
|
pIdx->aiColumn[n] = pTerm->u.leftColumn;
|
|
- pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
|
|
+ pColl = sqlite3ExprCompareCollSeq(pParse, pX);
|
|
+ assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */
|
|
pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY;
|
|
n++;
|
|
}
|
|
@@ -141461,8 +145701,8 @@
|
|
pTabItem->fg.viaCoroutine = 0;
|
|
}else{
|
|
sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v);
|
|
+ sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
|
|
}
|
|
- sqlite3VdbeChangeP5(v, SQLITE_STMTSTATUS_AUTOINDEX);
|
|
sqlite3VdbeJumpHere(v, addrTop);
|
|
sqlite3ReleaseTempReg(pParse, regRecord);
|
|
|
|
@@ -141525,6 +145765,7 @@
|
|
for(i=0; i<n; i++){
|
|
Expr *pExpr = pOrderBy->a[i].pExpr;
|
|
if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break;
|
|
+ if( pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL ) break;
|
|
}
|
|
if( i==n){
|
|
nOrderBy = n;
|
|
@@ -141540,23 +145781,14 @@
|
|
sqlite3ErrorMsg(pParse, "out of memory");
|
|
return 0;
|
|
}
|
|
-
|
|
- /* Initialize the structure. The sqlite3_index_info structure contains
|
|
- ** many fields that are declared "const" to prevent xBestIndex from
|
|
- ** changing them. We have to do some funky casting in order to
|
|
- ** initialize those fields.
|
|
- */
|
|
pHidden = (struct HiddenIndexInfo*)&pIdxInfo[1];
|
|
pIdxCons = (struct sqlite3_index_constraint*)&pHidden[1];
|
|
pIdxOrderBy = (struct sqlite3_index_orderby*)&pIdxCons[nTerm];
|
|
pUsage = (struct sqlite3_index_constraint_usage*)&pIdxOrderBy[nOrderBy];
|
|
- *(int*)&pIdxInfo->nConstraint = nTerm;
|
|
- *(int*)&pIdxInfo->nOrderBy = nOrderBy;
|
|
- *(struct sqlite3_index_constraint**)&pIdxInfo->aConstraint = pIdxCons;
|
|
- *(struct sqlite3_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy;
|
|
- *(struct sqlite3_index_constraint_usage**)&pIdxInfo->aConstraintUsage =
|
|
- pUsage;
|
|
-
|
|
+ pIdxInfo->nOrderBy = nOrderBy;
|
|
+ pIdxInfo->aConstraint = pIdxCons;
|
|
+ pIdxInfo->aOrderBy = pIdxOrderBy;
|
|
+ pIdxInfo->aConstraintUsage = pUsage;
|
|
pHidden->pWC = pWC;
|
|
pHidden->pParse = pParse;
|
|
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
|
@@ -141570,18 +145802,13 @@
|
|
testcase( pTerm->eOperator & WO_ALL );
|
|
if( (pTerm->eOperator & ~(WO_EQUIV))==0 ) continue;
|
|
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
|
+
|
|
+ /* tag-20191211-002: WHERE-clause constraints are not useful to the
|
|
+ ** right-hand table of a LEFT JOIN. See tag-20191211-001 for the
|
|
+ ** equivalent restriction for ordinary tables. */
|
|
if( (pSrc->fg.jointype & JT_LEFT)!=0
|
|
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
|
|
- && (pTerm->eOperator & (WO_IS|WO_ISNULL))
|
|
){
|
|
- /* An "IS" term in the WHERE clause where the virtual table is the rhs
|
|
- ** of a LEFT JOIN. Do not pass this term to the virtual table
|
|
- ** implementation, as this can lead to incorrect results from SQL such
|
|
- ** as:
|
|
- **
|
|
- ** "LEFT JOIN vtab WHERE vtab.col IS NULL" */
|
|
- testcase( pTerm->eOperator & WO_ISNULL );
|
|
- testcase( pTerm->eOperator & WO_IS );
|
|
continue;
|
|
}
|
|
assert( pTerm->u.leftColumn>=(-1) );
|
|
@@ -141612,7 +145839,8 @@
|
|
if( op & (WO_LT|WO_LE|WO_GT|WO_GE)
|
|
&& sqlite3ExprIsVector(pTerm->pExpr->pRight)
|
|
){
|
|
- if( i<16 ) mNoOmit |= (1 << i);
|
|
+ testcase( j!=i );
|
|
+ if( j<16 ) mNoOmit |= (1 << j);
|
|
if( op==WO_LT ) pIdxCons[j].op = WO_LE;
|
|
if( op==WO_GT ) pIdxCons[j].op = WO_GE;
|
|
}
|
|
@@ -141620,10 +145848,11 @@
|
|
|
|
j++;
|
|
}
|
|
+ pIdxInfo->nConstraint = j;
|
|
for(i=0; i<nOrderBy; i++){
|
|
Expr *pExpr = pOrderBy->a[i].pExpr;
|
|
pIdxOrderBy[i].iColumn = pExpr->iColumn;
|
|
- pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder;
|
|
+ pIdxOrderBy[i].desc = pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC;
|
|
}
|
|
|
|
*pmNoOmit = mNoOmit;
|
|
@@ -141650,9 +145879,9 @@
|
|
sqlite3_vtab *pVtab = sqlite3GetVTable(pParse->db, pTab)->pVtab;
|
|
int rc;
|
|
|
|
- TRACE_IDX_INPUTS(p);
|
|
+ whereTraceIndexInfoInputs(p);
|
|
rc = pVtab->pModule->xBestIndex(pVtab, p);
|
|
- TRACE_IDX_OUTPUTS(p);
|
|
+ whereTraceIndexInfoOutputs(p);
|
|
|
|
if( rc!=SQLITE_OK && rc!=SQLITE_CONSTRAINT ){
|
|
if( rc==SQLITE_NOMEM ){
|
|
@@ -141669,7 +145898,7 @@
|
|
}
|
|
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Estimate the location of a particular key among all keys in an
|
|
** index. Store the results in aStat as follows:
|
|
@@ -141862,7 +146091,7 @@
|
|
pRec->nField = nField;
|
|
return i;
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
/*
|
|
** If it is not NULL, pTerm is a term that provides an upper or lower
|
|
@@ -141888,7 +146117,7 @@
|
|
}
|
|
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Return the affinity for a single column of an index.
|
|
*/
|
|
@@ -141897,12 +146126,13 @@
|
|
if( !pIdx->zColAff ){
|
|
if( sqlite3IndexAffinityStr(db, pIdx)==0 ) return SQLITE_AFF_BLOB;
|
|
}
|
|
+ assert( pIdx->zColAff[iCol]!=0 );
|
|
return pIdx->zColAff[iCol];
|
|
}
|
|
#endif
|
|
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** This function is called to estimate the number of rows visited by a
|
|
** range-scan on a skip-scan index. For example:
|
|
@@ -142008,7 +146238,7 @@
|
|
|
|
return rc;
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
/*
|
|
** This function is used to estimate the number of rows that will be visited
|
|
@@ -142061,12 +146291,12 @@
|
|
int nOut = pLoop->nOut;
|
|
LogEst nNew;
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
Index *p = pLoop->u.btree.pIndex;
|
|
int nEq = pLoop->u.btree.nEq;
|
|
|
|
- if( p->nSample>0 && nEq<p->nSampleCol
|
|
- && OptimizationEnabled(pParse->db, SQLITE_Stat34)
|
|
+ if( p->nSample>0 && ALWAYS(nEq<p->nSampleCol)
|
|
+ && OptimizationEnabled(pParse->db, SQLITE_Stat4)
|
|
){
|
|
if( nEq==pBuilder->nRecValid ){
|
|
UnpackedRecord *pRec = pBuilder->pRec;
|
|
@@ -142164,7 +146394,7 @@
|
|
/* TUNING: If both iUpper and iLower are derived from the same
|
|
** sample, then assume they are 4x more selective. This brings
|
|
** the estimated selectivity more in line with what it would be
|
|
- ** if estimated without the use of STAT3/4 tables. */
|
|
+ ** if estimated without the use of STAT4 tables. */
|
|
if( iLwrIdx==iUprIdx ) nNew -= 20; assert( 20==sqlite3LogEst(4) );
|
|
}else{
|
|
nNew = 10; assert( 10==sqlite3LogEst(2) );
|
|
@@ -142213,12 +146443,12 @@
|
|
return rc;
|
|
}
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Estimate the number of rows that will be returned based on
|
|
** an equality constraint x=VALUE and where that VALUE occurs in
|
|
** the histogram data. This only works when x is the left-most
|
|
-** column of an index and sqlite_stat3 histogram data is available
|
|
+** column of an index and sqlite_stat4 histogram data is available
|
|
** for that index. When pExpr==NULL that means the constraint is
|
|
** "x IS NULL" instead of "x=VALUE".
|
|
**
|
|
@@ -142276,9 +146506,9 @@
|
|
|
|
return rc;
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
/*
|
|
** Estimate the number of rows that will be returned based on
|
|
** an IN constraint where the right-hand side of the IN operator
|
|
@@ -142325,23 +146555,24 @@
|
|
assert( pBuilder->nRecValid==nRecValid );
|
|
return rc;
|
|
}
|
|
-#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
|
|
+#endif /* SQLITE_ENABLE_STAT4 */
|
|
|
|
|
|
#ifdef WHERETRACE_ENABLED
|
|
/*
|
|
** Print the content of a WhereTerm object
|
|
*/
|
|
-static void whereTermPrint(WhereTerm *pTerm, int iTerm){
|
|
+SQLITE_PRIVATE void sqlite3WhereTermPrint(WhereTerm *pTerm, int iTerm){
|
|
if( pTerm==0 ){
|
|
sqlite3DebugPrintf("TERM-%-3d NULL\n", iTerm);
|
|
}else{
|
|
- char zType[4];
|
|
+ char zType[8];
|
|
char zLeft[50];
|
|
- memcpy(zType, "...", 4);
|
|
+ memcpy(zType, "....", 5);
|
|
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
|
|
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
|
|
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
|
|
+ if( pTerm->wtFlags & TERM_CODED ) zType[3] = 'C';
|
|
if( pTerm->eOperator & WO_SINGLE ){
|
|
sqlite3_snprintf(sizeof(zLeft),zLeft,"left={%d:%d}",
|
|
pTerm->leftCursor, pTerm->u.leftColumn);
|
|
@@ -142352,14 +146583,21 @@
|
|
sqlite3_snprintf(sizeof(zLeft),zLeft,"left=%d", pTerm->leftCursor);
|
|
}
|
|
sqlite3DebugPrintf(
|
|
- "TERM-%-3d %p %s %-12s prob=%-3d op=0x%03x wtFlags=0x%04x",
|
|
- iTerm, pTerm, zType, zLeft, pTerm->truthProb,
|
|
- pTerm->eOperator, pTerm->wtFlags);
|
|
+ "TERM-%-3d %p %s %-12s op=%03x wtFlags=%04x",
|
|
+ iTerm, pTerm, zType, zLeft, pTerm->eOperator, pTerm->wtFlags);
|
|
+ /* The 0x10000 .wheretrace flag causes extra information to be
|
|
+ ** shown about each Term */
|
|
+ if( sqlite3WhereTrace & 0x10000 ){
|
|
+ sqlite3DebugPrintf(" prob=%-3d prereq=%llx,%llx",
|
|
+ pTerm->truthProb, (u64)pTerm->prereqAll, (u64)pTerm->prereqRight);
|
|
+ }
|
|
if( pTerm->iField ){
|
|
- sqlite3DebugPrintf(" iField=%d\n", pTerm->iField);
|
|
- }else{
|
|
- sqlite3DebugPrintf("\n");
|
|
+ sqlite3DebugPrintf(" iField=%d", pTerm->iField);
|
|
}
|
|
+ if( pTerm->iParent>=0 ){
|
|
+ sqlite3DebugPrintf(" iParent=%d", pTerm->iParent);
|
|
+ }
|
|
+ sqlite3DebugPrintf("\n");
|
|
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
|
|
}
|
|
}
|
|
@@ -142372,7 +146610,7 @@
|
|
SQLITE_PRIVATE void sqlite3WhereClausePrint(WhereClause *pWC){
|
|
int i;
|
|
for(i=0; i<pWC->nTerm; i++){
|
|
- whereTermPrint(&pWC->a[i], i);
|
|
+ sqlite3WhereTermPrint(&pWC->a[i], i);
|
|
}
|
|
}
|
|
#endif
|
|
@@ -142381,7 +146619,7 @@
|
|
/*
|
|
** Print a WhereLoop object for debugging purposes
|
|
*/
|
|
-static void whereLoopPrint(WhereLoop *p, WhereClause *pWC){
|
|
+SQLITE_PRIVATE void sqlite3WhereLoopPrint(WhereLoop *p, WhereClause *pWC){
|
|
WhereInfo *pWInfo = pWC->pWInfo;
|
|
int nb = 1+(pWInfo->pTabList->nSrc+3)/4;
|
|
struct SrcList_item *pItem = pWInfo->pTabList->a + p->iTab;
|
|
@@ -142406,7 +146644,7 @@
|
|
}else{
|
|
char *z;
|
|
if( p->u.vtab.idxStr ){
|
|
- z = sqlite3_mprintf("(%d,\"%s\",%x)",
|
|
+ z = sqlite3_mprintf("(%d,\"%s\",%#x)",
|
|
p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
|
|
}else{
|
|
z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
|
|
@@ -142423,7 +146661,7 @@
|
|
if( p->nLTerm && (sqlite3WhereTrace & 0x100)!=0 ){
|
|
int i;
|
|
for(i=0; i<p->nLTerm; i++){
|
|
- whereTermPrint(p->aLTerm[i], i);
|
|
+ sqlite3WhereTermPrint(p->aLTerm[i], i);
|
|
}
|
|
}
|
|
}
|
|
@@ -142527,6 +146765,7 @@
|
|
pWInfo->pLoops = p->pNextLoop;
|
|
whereLoopDelete(db, p);
|
|
}
|
|
+ assert( pWInfo->pExprMods==0 );
|
|
sqlite3DbFreeNN(db, pWInfo);
|
|
}
|
|
|
|
@@ -142728,6 +146967,8 @@
|
|
}
|
|
pBuilder->iPlanLimit--;
|
|
|
|
+ whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
|
|
+
|
|
/* If pBuilder->pOrSet is defined, then only keep track of the costs
|
|
** and prereqs.
|
|
*/
|
|
@@ -142742,7 +146983,7 @@
|
|
#if WHERETRACE_ENABLED /* 0x8 */
|
|
if( sqlite3WhereTrace & 0x8 ){
|
|
sqlite3DebugPrintf(x?" or-%d: ":" or-X: ", n);
|
|
- whereLoopPrint(pTemplate, pBuilder->pWC);
|
|
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
|
|
}
|
|
#endif
|
|
}
|
|
@@ -142751,7 +146992,6 @@
|
|
|
|
/* Look for an existing WhereLoop to replace with pTemplate
|
|
*/
|
|
- whereLoopAdjustCost(pWInfo->pLoops, pTemplate);
|
|
ppPrev = whereLoopFindLesser(&pWInfo->pLoops, pTemplate);
|
|
|
|
if( ppPrev==0 ){
|
|
@@ -142760,7 +147000,7 @@
|
|
#if WHERETRACE_ENABLED /* 0x8 */
|
|
if( sqlite3WhereTrace & 0x8 ){
|
|
sqlite3DebugPrintf(" skip: ");
|
|
- whereLoopPrint(pTemplate, pBuilder->pWC);
|
|
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
|
|
}
|
|
#endif
|
|
return SQLITE_OK;
|
|
@@ -142776,12 +147016,12 @@
|
|
if( sqlite3WhereTrace & 0x8 ){
|
|
if( p!=0 ){
|
|
sqlite3DebugPrintf("replace: ");
|
|
- whereLoopPrint(p, pBuilder->pWC);
|
|
+ sqlite3WhereLoopPrint(p, pBuilder->pWC);
|
|
sqlite3DebugPrintf(" with: ");
|
|
}else{
|
|
sqlite3DebugPrintf(" add: ");
|
|
}
|
|
- whereLoopPrint(pTemplate, pBuilder->pWC);
|
|
+ sqlite3WhereLoopPrint(pTemplate, pBuilder->pWC);
|
|
}
|
|
#endif
|
|
if( p==0 ){
|
|
@@ -142805,7 +147045,7 @@
|
|
#if WHERETRACE_ENABLED /* 0x8 */
|
|
if( sqlite3WhereTrace & 0x8 ){
|
|
sqlite3DebugPrintf(" delete: ");
|
|
- whereLoopPrint(pToDel, pBuilder->pWC);
|
|
+ sqlite3WhereLoopPrint(pToDel, pBuilder->pWC);
|
|
}
|
|
#endif
|
|
whereLoopDelete(db, pToDel);
|
|
@@ -142857,11 +147097,12 @@
|
|
){
|
|
WhereTerm *pTerm, *pX;
|
|
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
|
|
- int i, j, k;
|
|
+ int i, j;
|
|
LogEst iReduce = 0; /* pLoop->nOut should not exceed nRow-iReduce */
|
|
|
|
assert( (pLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
|
|
for(i=pWC->nTerm, pTerm=pWC->a; i>0; i--, pTerm++){
|
|
+ assert( pTerm!=0 );
|
|
if( (pTerm->wtFlags & TERM_VIRTUAL)!=0 ) break;
|
|
if( (pTerm->prereqAll & pLoop->maskSelf)==0 ) continue;
|
|
if( (pTerm->prereqAll & notAllowed)!=0 ) continue;
|
|
@@ -142880,15 +147121,21 @@
|
|
/* In the absence of explicit truth probabilities, use heuristics to
|
|
** guess a reasonable truth probability. */
|
|
pLoop->nOut--;
|
|
- if( pTerm->eOperator&(WO_EQ|WO_IS) ){
|
|
+ if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0
|
|
+ && (pTerm->wtFlags & TERM_HIGHTRUTH)==0 /* tag-20200224-1 */
|
|
+ ){
|
|
Expr *pRight = pTerm->pExpr->pRight;
|
|
+ int k = 0;
|
|
testcase( pTerm->pExpr->op==TK_IS );
|
|
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
|
|
k = 10;
|
|
}else{
|
|
k = 20;
|
|
}
|
|
- if( iReduce<k ) iReduce = k;
|
|
+ if( iReduce<k ){
|
|
+ pTerm->wtFlags |= TERM_HEURTRUTH;
|
|
+ iReduce = k;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -143012,8 +147259,9 @@
|
|
|
|
pNew = pBuilder->pNew;
|
|
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
|
|
- WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d\n",
|
|
- pProbe->pTable->zName,pProbe->zName, pNew->u.btree.nEq));
|
|
+ WHERETRACE(0x800, ("BEGIN %s.addBtreeIdx(%s), nEq=%d, nSkip=%d\n",
|
|
+ pProbe->pTable->zName,pProbe->zName,
|
|
+ pNew->u.btree.nEq, pNew->nSkip));
|
|
|
|
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
|
|
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
|
|
@@ -143045,7 +147293,7 @@
|
|
LogEst rCostIdx;
|
|
LogEst nOutUnadjusted; /* nOut before IN() and WHERE adjustments */
|
|
int nIn = 0;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
int nRecValid = pBuilder->nRecValid;
|
|
#endif
|
|
if( (eOp==WO_ISNULL || (pTerm->wtFlags&TERM_VNULL)!=0)
|
|
@@ -143059,9 +147307,9 @@
|
|
** to mix with a lower range bound from some other source */
|
|
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
|
|
|
|
- /* Do not allow constraints from the WHERE clause to be used by the
|
|
- ** right table of a LEFT JOIN. Only constraints in the ON clause are
|
|
- ** allowed */
|
|
+ /* tag-20191211-001: Do not allow constraints from the WHERE clause to
|
|
+ ** be used by the right table of a LEFT JOIN. Only constraints in the
|
|
+ ** ON clause are allowed. See tag-20191211-002 for the vtab equivalent. */
|
|
if( (pSrc->fg.jointype & JT_LEFT)!=0
|
|
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
|
|
){
|
|
@@ -143069,9 +147317,9 @@
|
|
}
|
|
|
|
if( IsUniqueIndex(pProbe) && saved_nEq==pProbe->nKeyCol-1 ){
|
|
- pBuilder->bldFlags |= SQLITE_BLDF_UNIQUE;
|
|
+ pBuilder->bldFlags1 |= SQLITE_BLDF1_UNIQUE;
|
|
}else{
|
|
- pBuilder->bldFlags |= SQLITE_BLDF_INDEXED;
|
|
+ pBuilder->bldFlags1 |= SQLITE_BLDF1_INDEXED;
|
|
}
|
|
pNew->wsFlags = saved_wsFlags;
|
|
pNew->u.btree.nEq = saved_nEq;
|
|
@@ -143106,8 +147354,6 @@
|
|
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
|
|
/* "x IN (value, value, ...)" */
|
|
nIn = sqlite3LogEst(pExpr->x.pList->nExpr);
|
|
- assert( nIn>0 ); /* RHS always has 2 or more terms... The parser
|
|
- ** changes "x IN (?)" into "x=?". */
|
|
}
|
|
if( pProbe->hasStat1 ){
|
|
LogEst M, logK, safetyMargin;
|
|
@@ -143203,7 +147449,7 @@
|
|
** the value of pNew->nOut to account for pTerm (but not nIn/nInMul). */
|
|
assert( pNew->nOut==saved_nOut );
|
|
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
|
|
- /* Adjust nOut using stat3/stat4 data. Or, if there is no stat3/stat4
|
|
+ /* Adjust nOut using stat4 data. Or, if there is no stat4
|
|
** data, using some other estimate. */
|
|
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
|
|
}else{
|
|
@@ -143217,13 +147463,13 @@
|
|
pNew->nOut += pTerm->truthProb;
|
|
pNew->nOut -= nIn;
|
|
}else{
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
tRowcnt nOut = 0;
|
|
if( nInMul==0
|
|
&& pProbe->nSample
|
|
&& pNew->u.btree.nEq<=pProbe->nSampleCol
|
|
&& ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
|
|
- && OptimizationEnabled(db, SQLITE_Stat34)
|
|
+ && OptimizationEnabled(db, SQLITE_Stat4)
|
|
){
|
|
Expr *pExpr = pTerm->pExpr;
|
|
if( (eOp & (WO_EQ|WO_ISNULL|WO_IS))!=0 ){
|
|
@@ -143238,6 +147484,27 @@
|
|
if( rc!=SQLITE_OK ) break; /* Jump out of the pTerm loop */
|
|
if( nOut ){
|
|
pNew->nOut = sqlite3LogEst(nOut);
|
|
+ if( nEq==1
|
|
+ /* TUNING: Mark terms as "low selectivity" if they seem likely
|
|
+ ** to be true for half or more of the rows in the table.
|
|
+ ** See tag-202002240-1 */
|
|
+ && pNew->nOut+10 > pProbe->aiRowLogEst[0]
|
|
+ ){
|
|
+#if WHERETRACE_ENABLED /* 0x01 */
|
|
+ if( sqlite3WhereTrace & 0x01 ){
|
|
+ sqlite3DebugPrintf(
|
|
+ "STAT4 determines term has low selectivity:\n");
|
|
+ sqlite3WhereTermPrint(pTerm, 999);
|
|
+ }
|
|
+#endif
|
|
+ pTerm->wtFlags |= TERM_HIGHTRUTH;
|
|
+ if( pTerm->wtFlags & TERM_HEURTRUTH ){
|
|
+ /* If the term has previously been used with an assumption of
|
|
+ ** higher selectivity, then set the flag to rerun the
|
|
+ ** loop computations. */
|
|
+ pBuilder->bldFlags2 |= SQLITE_BLDF2_2NDPASS;
|
|
+ }
|
|
+ }
|
|
if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
|
|
pNew->nOut -= nIn;
|
|
}
|
|
@@ -143260,6 +147527,7 @@
|
|
** it to pNew->rRun, which is currently set to the cost of the index
|
|
** seek only. Then, if this is a non-covering index, add the cost of
|
|
** visiting the rows in the main table. */
|
|
+ assert( pSrc->pTab->szTabRow>0 );
|
|
rCostIdx = pNew->nOut + 1 + (15*pProbe->szIdxRow)/pSrc->pTab->szTabRow;
|
|
pNew->rRun = sqlite3LogEstAdd(rLogSize, rCostIdx);
|
|
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
|
|
@@ -143285,7 +147553,7 @@
|
|
whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn);
|
|
}
|
|
pNew->nOut = saved_nOut;
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
pBuilder->nRecValid = nRecValid;
|
|
#endif
|
|
}
|
|
@@ -143311,7 +147579,9 @@
|
|
assert( 42==sqlite3LogEst(18) );
|
|
if( saved_nEq==saved_nSkip
|
|
&& saved_nEq+1<pProbe->nKeyCol
|
|
+ && saved_nEq==pNew->nLTerm
|
|
&& pProbe->noSkipScan==0
|
|
+ && pProbe->hasStat1!=0
|
|
&& OptimizationEnabled(db, SQLITE_SkipScan)
|
|
&& pProbe->aiRowLogEst[saved_nEq+1]>=42 /* TUNING: Minimum for skip-scan */
|
|
&& (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
|
|
@@ -143358,7 +147628,7 @@
|
|
if( pIndex->bUnordered ) return 0;
|
|
if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0;
|
|
for(ii=0; ii<pOB->nExpr; ii++){
|
|
- Expr *pExpr = sqlite3ExprSkipCollate(pOB->a[ii].pExpr);
|
|
+ Expr *pExpr = sqlite3ExprSkipCollateAndLikely(pOB->a[ii].pExpr);
|
|
if( pExpr->op==TK_COLUMN && pExpr->iTable==iCursor ){
|
|
if( pExpr->iColumn<0 ) return 1;
|
|
for(jj=0; jj<pIndex->nKeyCol; jj++){
|
|
@@ -143379,18 +147649,25 @@
|
|
/* Check to see if a partial index with pPartIndexWhere can be used
|
|
** in the current query. Return true if it can be and false if not.
|
|
*/
|
|
-static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
|
|
+static int whereUsablePartialIndex(
|
|
+ int iTab, /* The table for which we want an index */
|
|
+ int isLeft, /* True if iTab is the right table of a LEFT JOIN */
|
|
+ WhereClause *pWC, /* The WHERE clause of the query */
|
|
+ Expr *pWhere /* The WHERE clause from the partial index */
|
|
+){
|
|
int i;
|
|
WhereTerm *pTerm;
|
|
Parse *pParse = pWC->pWInfo->pParse;
|
|
while( pWhere->op==TK_AND ){
|
|
- if( !whereUsablePartialIndex(iTab,pWC,pWhere->pLeft) ) return 0;
|
|
+ if( !whereUsablePartialIndex(iTab,isLeft,pWC,pWhere->pLeft) ) return 0;
|
|
pWhere = pWhere->pRight;
|
|
}
|
|
if( pParse->db->flags & SQLITE_EnableQPSG ) pParse = 0;
|
|
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
|
- Expr *pExpr = pTerm->pExpr;
|
|
+ Expr *pExpr;
|
|
+ pExpr = pTerm->pExpr;
|
|
if( (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
|
|
+ && (isLeft==0 || ExprHasProperty(pExpr, EP_FromJoin))
|
|
&& sqlite3ExprImpliesExpr(pParse, pExpr, pWhere, iTab)
|
|
){
|
|
return 1;
|
|
@@ -143553,8 +147830,11 @@
|
|
for(; rc==SQLITE_OK && pProbe;
|
|
pProbe=(pSrc->pIBIndex ? 0 : pProbe->pNext), iSortIdx++
|
|
){
|
|
+ int isLeft = (pSrc->fg.jointype & JT_OUTER)!=0;
|
|
if( pProbe->pPartIdxWhere!=0
|
|
- && !whereUsablePartialIndex(pSrc->iCursor, pWC, pProbe->pPartIdxWhere) ){
|
|
+ && !whereUsablePartialIndex(pSrc->iCursor, isLeft, pWC,
|
|
+ pProbe->pPartIdxWhere)
|
|
+ ){
|
|
testcase( pNew->iTab!=pSrc->iCursor ); /* See ticket [98d973b8f5] */
|
|
continue; /* Partial index inappropriate for this query */
|
|
}
|
|
@@ -143649,16 +147929,16 @@
|
|
}
|
|
}
|
|
|
|
- pBuilder->bldFlags = 0;
|
|
+ pBuilder->bldFlags1 = 0;
|
|
rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
|
|
- if( pBuilder->bldFlags==SQLITE_BLDF_INDEXED ){
|
|
+ if( pBuilder->bldFlags1==SQLITE_BLDF1_INDEXED ){
|
|
/* If a non-unique index is used, or if a prefix of the key for
|
|
** unique index is used (making the index functionally non-unique)
|
|
** then the sqlite_stat1 data becomes important for scoring the
|
|
** plan */
|
|
pTab->tabFlags |= TF_StatsUsed;
|
|
}
|
|
-#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
sqlite3Stat4ProbeFree(pBuilder->pRec);
|
|
pBuilder->nRecValid = 0;
|
|
pBuilder->pRec = 0;
|
|
@@ -143781,7 +148061,14 @@
|
|
if( iTerm>mxTerm ) mxTerm = iTerm;
|
|
testcase( iTerm==15 );
|
|
testcase( iTerm==16 );
|
|
- if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm;
|
|
+ if( pUsage[i].omit ){
|
|
+ if( i<16 && ((1<<i)&mNoOmit)==0 ){
|
|
+ testcase( i!=iTerm );
|
|
+ pNew->u.vtab.omitMask |= 1<<iTerm;
|
|
+ }else{
|
|
+ testcase( i!=iTerm );
|
|
+ }
|
|
+ }
|
|
if( (pTerm->eOperator & WO_IN)!=0 ){
|
|
/* A virtual table that is constrained by an IN clause may not
|
|
** consume the ORDER BY clause because (1) the order of IN terms
|
|
@@ -143794,7 +148081,6 @@
|
|
}
|
|
}
|
|
}
|
|
- pNew->u.vtab.omitMask &= ~mNoOmit;
|
|
|
|
pNew->nLTerm = mxTerm+1;
|
|
for(i=0; i<=mxTerm; i++){
|
|
@@ -143851,7 +148137,7 @@
|
|
int iTerm = pIdxInfo->aConstraint[iCons].iTermOffset;
|
|
Expr *pX = pHidden->pWC->a[iTerm].pExpr;
|
|
if( pX->pLeft ){
|
|
- pC = sqlite3BinaryCompareCollSeq(pHidden->pParse, pX->pLeft, pX->pRight);
|
|
+ pC = sqlite3ExprCompareCollSeq(pHidden->pParse, pX);
|
|
}
|
|
zRet = (pC ? pC->zName : sqlite3StrBINARY);
|
|
}
|
|
@@ -144076,7 +148362,8 @@
|
|
if( rc==SQLITE_OK ){
|
|
rc = whereLoopAddOr(&sSubBuild, mPrereq, mUnusable);
|
|
}
|
|
- assert( rc==SQLITE_OK || sCur.n==0 );
|
|
+ assert( rc==SQLITE_OK || rc==SQLITE_DONE || sCur.n==0 );
|
|
+ testcase( rc==SQLITE_DONE );
|
|
if( sCur.n==0 ){
|
|
sSum.n = 0;
|
|
break;
|
|
@@ -144284,10 +148571,12 @@
|
|
pLoop = pLast;
|
|
}
|
|
if( pLoop->wsFlags & WHERE_VIRTUALTABLE ){
|
|
- if( pLoop->u.vtab.isOrdered ) obSat = obDone;
|
|
+ if( pLoop->u.vtab.isOrdered && (wctrlFlags & WHERE_DISTINCTBY)==0 ){
|
|
+ obSat = obDone;
|
|
+ }
|
|
break;
|
|
- }else{
|
|
- pLoop->u.btree.nIdxCol = 0;
|
|
+ }else if( wctrlFlags & WHERE_DISTINCTBY ){
|
|
+ pLoop->u.btree.nDistinctCol = 0;
|
|
}
|
|
iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor;
|
|
|
|
@@ -144298,7 +148587,7 @@
|
|
*/
|
|
for(i=0; i<nOrderBy; i++){
|
|
if( MASKBIT(i) & obSat ) continue;
|
|
- pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
|
|
+ pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
|
|
if( pOBExpr->op!=TK_COLUMN ) continue;
|
|
if( pOBExpr->iTable!=iCur ) continue;
|
|
pTerm = sqlite3WhereFindTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn,
|
|
@@ -144313,8 +148602,11 @@
|
|
if( j>=pLoop->nLTerm ) continue;
|
|
}
|
|
if( (pTerm->eOperator&(WO_EQ|WO_IS))!=0 && pOBExpr->iColumn>=0 ){
|
|
- if( sqlite3ExprCollSeqMatch(pWInfo->pParse,
|
|
- pOrderBy->a[i].pExpr, pTerm->pExpr)==0 ){
|
|
+ Parse *pParse = pWInfo->pParse;
|
|
+ CollSeq *pColl1 = sqlite3ExprNNCollSeq(pParse, pOrderBy->a[i].pExpr);
|
|
+ CollSeq *pColl2 = sqlite3ExprCompareCollSeq(pParse, pTerm->pExpr);
|
|
+ assert( pColl1 );
|
|
+ if( pColl2==0 || sqlite3StrICmp(pColl1->zName, pColl2->zName) ){
|
|
continue;
|
|
}
|
|
testcase( pTerm->pExpr->op==TK_IS );
|
|
@@ -144335,7 +148627,8 @@
|
|
assert( nColumn==nKeyCol+1 || !HasRowid(pIndex->pTable) );
|
|
assert( pIndex->aiColumn[nColumn-1]==XN_ROWID
|
|
|| !HasRowid(pIndex->pTable));
|
|
- isOrderDistinct = IsUniqueIndex(pIndex);
|
|
+ isOrderDistinct = IsUniqueIndex(pIndex)
|
|
+ && (pLoop->wsFlags & WHERE_SKIPSCAN)==0;
|
|
}
|
|
|
|
/* Loop through all columns of the index and deal with the ones
|
|
@@ -144353,15 +148646,21 @@
|
|
u16 eOp = pLoop->aLTerm[j]->eOperator;
|
|
|
|
/* Skip over == and IS and ISNULL terms. (Also skip IN terms when
|
|
- ** doing WHERE_ORDERBY_LIMIT processing).
|
|
+ ** doing WHERE_ORDERBY_LIMIT processing). Except, IS and ISNULL
|
|
+ ** terms imply that the index is not UNIQUE NOT NULL in which case
|
|
+ ** the loop need to be marked as not order-distinct because it can
|
|
+ ** have repeated NULL rows.
|
|
**
|
|
** If the current term is a column of an ((?,?) IN (SELECT...))
|
|
** expression for which the SELECT returns more than one column,
|
|
** check that it is the only column used by this loop. Otherwise,
|
|
** if it is one of two or more, none of the columns can be
|
|
- ** considered to match an ORDER BY term. */
|
|
+ ** considered to match an ORDER BY term.
|
|
+ */
|
|
if( (eOp & eqOpMask)!=0 ){
|
|
- if( eOp & WO_ISNULL ){
|
|
+ if( eOp & (WO_ISNULL|WO_IS) ){
|
|
+ testcase( eOp & WO_ISNULL );
|
|
+ testcase( eOp & WO_IS );
|
|
testcase( isOrderDistinct );
|
|
isOrderDistinct = 0;
|
|
}
|
|
@@ -144387,7 +148686,7 @@
|
|
*/
|
|
if( pIndex ){
|
|
iColumn = pIndex->aiColumn[j];
|
|
- revIdx = pIndex->aSortOrder[j];
|
|
+ revIdx = pIndex->aSortOrder[j] & KEYINFO_ORDER_DESC;
|
|
if( iColumn==pIndex->pTable->iPKey ) iColumn = XN_ROWID;
|
|
}else{
|
|
iColumn = XN_ROWID;
|
|
@@ -144411,7 +148710,7 @@
|
|
isMatch = 0;
|
|
for(i=0; bOnce && i<nOrderBy; i++){
|
|
if( MASKBIT(i) & obSat ) continue;
|
|
- pOBExpr = sqlite3ExprSkipCollate(pOrderBy->a[i].pExpr);
|
|
+ pOBExpr = sqlite3ExprSkipCollateAndLikely(pOrderBy->a[i].pExpr);
|
|
testcase( wctrlFlags & WHERE_GROUPBY );
|
|
testcase( wctrlFlags & WHERE_DISTINCTBY );
|
|
if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0;
|
|
@@ -144429,7 +148728,9 @@
|
|
pColl = sqlite3ExprNNCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr);
|
|
if( sqlite3StrICmp(pColl->zName, pIndex->azColl[j])!=0 ) continue;
|
|
}
|
|
- pLoop->u.btree.nIdxCol = j+1;
|
|
+ if( wctrlFlags & WHERE_DISTINCTBY ){
|
|
+ pLoop->u.btree.nDistinctCol = j+1;
|
|
+ }
|
|
isMatch = 1;
|
|
break;
|
|
}
|
|
@@ -144437,13 +148738,22 @@
|
|
/* Make sure the sort order is compatible in an ORDER BY clause.
|
|
** Sort order is irrelevant for a GROUP BY clause. */
|
|
if( revSet ){
|
|
- if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) isMatch = 0;
|
|
+ if( (rev ^ revIdx)!=(pOrderBy->a[i].sortFlags&KEYINFO_ORDER_DESC) ){
|
|
+ isMatch = 0;
|
|
+ }
|
|
}else{
|
|
- rev = revIdx ^ pOrderBy->a[i].sortOrder;
|
|
+ rev = revIdx ^ (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_DESC);
|
|
if( rev ) *pRevMask |= MASKBIT(iLoop);
|
|
revSet = 1;
|
|
}
|
|
}
|
|
+ if( isMatch && (pOrderBy->a[i].sortFlags & KEYINFO_ORDER_BIGNULL) ){
|
|
+ if( j==pLoop->u.btree.nEq ){
|
|
+ pLoop->wsFlags |= WHERE_BIGNULL_SORT;
|
|
+ }else{
|
|
+ isMatch = 0;
|
|
+ }
|
|
+ }
|
|
if( isMatch ){
|
|
if( iColumn==XN_ROWID ){
|
|
testcase( distinctColumns==0 );
|
|
@@ -145076,6 +149386,28 @@
|
|
return w.eCode;
|
|
}
|
|
|
|
+
|
|
+#ifdef WHERETRACE_ENABLED
|
|
+/*
|
|
+** Display all WhereLoops in pWInfo
|
|
+*/
|
|
+static void showAllWhereLoops(WhereInfo *pWInfo, WhereClause *pWC){
|
|
+ if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */
|
|
+ WhereLoop *p;
|
|
+ int i;
|
|
+ static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
|
+ "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
|
+ for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
|
|
+ p->cId = zLabel[i%(sizeof(zLabel)-1)];
|
|
+ sqlite3WhereLoopPrint(p, pWC);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+# define WHERETRACE_ALL_LOOPS(W,C) showAllWhereLoops(W,C)
|
|
+#else
|
|
+# define WHERETRACE_ALL_LOOPS(W,C)
|
|
+#endif
|
|
+
|
|
/*
|
|
** Generate the beginning of the loop used for WHERE clause processing.
|
|
** The return value is a pointer to an opaque structure that contains
|
|
@@ -145357,8 +149689,19 @@
|
|
sqlite3DebugPrintf(", limit: %d", iAuxArg);
|
|
}
|
|
sqlite3DebugPrintf(")\n");
|
|
+ if( sqlite3WhereTrace & 0x100 ){
|
|
+ Select sSelect;
|
|
+ memset(&sSelect, 0, sizeof(sSelect));
|
|
+ sSelect.selFlags = SF_WhereBegin;
|
|
+ sSelect.pSrc = pTabList;
|
|
+ sSelect.pWhere = pWhere;
|
|
+ sSelect.pOrderBy = pOrderBy;
|
|
+ sSelect.pEList = pResultSet;
|
|
+ sqlite3TreeViewSelect(0, &sSelect, 0);
|
|
+ }
|
|
}
|
|
if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
|
|
+ sqlite3DebugPrintf("---- WHERE clause at start of analysis:\n");
|
|
sqlite3WhereClausePrint(sWLB.pWC);
|
|
}
|
|
#endif
|
|
@@ -145366,19 +149709,28 @@
|
|
if( nTabList!=1 || whereShortCut(&sWLB)==0 ){
|
|
rc = whereLoopAddAll(&sWLB);
|
|
if( rc ) goto whereBeginError;
|
|
-
|
|
-#ifdef WHERETRACE_ENABLED
|
|
- if( sqlite3WhereTrace ){ /* Display all of the WhereLoop objects */
|
|
- WhereLoop *p;
|
|
- int i;
|
|
- static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
|
- "ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
|
- for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
|
|
- p->cId = zLabel[i%(sizeof(zLabel)-1)];
|
|
- whereLoopPrint(p, sWLB.pWC);
|
|
- }
|
|
- }
|
|
-#endif
|
|
+
|
|
+#ifdef SQLITE_ENABLE_STAT4
|
|
+ /* If one or more WhereTerm.truthProb values were used in estimating
|
|
+ ** loop parameters, but then those truthProb values were subsequently
|
|
+ ** changed based on STAT4 information while computing subsequent loops,
|
|
+ ** then we need to rerun the whole loop building process so that all
|
|
+ ** loops will be built using the revised truthProb values. */
|
|
+ if( sWLB.bldFlags2 & SQLITE_BLDF2_2NDPASS ){
|
|
+ WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
|
|
+ WHERETRACE(0xffff,
|
|
+ ("**** Redo all loop computations due to"
|
|
+ " TERM_HIGHTRUTH changes ****\n"));
|
|
+ while( pWInfo->pLoops ){
|
|
+ WhereLoop *p = pWInfo->pLoops;
|
|
+ pWInfo->pLoops = p->pNextLoop;
|
|
+ whereLoopDelete(db, p);
|
|
+ }
|
|
+ rc = whereLoopAddAll(&sWLB);
|
|
+ if( rc ) goto whereBeginError;
|
|
+ }
|
|
+#endif
|
|
+ WHERETRACE_ALL_LOOPS(pWInfo, sWLB.pWC);
|
|
|
|
wherePathSolver(pWInfo, 0);
|
|
if( db->mallocFailed ) goto whereBeginError;
|
|
@@ -145415,7 +149767,7 @@
|
|
}
|
|
sqlite3DebugPrintf("\n");
|
|
for(ii=0; ii<pWInfo->nLevel; ii++){
|
|
- whereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
|
|
+ sqlite3WhereLoopPrint(pWInfo->a[ii].pWLoop, sWLB.pWC);
|
|
}
|
|
}
|
|
#endif
|
|
@@ -145440,14 +149792,14 @@
|
|
** then table t2 can be omitted from the following:
|
|
**
|
|
** SELECT v1, v3 FROM t1
|
|
- ** LEFT JOIN t2 USING (t1.ipk=t2.ipk)
|
|
- ** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
|
|
+ ** LEFT JOIN t2 ON (t1.ipk=t2.ipk)
|
|
+ ** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
|
|
**
|
|
** or from:
|
|
**
|
|
** SELECT DISTINCT v1, v3 FROM t1
|
|
** LEFT JOIN t2
|
|
- ** LEFT JOIN t3 USING (t1.ipk=t3.ipk)
|
|
+ ** LEFT JOIN t3 ON (t1.ipk=t3.ipk)
|
|
*/
|
|
notReady = ~(Bitmask)0;
|
|
if( pWInfo->nLevel>=2
|
|
@@ -145497,7 +149849,13 @@
|
|
nTabList--;
|
|
}
|
|
}
|
|
+#if defined(WHERETRACE_ENABLED)
|
|
+ if( sqlite3WhereTrace & 0x100 ){ /* Display all terms of the WHERE clause */
|
|
+ sqlite3DebugPrintf("---- WHERE clause at end of analysis:\n");
|
|
+ sqlite3WhereClausePrint(sWLB.pWC);
|
|
+ }
|
|
WHERETRACE(0xffff,("*** Optimizer Finished ***\n"));
|
|
+#endif
|
|
pWInfo->pParse->nQueryLoop += pWInfo->nRowOut;
|
|
|
|
/* If the caller is an UPDATE or DELETE statement that is requesting
|
|
@@ -145574,7 +149932,13 @@
|
|
assert( pTabItem->iCursor==pLevel->iTabCur );
|
|
testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 );
|
|
testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS );
|
|
- if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){
|
|
+ if( pWInfo->eOnePass==ONEPASS_OFF
|
|
+ && pTab->nCol<BMS
|
|
+ && (pTab->tabFlags & (TF_HasGenerated|TF_WithoutRowid))==0
|
|
+ ){
|
|
+ /* If we know that only a prefix of the record will be used,
|
|
+ ** it is advantageous to reduce the "column count" field in
|
|
+ ** the P4 operand of the OP_OpenRead/Write opcode. */
|
|
Bitmask b = pTabItem->colUsed;
|
|
int n = 0;
|
|
for(; b; b=b>>1, n++){}
|
|
@@ -145633,10 +149997,11 @@
|
|
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
|
|
if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
|
|
&& (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
|
|
+ && (pLoop->wsFlags & WHERE_BIGNULL_SORT)==0
|
|
&& (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
|
|
&& pWInfo->eDistinct!=WHERE_DISTINCT_ORDERED
|
|
){
|
|
- sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
|
|
+ sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ);
|
|
}
|
|
VdbeComment((v, "%s", pIx->zName));
|
|
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
|
@@ -145750,7 +150115,7 @@
|
|
&& i==pWInfo->nLevel-1 /* Ticket [ef9318757b152e3] 2017-10-21 */
|
|
&& (pLoop->wsFlags & WHERE_INDEXED)!=0
|
|
&& (pIdx = pLoop->u.btree.pIndex)->hasStat1
|
|
- && (n = pLoop->u.btree.nIdxCol)>0
|
|
+ && (n = pLoop->u.btree.nDistinctCol)>0
|
|
&& pIdx->aiRowLogEst[n]>=36
|
|
){
|
|
int r1 = pParse->nMem+1;
|
|
@@ -145774,6 +150139,11 @@
|
|
VdbeCoverageIf(v, pLevel->op==OP_Next);
|
|
VdbeCoverageIf(v, pLevel->op==OP_Prev);
|
|
VdbeCoverageIf(v, pLevel->op==OP_VNext);
|
|
+ if( pLevel->regBignull ){
|
|
+ sqlite3VdbeResolveLabel(v, pLevel->addrBignull);
|
|
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, pLevel->regBignull, pLevel->p2-1);
|
|
+ VdbeCoverage(v);
|
|
+ }
|
|
#ifndef SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
|
if( addrSeek ) sqlite3VdbeJumpHere(v, addrSeek);
|
|
#endif
|
|
@@ -145789,10 +150159,27 @@
|
|
if( pIn->eEndLoopOp!=OP_Noop ){
|
|
if( pIn->nPrefix ){
|
|
assert( pLoop->wsFlags & WHERE_IN_EARLYOUT );
|
|
- sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
|
|
- sqlite3VdbeCurrentAddr(v)+2,
|
|
- pIn->iBase, pIn->nPrefix);
|
|
- VdbeCoverage(v);
|
|
+ if( pLevel->iLeftJoin ){
|
|
+ /* For LEFT JOIN queries, cursor pIn->iCur may not have been
|
|
+ ** opened yet. This occurs for WHERE clauses such as
|
|
+ ** "a = ? AND b IN (...)", where the index is on (a, b). If
|
|
+ ** the RHS of the (a=?) is NULL, then the "b IN (...)" may
|
|
+ ** never have been coded, but the body of the loop run to
|
|
+ ** return the null-row. So, if the cursor is not open yet,
|
|
+ ** jump over the OP_Next or OP_Prev instruction about to
|
|
+ ** be coded. */
|
|
+ sqlite3VdbeAddOp2(v, OP_IfNotOpen, pIn->iCur,
|
|
+ sqlite3VdbeCurrentAddr(v) + 2 +
|
|
+ ((pLoop->wsFlags & WHERE_VIRTUALTABLE)==0)
|
|
+ );
|
|
+ VdbeCoverage(v);
|
|
+ }
|
|
+ if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ){
|
|
+ sqlite3VdbeAddOp4Int(v, OP_IfNoHope, pLevel->iIdxCur,
|
|
+ sqlite3VdbeCurrentAddr(v)+2,
|
|
+ pIn->iBase, pIn->nPrefix);
|
|
+ VdbeCoverage(v);
|
|
+ }
|
|
}
|
|
sqlite3VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop);
|
|
VdbeCoverage(v);
|
|
@@ -145930,8 +150317,11 @@
|
|
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
|
|
x = pPk->aiColumn[x];
|
|
assert( x>=0 );
|
|
+ }else{
|
|
+ testcase( x!=sqlite3StorageColumnToTable(pTab,x) );
|
|
+ x = sqlite3StorageColumnToTable(pTab,x);
|
|
}
|
|
- x = sqlite3ColumnOfIndex(pIdx, x);
|
|
+ x = sqlite3TableColumnToIndex(pIdx, x);
|
|
if( x>=0 ){
|
|
pOp->p2 = x;
|
|
pOp->p1 = pLevel->iIdxCur;
|
|
@@ -145954,6 +150344,14 @@
|
|
}
|
|
}
|
|
|
|
+ /* Undo all Expr node modifications */
|
|
+ while( pWInfo->pExprMods ){
|
|
+ WhereExprMod *p = pWInfo->pExprMods;
|
|
+ pWInfo->pExprMods = p->pNext;
|
|
+ memcpy(p->pExpr, &p->orig, sizeof(p->orig));
|
|
+ sqlite3DbFree(db, p);
|
|
+ }
|
|
+
|
|
/* Final cleanup
|
|
*/
|
|
pParse->nQueryLoop = pWInfo->savedNQueryLoop;
|
|
@@ -146713,6 +151111,8 @@
|
|
static int selectWindowRewriteExprCb(Walker *pWalker, Expr *pExpr){
|
|
struct WindowRewrite *p = pWalker->u.pRewrite;
|
|
Parse *pParse = pWalker->pParse;
|
|
+ assert( p!=0 );
|
|
+ assert( p->pWin!=0 );
|
|
|
|
/* If this function is being called from within a scalar sub-select
|
|
** that used by the SELECT statement being processed, only process
|
|
@@ -146750,8 +151150,21 @@
|
|
|
|
case TK_AGG_FUNCTION:
|
|
case TK_COLUMN: {
|
|
- Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
|
|
- p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
|
|
+ int iCol = -1;
|
|
+ if( p->pSub ){
|
|
+ int i;
|
|
+ for(i=0; i<p->pSub->nExpr; i++){
|
|
+ if( 0==sqlite3ExprCompare(0, p->pSub->a[i].pExpr, pExpr, -1) ){
|
|
+ iCol = i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ if( iCol<0 ){
|
|
+ Expr *pDup = sqlite3ExprDup(pParse->db, pExpr, 0);
|
|
+ if( pDup && pDup->op==TK_AGG_FUNCTION ) pDup->op = TK_FUNCTION;
|
|
+ p->pSub = sqlite3ExprListAppend(pParse, p->pSub, pDup);
|
|
+ }
|
|
if( p->pSub ){
|
|
assert( ExprHasProperty(pExpr, EP_Static)==0 );
|
|
ExprSetProperty(pExpr, EP_Static);
|
|
@@ -146760,11 +151173,11 @@
|
|
memset(pExpr, 0, sizeof(Expr));
|
|
|
|
pExpr->op = TK_COLUMN;
|
|
- pExpr->iColumn = p->pSub->nExpr-1;
|
|
+ pExpr->iColumn = (iCol<0 ? p->pSub->nExpr-1: iCol);
|
|
pExpr->iTable = p->pWin->iEphCsr;
|
|
pExpr->y.pTab = p->pTab;
|
|
}
|
|
-
|
|
+ if( pParse->db->mallocFailed ) return WRC_Abort;
|
|
break;
|
|
}
|
|
|
|
@@ -146812,6 +151225,7 @@
|
|
Walker sWalker;
|
|
WindowRewrite sRewrite;
|
|
|
|
+ assert( pWin!=0 );
|
|
memset(&sWalker, 0, sizeof(Walker));
|
|
memset(&sRewrite, 0, sizeof(WindowRewrite));
|
|
|
|
@@ -146845,17 +151259,43 @@
|
|
int nInit = pList ? pList->nExpr : 0;
|
|
for(i=0; i<pAppend->nExpr; i++){
|
|
Expr *pDup = sqlite3ExprDup(pParse->db, pAppend->a[i].pExpr, 0);
|
|
- if( bIntToNull && pDup && pDup->op==TK_INTEGER ){
|
|
- pDup->op = TK_NULL;
|
|
- pDup->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
|
|
+ assert( pDup==0 || !ExprHasProperty(pDup, EP_MemToken) );
|
|
+ if( bIntToNull && pDup ){
|
|
+ int iDummy;
|
|
+ Expr *pSub;
|
|
+ for(pSub=pDup; ExprHasProperty(pSub, EP_Skip); pSub=pSub->pLeft){
|
|
+ assert( pSub );
|
|
+ }
|
|
+ if( sqlite3ExprIsInteger(pSub, &iDummy) ){
|
|
+ pSub->op = TK_NULL;
|
|
+ pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
|
|
+ pSub->u.zToken = 0;
|
|
+ }
|
|
}
|
|
pList = sqlite3ExprListAppend(pParse, pList, pDup);
|
|
- if( pList ) pList->a[nInit+i].sortOrder = pAppend->a[i].sortOrder;
|
|
+ if( pList ) pList->a[nInit+i].sortFlags = pAppend->a[i].sortFlags;
|
|
}
|
|
}
|
|
return pList;
|
|
}
|
|
|
|
+/*
|
|
+** When rewriting a query, if the new subquery in the FROM clause
|
|
+** contains TK_AGG_FUNCTION nodes that refer to an outer query,
|
|
+** then we have to increase the Expr->op2 values of those nodes
|
|
+** due to the extra subquery layer that was added.
|
|
+**
|
|
+** See also the incrAggDepth() routine in resolve.c
|
|
+*/
|
|
+static int sqlite3WindowExtraAggFuncDepth(Walker *pWalker, Expr *pExpr){
|
|
+ if( pExpr->op==TK_AGG_FUNCTION
|
|
+ && pExpr->op2>=pWalker->walkerDepth
|
|
+ ){
|
|
+ pExpr->op2++;
|
|
+ }
|
|
+ return WRC_Continue;
|
|
+}
|
|
+
|
|
/*
|
|
** If the SELECT statement passed as the second argument does not invoke
|
|
** any SQL window functions, this function is a no-op. Otherwise, it
|
|
@@ -146865,7 +151305,7 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
|
int rc = SQLITE_OK;
|
|
- if( p->pWin && p->pPrior==0 ){
|
|
+ if( p->pWin && p->pPrior==0 && (p->selFlags & SF_WinRewrite)==0 ){
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
sqlite3 *db = pParse->db;
|
|
Select *pSub = 0; /* The subquery */
|
|
@@ -146879,10 +151319,11 @@
|
|
Window *pMWin = p->pWin; /* Master window object */
|
|
Window *pWin; /* Window object iterator */
|
|
Table *pTab;
|
|
+ u32 selFlags = p->selFlags;
|
|
|
|
pTab = sqlite3DbMallocZero(db, sizeof(Table));
|
|
if( pTab==0 ){
|
|
- return SQLITE_NOMEM;
|
|
+ return sqlite3ErrorToParser(db, SQLITE_NOMEM);
|
|
}
|
|
|
|
p->pSrc = 0;
|
|
@@ -146890,17 +151331,21 @@
|
|
p->pGroupBy = 0;
|
|
p->pHaving = 0;
|
|
p->selFlags &= ~SF_Aggregate;
|
|
+ p->selFlags |= SF_WinRewrite;
|
|
|
|
/* Create the ORDER BY clause for the sub-select. This is the concatenation
|
|
** of the window PARTITION and ORDER BY clauses. Then, if this makes it
|
|
** redundant, remove the ORDER BY from the parent SELECT. */
|
|
- pSort = sqlite3ExprListDup(db, pMWin->pPartition, 0);
|
|
+ pSort = exprListAppendList(pParse, 0, pMWin->pPartition, 1);
|
|
pSort = exprListAppendList(pParse, pSort, pMWin->pOrderBy, 1);
|
|
- if( pSort && p->pOrderBy ){
|
|
+ if( pSort && p->pOrderBy && p->pOrderBy->nExpr<=pSort->nExpr ){
|
|
+ int nSave = pSort->nExpr;
|
|
+ pSort->nExpr = p->pOrderBy->nExpr;
|
|
if( sqlite3ExprListCompare(pSort, p->pOrderBy, -1)==0 ){
|
|
sqlite3ExprListDelete(db, p->pOrderBy);
|
|
p->pOrderBy = 0;
|
|
}
|
|
+ pSort->nExpr = nSave;
|
|
}
|
|
|
|
/* Assign a cursor number for the ephemeral table used to buffer rows.
|
|
@@ -146924,8 +151369,15 @@
|
|
** window function - one for the accumulator, another for interim
|
|
** results. */
|
|
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
|
- pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
|
|
- pSublist = exprListAppendList(pParse, pSublist, pWin->pOwner->x.pList, 0);
|
|
+ ExprList *pArgs = pWin->pOwner->x.pList;
|
|
+ if( pWin->pFunc->funcFlags & SQLITE_FUNC_SUBTYPE ){
|
|
+ selectWindowRewriteEList(pParse, pMWin, pSrc, pArgs, pTab, &pSublist);
|
|
+ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
|
|
+ pWin->bExprArgs = 1;
|
|
+ }else{
|
|
+ pWin->iArgCol = (pSublist ? pSublist->nExpr : 0);
|
|
+ pSublist = exprListAppendList(pParse, pSublist, pArgs, 0);
|
|
+ }
|
|
if( pWin->pFilter ){
|
|
Expr *pFilter = sqlite3ExprDup(db, pWin->pFilter, 0);
|
|
pSublist = sqlite3ExprListAppend(pParse, pSublist, pFilter);
|
|
@@ -146943,7 +151395,7 @@
|
|
*/
|
|
if( pSublist==0 ){
|
|
pSublist = sqlite3ExprListAppend(pParse, 0,
|
|
- sqlite3ExprAlloc(db, TK_INTEGER, &sqlite3IntTokens[0], 0)
|
|
+ sqlite3Expr(db, TK_INTEGER, "0")
|
|
);
|
|
}
|
|
|
|
@@ -146953,22 +151405,28 @@
|
|
p->pSrc = sqlite3SrcListAppend(pParse, 0, 0, 0);
|
|
if( p->pSrc ){
|
|
Table *pTab2;
|
|
+ Walker w;
|
|
p->pSrc->a[0].pSelect = pSub;
|
|
sqlite3SrcListAssignCursors(pParse, p->pSrc);
|
|
pSub->selFlags |= SF_Expanded;
|
|
- pTab2 = sqlite3ResultSetOfSelect(pParse, pSub);
|
|
+ pTab2 = sqlite3ResultSetOfSelect(pParse, pSub, SQLITE_AFF_NONE);
|
|
+ pSub->selFlags |= (selFlags & SF_Aggregate);
|
|
if( pTab2==0 ){
|
|
+ /* Might actually be some other kind of error, but in that case
|
|
+ ** pParse->nErr will be set, so if SQLITE_NOMEM is set, we will get
|
|
+ ** the correct error message regardless. */
|
|
rc = SQLITE_NOMEM;
|
|
}else{
|
|
memcpy(pTab, pTab2, sizeof(Table));
|
|
pTab->tabFlags |= TF_Ephemeral;
|
|
p->pSrc->a[0].pTab = pTab;
|
|
pTab = pTab2;
|
|
+ memset(&w, 0, sizeof(w));
|
|
+ w.xExprCallback = sqlite3WindowExtraAggFuncDepth;
|
|
+ w.xSelectCallback = sqlite3WalkerDepthIncrease;
|
|
+ w.xSelectCallback2 = sqlite3WalkerDepthDecrease;
|
|
+ sqlite3WalkSelect(&w, pSub);
|
|
}
|
|
- sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, pSublist->nExpr);
|
|
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
|
|
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
|
|
- sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
|
|
}else{
|
|
sqlite3SelectDelete(db, pSub);
|
|
}
|
|
@@ -146976,14 +151434,34 @@
|
|
sqlite3DbFree(db, pTab);
|
|
}
|
|
|
|
+ if( rc ){
|
|
+ if( pParse->nErr==0 ){
|
|
+ assert( pParse->db->mallocFailed );
|
|
+ sqlite3ErrorToParser(pParse->db, SQLITE_NOMEM);
|
|
+ }
|
|
+ sqlite3SelectReset(pParse, p);
|
|
+ }
|
|
return rc;
|
|
}
|
|
|
|
+/*
|
|
+** Unlink the Window object from the Select to which it is attached,
|
|
+** if it is attached.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3WindowUnlinkFromSelect(Window *p){
|
|
+ if( p->ppThis ){
|
|
+ *p->ppThis = p->pNextWin;
|
|
+ if( p->pNextWin ) p->pNextWin->ppThis = p->ppThis;
|
|
+ p->ppThis = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Free the Window object passed as the second argument.
|
|
*/
|
|
SQLITE_PRIVATE void sqlite3WindowDelete(sqlite3 *db, Window *p){
|
|
if( p ){
|
|
+ sqlite3WindowUnlinkFromSelect(p);
|
|
sqlite3ExprDelete(db, p->pFilter);
|
|
sqlite3ExprListDelete(db, p->pPartition);
|
|
sqlite3ExprListDelete(db, p->pOrderBy);
|
|
@@ -147161,17 +151639,14 @@
|
|
SQLITE_PRIVATE void sqlite3WindowAttach(Parse *pParse, Expr *p, Window *pWin){
|
|
if( p ){
|
|
assert( p->op==TK_FUNCTION );
|
|
- /* This routine is only called for the parser. If pWin was not
|
|
- ** allocated due to an OOM, then the parser would fail before ever
|
|
- ** invoking this routine */
|
|
- if( ALWAYS(pWin) ){
|
|
- p->y.pWin = pWin;
|
|
- ExprSetProperty(p, EP_WinFunc);
|
|
- pWin->pOwner = p;
|
|
- if( p->flags & EP_Distinct ){
|
|
- sqlite3ErrorMsg(pParse,
|
|
- "DISTINCT is not supported for window functions");
|
|
- }
|
|
+ assert( pWin );
|
|
+ p->y.pWin = pWin;
|
|
+ ExprSetProperty(p, EP_WinFunc);
|
|
+ pWin->pOwner = p;
|
|
+ if( (p->flags & EP_Distinct) && pWin->eFrmType!=TK_FILTER ){
|
|
+ sqlite3ErrorMsg(pParse,
|
|
+ "DISTINCT is not supported for window functions"
|
|
+ );
|
|
}
|
|
}else{
|
|
sqlite3WindowDelete(pParse->db, pWin);
|
|
@@ -147179,18 +151654,49 @@
|
|
}
|
|
|
|
/*
|
|
-** Return 0 if the two window objects are identical, or non-zero otherwise.
|
|
-** Identical window objects can be processed in a single scan.
|
|
+** Possibly link window pWin into the list at pSel->pWin (window functions
|
|
+** to be processed as part of SELECT statement pSel). The window is linked
|
|
+** in if either (a) there are no other windows already linked to this
|
|
+** SELECT, or (b) the windows already linked use a compatible window frame.
|
|
+*/
|
|
+SQLITE_PRIVATE void sqlite3WindowLink(Select *pSel, Window *pWin){
|
|
+ if( pSel!=0
|
|
+ && (0==pSel->pWin || 0==sqlite3WindowCompare(0, pSel->pWin, pWin, 0))
|
|
+ ){
|
|
+ pWin->pNextWin = pSel->pWin;
|
|
+ if( pSel->pWin ){
|
|
+ pSel->pWin->ppThis = &pWin->pNextWin;
|
|
+ }
|
|
+ pSel->pWin = pWin;
|
|
+ pWin->ppThis = &pSel->pWin;
|
|
+ }
|
|
+}
|
|
+
|
|
+/*
|
|
+** Return 0 if the two window objects are identical, 1 if they are
|
|
+** different, or 2 if it cannot be determined if the objects are identical
|
|
+** or not. Identical window objects can be processed in a single scan.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2){
|
|
+SQLITE_PRIVATE int sqlite3WindowCompare(Parse *pParse, Window *p1, Window *p2, int bFilter){
|
|
+ int res;
|
|
+ if( NEVER(p1==0) || NEVER(p2==0) ) return 1;
|
|
if( p1->eFrmType!=p2->eFrmType ) return 1;
|
|
if( p1->eStart!=p2->eStart ) return 1;
|
|
if( p1->eEnd!=p2->eEnd ) return 1;
|
|
if( p1->eExclude!=p2->eExclude ) return 1;
|
|
if( sqlite3ExprCompare(pParse, p1->pStart, p2->pStart, -1) ) return 1;
|
|
if( sqlite3ExprCompare(pParse, p1->pEnd, p2->pEnd, -1) ) return 1;
|
|
- if( sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1) ) return 1;
|
|
- if( sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1) ) return 1;
|
|
+ if( (res = sqlite3ExprListCompare(p1->pPartition, p2->pPartition, -1)) ){
|
|
+ return res;
|
|
+ }
|
|
+ if( (res = sqlite3ExprListCompare(p1->pOrderBy, p2->pOrderBy, -1)) ){
|
|
+ return res;
|
|
+ }
|
|
+ if( bFilter ){
|
|
+ if( (res = sqlite3ExprCompare(pParse, p1->pFilter, p2->pFilter, -1)) ){
|
|
+ return res;
|
|
+ }
|
|
+ }
|
|
return 0;
|
|
}
|
|
|
|
@@ -147200,10 +151706,17 @@
|
|
** to begin iterating through the sub-query results. It is used to allocate
|
|
** and initialize registers and cursors used by sqlite3WindowCodeStep().
|
|
*/
|
|
-SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Window *pMWin){
|
|
+SQLITE_PRIVATE void sqlite3WindowCodeInit(Parse *pParse, Select *pSelect){
|
|
+ int nEphExpr = pSelect->pSrc->a[0].pSelect->pEList->nExpr;
|
|
+ Window *pMWin = pSelect->pWin;
|
|
Window *pWin;
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
|
|
+ sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pMWin->iEphCsr, nEphExpr);
|
|
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+1, pMWin->iEphCsr);
|
|
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+2, pMWin->iEphCsr);
|
|
+ sqlite3VdbeAddOp2(v, OP_OpenDup, pMWin->iEphCsr+3, pMWin->iEphCsr);
|
|
+
|
|
/* Allocate registers to use for PARTITION BY values, if any. Initialize
|
|
** said registers to NULL. */
|
|
if( pMWin->pPartition ){
|
|
@@ -147242,8 +151755,8 @@
|
|
pWin->regApp = pParse->nMem+1;
|
|
pParse->nMem += 3;
|
|
if( pKeyInfo && pWin->pFunc->zName[1]=='i' ){
|
|
- assert( pKeyInfo->aSortOrder[0]==0 );
|
|
- pKeyInfo->aSortOrder[0] = 1;
|
|
+ assert( pKeyInfo->aSortFlags[0]==0 );
|
|
+ pKeyInfo->aSortFlags[0] = KEYINFO_ORDER_DESC;
|
|
}
|
|
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pWin->csrApp, 2);
|
|
sqlite3VdbeAppendP4(v, pKeyInfo, P4_KEYINFO);
|
|
@@ -147328,6 +151841,108 @@
|
|
return (pList ? pList->nExpr : 0);
|
|
}
|
|
|
|
+typedef struct WindowCodeArg WindowCodeArg;
|
|
+typedef struct WindowCsrAndReg WindowCsrAndReg;
|
|
+
|
|
+/*
|
|
+** See comments above struct WindowCodeArg.
|
|
+*/
|
|
+struct WindowCsrAndReg {
|
|
+ int csr; /* Cursor number */
|
|
+ int reg; /* First in array of peer values */
|
|
+};
|
|
+
|
|
+/*
|
|
+** A single instance of this structure is allocated on the stack by
|
|
+** sqlite3WindowCodeStep() and a pointer to it passed to the various helper
|
|
+** routines. This is to reduce the number of arguments required by each
|
|
+** helper function.
|
|
+**
|
|
+** regArg:
|
|
+** Each window function requires an accumulator register (just as an
|
|
+** ordinary aggregate function does). This variable is set to the first
|
|
+** in an array of accumulator registers - one for each window function
|
|
+** in the WindowCodeArg.pMWin list.
|
|
+**
|
|
+** eDelete:
|
|
+** The window functions implementation sometimes caches the input rows
|
|
+** that it processes in a temporary table. If it is not zero, this
|
|
+** variable indicates when rows may be removed from the temp table (in
|
|
+** order to reduce memory requirements - it would always be safe just
|
|
+** to leave them there). Possible values for eDelete are:
|
|
+**
|
|
+** WINDOW_RETURN_ROW:
|
|
+** An input row can be discarded after it is returned to the caller.
|
|
+**
|
|
+** WINDOW_AGGINVERSE:
|
|
+** An input row can be discarded after the window functions xInverse()
|
|
+** callbacks have been invoked in it.
|
|
+**
|
|
+** WINDOW_AGGSTEP:
|
|
+** An input row can be discarded after the window functions xStep()
|
|
+** callbacks have been invoked in it.
|
|
+**
|
|
+** start,current,end
|
|
+** Consider a window-frame similar to the following:
|
|
+**
|
|
+** (ORDER BY a, b GROUPS BETWEEN 2 PRECEDING AND 2 FOLLOWING)
|
|
+**
|
|
+** The windows functions implmentation caches the input rows in a temp
|
|
+** table, sorted by "a, b" (it actually populates the cache lazily, and
|
|
+** aggressively removes rows once they are no longer required, but that's
|
|
+** a mere detail). It keeps three cursors open on the temp table. One
|
|
+** (current) that points to the next row to return to the query engine
|
|
+** once its window function values have been calculated. Another (end)
|
|
+** points to the next row to call the xStep() method of each window function
|
|
+** on (so that it is 2 groups ahead of current). And a third (start) that
|
|
+** points to the next row to call the xInverse() method of each window
|
|
+** function on.
|
|
+**
|
|
+** Each cursor (start, current and end) consists of a VDBE cursor
|
|
+** (WindowCsrAndReg.csr) and an array of registers (starting at
|
|
+** WindowCodeArg.reg) that always contains a copy of the peer values
|
|
+** read from the corresponding cursor.
|
|
+**
|
|
+** Depending on the window-frame in question, all three cursors may not
|
|
+** be required. In this case both WindowCodeArg.csr and reg are set to
|
|
+** 0.
|
|
+*/
|
|
+struct WindowCodeArg {
|
|
+ Parse *pParse; /* Parse context */
|
|
+ Window *pMWin; /* First in list of functions being processed */
|
|
+ Vdbe *pVdbe; /* VDBE object */
|
|
+ int addrGosub; /* OP_Gosub to this address to return one row */
|
|
+ int regGosub; /* Register used with OP_Gosub(addrGosub) */
|
|
+ int regArg; /* First in array of accumulator registers */
|
|
+ int eDelete; /* See above */
|
|
+
|
|
+ WindowCsrAndReg start;
|
|
+ WindowCsrAndReg current;
|
|
+ WindowCsrAndReg end;
|
|
+};
|
|
+
|
|
+/*
|
|
+** Generate VM code to read the window frames peer values from cursor csr into
|
|
+** an array of registers starting at reg.
|
|
+*/
|
|
+static void windowReadPeerValues(
|
|
+ WindowCodeArg *p,
|
|
+ int csr,
|
|
+ int reg
|
|
+){
|
|
+ Window *pMWin = p->pMWin;
|
|
+ ExprList *pOrderBy = pMWin->pOrderBy;
|
|
+ if( pOrderBy ){
|
|
+ Vdbe *v = sqlite3GetVdbe(p->pParse);
|
|
+ ExprList *pPart = pMWin->pPartition;
|
|
+ int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
|
|
+ int i;
|
|
+ for(i=0; i<pOrderBy->nExpr; i++){
|
|
+ sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
/*
|
|
** Generate VM code to invoke either xStep() (if bInverse is 0) or
|
|
** xInverse (if bInverse is non-zero) for each window function in the
|
|
@@ -147348,20 +151963,27 @@
|
|
** number of rows in the current partition.
|
|
*/
|
|
static void windowAggStep(
|
|
- Parse *pParse,
|
|
+ WindowCodeArg *p,
|
|
Window *pMWin, /* Linked list of window functions */
|
|
int csr, /* Read arguments from this cursor */
|
|
int bInverse, /* True to invoke xInverse instead of xStep */
|
|
int reg /* Array of registers */
|
|
){
|
|
+ Parse *pParse = p->pParse;
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
Window *pWin;
|
|
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
|
FuncDef *pFunc = pWin->pFunc;
|
|
int regArg;
|
|
- int nArg = windowArgCount(pWin);
|
|
+ int nArg = pWin->bExprArgs ? 0 : windowArgCount(pWin);
|
|
int i;
|
|
|
|
+ assert( bInverse==0 || pWin->eStart!=TK_UNBOUNDED );
|
|
+
|
|
+ /* All OVER clauses in the same window function aggregate step must
|
|
+ ** be the same. */
|
|
+ assert( pWin==pMWin || sqlite3WindowCompare(pParse,pWin,pMWin,0)!=1 );
|
|
+
|
|
for(i=0; i<nArg; i++){
|
|
if( i!=1 || pFunc->zName!=nth_valueName ){
|
|
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+i, reg+i);
|
|
@@ -147399,14 +152021,30 @@
|
|
int addrIf = 0;
|
|
if( pWin->pFilter ){
|
|
int regTmp;
|
|
- assert( nArg==0 || nArg==pWin->pOwner->x.pList->nExpr );
|
|
- assert( nArg || pWin->pOwner->x.pList==0 );
|
|
+ assert( pWin->bExprArgs || !nArg ||nArg==pWin->pOwner->x.pList->nExpr );
|
|
+ assert( pWin->bExprArgs || nArg ||pWin->pOwner->x.pList==0 );
|
|
regTmp = sqlite3GetTempReg(pParse);
|
|
sqlite3VdbeAddOp3(v, OP_Column, csr, pWin->iArgCol+nArg,regTmp);
|
|
addrIf = sqlite3VdbeAddOp3(v, OP_IfNot, regTmp, 0, 1);
|
|
VdbeCoverage(v);
|
|
sqlite3ReleaseTempReg(pParse, regTmp);
|
|
}
|
|
+
|
|
+ if( pWin->bExprArgs ){
|
|
+ int iStart = sqlite3VdbeCurrentAddr(v);
|
|
+ VdbeOp *pOp, *pEnd;
|
|
+
|
|
+ nArg = pWin->pOwner->x.pList->nExpr;
|
|
+ regArg = sqlite3GetTempRange(pParse, nArg);
|
|
+ sqlite3ExprCodeExprList(pParse, pWin->pOwner->x.pList, regArg, 0, 0);
|
|
+
|
|
+ pEnd = sqlite3VdbeGetOp(v, -1);
|
|
+ for(pOp=sqlite3VdbeGetOp(v, iStart); pOp<=pEnd; pOp++){
|
|
+ if( pOp->opcode==OP_Column && pOp->p1==pWin->iEphCsr ){
|
|
+ pOp->p1 = csr;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
if( pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
|
|
CollSeq *pColl;
|
|
assert( nArg>0 );
|
|
@@ -147417,32 +152055,14 @@
|
|
bInverse, regArg, pWin->regAccum);
|
|
sqlite3VdbeAppendP4(v, pFunc, P4_FUNCDEF);
|
|
sqlite3VdbeChangeP5(v, (u8)nArg);
|
|
+ if( pWin->bExprArgs ){
|
|
+ sqlite3ReleaseTempRange(pParse, regArg, nArg);
|
|
+ }
|
|
if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
|
|
}
|
|
}
|
|
}
|
|
|
|
-typedef struct WindowCodeArg WindowCodeArg;
|
|
-typedef struct WindowCsrAndReg WindowCsrAndReg;
|
|
-struct WindowCsrAndReg {
|
|
- int csr;
|
|
- int reg;
|
|
-};
|
|
-
|
|
-struct WindowCodeArg {
|
|
- Parse *pParse;
|
|
- Window *pMWin;
|
|
- Vdbe *pVdbe;
|
|
- int regGosub;
|
|
- int addrGosub;
|
|
- int regArg;
|
|
- int eDelete;
|
|
-
|
|
- WindowCsrAndReg start;
|
|
- WindowCsrAndReg current;
|
|
- WindowCsrAndReg end;
|
|
-};
|
|
-
|
|
/*
|
|
** Values that may be passed as the second argument to windowCodeOp().
|
|
*/
|
|
@@ -147450,28 +152070,6 @@
|
|
#define WINDOW_AGGINVERSE 2
|
|
#define WINDOW_AGGSTEP 3
|
|
|
|
-/*
|
|
-** Generate VM code to read the window frames peer values from cursor csr into
|
|
-** an array of registers starting at reg.
|
|
-*/
|
|
-static void windowReadPeerValues(
|
|
- WindowCodeArg *p,
|
|
- int csr,
|
|
- int reg
|
|
-){
|
|
- Window *pMWin = p->pMWin;
|
|
- ExprList *pOrderBy = pMWin->pOrderBy;
|
|
- if( pOrderBy ){
|
|
- Vdbe *v = sqlite3GetVdbe(p->pParse);
|
|
- ExprList *pPart = pMWin->pPartition;
|
|
- int iColOff = pMWin->nBufferCol + (pPart ? pPart->nExpr : 0);
|
|
- int i;
|
|
- for(i=0; i<pOrderBy->nExpr; i++){
|
|
- sqlite3VdbeAddOp3(v, OP_Column, csr, iColOff+i, reg+i);
|
|
- }
|
|
- }
|
|
-}
|
|
-
|
|
/*
|
|
** Generate VM code to invoke either xValue() (bFin==0) or xFinalize()
|
|
** (bFin==1) for each window function in the linked list starting at
|
|
@@ -147532,8 +152130,12 @@
|
|
int lblNext;
|
|
int lblBrk;
|
|
int addrNext;
|
|
- int csr = pMWin->csrApp;
|
|
+ int csr;
|
|
+
|
|
+ VdbeModuleComment((v, "windowFullScan begin"));
|
|
|
|
+ assert( pMWin!=0 );
|
|
+ csr = pMWin->csrApp;
|
|
nPeer = (pMWin->pOrderBy ? pMWin->pOrderBy->nExpr : 0);
|
|
|
|
lblNext = sqlite3VdbeMakeLabel(pParse);
|
|
@@ -147588,7 +152190,7 @@
|
|
if( addrEq ) sqlite3VdbeJumpHere(v, addrEq);
|
|
}
|
|
|
|
- windowAggStep(pParse, pMWin, csr, 0, p->regArg);
|
|
+ windowAggStep(p, pMWin, csr, 0, p->regArg);
|
|
|
|
sqlite3VdbeResolveLabel(v, lblNext);
|
|
sqlite3VdbeAddOp2(v, OP_Next, csr, addrNext);
|
|
@@ -147603,6 +152205,7 @@
|
|
}
|
|
|
|
windowAggFinal(p, 1);
|
|
+ VdbeModuleComment((v, "windowFullScan end"));
|
|
}
|
|
|
|
/*
|
|
@@ -147701,6 +152304,7 @@
|
|
Window *pWin;
|
|
for(pWin=pMWin; pWin; pWin=pWin->pNextWin){
|
|
FuncDef *pFunc = pWin->pFunc;
|
|
+ assert( pWin->regAccum );
|
|
sqlite3VdbeAddOp2(v, OP_Null, 0, pWin->regAccum);
|
|
nArg = MAX(nArg, windowArgCount(pWin));
|
|
if( pMWin->regStartRowid==0 ){
|
|
@@ -147777,34 +152381,46 @@
|
|
/*
|
|
** This function is called as part of generating VM programs for RANGE
|
|
** offset PRECEDING/FOLLOWING frame boundaries. Assuming "ASC" order for
|
|
-** the ORDER BY term in the window, it generates code equivalent to:
|
|
+** the ORDER BY term in the window, and that argument op is OP_Ge, it generates
|
|
+** code equivalent to:
|
|
**
|
|
** if( csr1.peerVal + regVal >= csr2.peerVal ) goto lbl;
|
|
**
|
|
-** A special type of arithmetic is used such that if csr.peerVal is not
|
|
-** a numeric type (real or integer), then the result of the addition is
|
|
-** a copy of csr1.peerVal.
|
|
+** The value of parameter op may also be OP_Gt or OP_Le. In these cases the
|
|
+** operator in the above pseudo-code is replaced with ">" or "<=", respectively.
|
|
+**
|
|
+** If the sort-order for the ORDER BY term in the window is DESC, then the
|
|
+** comparison is reversed. Instead of adding regVal to csr1.peerVal, it is
|
|
+** subtracted. And the comparison operator is inverted to - ">=" becomes "<=",
|
|
+** ">" becomes "<", and so on. So, with DESC sort order, if the argument op
|
|
+** is OP_Ge, the generated code is equivalent to:
|
|
+**
|
|
+** if( csr1.peerVal - regVal <= csr2.peerVal ) goto lbl;
|
|
+**
|
|
+** A special type of arithmetic is used such that if csr1.peerVal is not
|
|
+** a numeric type (real or integer), then the result of the addition addition
|
|
+** or subtraction is a a copy of csr1.peerVal.
|
|
*/
|
|
static void windowCodeRangeTest(
|
|
WindowCodeArg *p,
|
|
- int op, /* OP_Ge or OP_Gt */
|
|
- int csr1,
|
|
- int regVal,
|
|
- int csr2,
|
|
- int lbl
|
|
+ int op, /* OP_Ge, OP_Gt, or OP_Le */
|
|
+ int csr1, /* Cursor number for cursor 1 */
|
|
+ int regVal, /* Register containing non-negative number */
|
|
+ int csr2, /* Cursor number for cursor 2 */
|
|
+ int lbl /* Jump destination if condition is true */
|
|
){
|
|
Parse *pParse = p->pParse;
|
|
Vdbe *v = sqlite3GetVdbe(pParse);
|
|
- int reg1 = sqlite3GetTempReg(pParse);
|
|
- int reg2 = sqlite3GetTempReg(pParse);
|
|
- int arith = OP_Add;
|
|
- int addrGe;
|
|
-
|
|
- int regString = ++pParse->nMem;
|
|
+ ExprList *pOrderBy = p->pMWin->pOrderBy; /* ORDER BY clause for window */
|
|
+ int reg1 = sqlite3GetTempReg(pParse); /* Reg. for csr1.peerVal+regVal */
|
|
+ int reg2 = sqlite3GetTempReg(pParse); /* Reg. for csr2.peerVal */
|
|
+ int regString = ++pParse->nMem; /* Reg. for constant value '' */
|
|
+ int arith = OP_Add; /* OP_Add or OP_Subtract */
|
|
+ int addrGe; /* Jump destination */
|
|
|
|
assert( op==OP_Ge || op==OP_Gt || op==OP_Le );
|
|
- assert( p->pMWin->pOrderBy && p->pMWin->pOrderBy->nExpr==1 );
|
|
- if( p->pMWin->pOrderBy->a[0].sortOrder ){
|
|
+ assert( pOrderBy && pOrderBy->nExpr==1 );
|
|
+ if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_DESC ){
|
|
switch( op ){
|
|
case OP_Ge: op = OP_Le; break;
|
|
case OP_Gt: op = OP_Lt; break;
|
|
@@ -147813,27 +152429,95 @@
|
|
arith = OP_Subtract;
|
|
}
|
|
|
|
+ /* Read the peer-value from each cursor into a register */
|
|
windowReadPeerValues(p, csr1, reg1);
|
|
windowReadPeerValues(p, csr2, reg2);
|
|
|
|
- /* Check if the peer value for csr1 value is a text or blob by comparing
|
|
- ** it to the smallest possible string - ''. If it is, jump over the
|
|
- ** OP_Add or OP_Subtract operation and proceed directly to the comparison. */
|
|
+ VdbeModuleComment((v, "CodeRangeTest: if( R%d %s R%d %s R%d ) goto lbl",
|
|
+ reg1, (arith==OP_Add ? "+" : "-"), regVal,
|
|
+ ((op==OP_Ge) ? ">=" : (op==OP_Le) ? "<=" : (op==OP_Gt) ? ">" : "<"), reg2
|
|
+ ));
|
|
+
|
|
+ /* Register reg1 currently contains csr1.peerVal (the peer-value from csr1).
|
|
+ ** This block adds (or subtracts for DESC) the numeric value in regVal
|
|
+ ** from it. Or, if reg1 is not numeric (it is a NULL, a text value or a blob),
|
|
+ ** then leave reg1 as it is. In pseudo-code, this is implemented as:
|
|
+ **
|
|
+ ** if( reg1>='' ) goto addrGe;
|
|
+ ** reg1 = reg1 +/- regVal
|
|
+ ** addrGe:
|
|
+ **
|
|
+ ** Since all strings and blobs are greater-than-or-equal-to an empty string,
|
|
+ ** the add/subtract is skipped for these, as required. If reg1 is a NULL,
|
|
+ ** then the arithmetic is performed, but since adding or subtracting from
|
|
+ ** NULL is always NULL anyway, this case is handled as required too. */
|
|
sqlite3VdbeAddOp4(v, OP_String8, 0, regString, 0, "", P4_STATIC);
|
|
addrGe = sqlite3VdbeAddOp3(v, OP_Ge, regString, 0, reg1);
|
|
VdbeCoverage(v);
|
|
sqlite3VdbeAddOp3(v, arith, regVal, reg1, reg1);
|
|
sqlite3VdbeJumpHere(v, addrGe);
|
|
+
|
|
+ /* If the BIGNULL flag is set for the ORDER BY, then it is required to
|
|
+ ** consider NULL values to be larger than all other values, instead of
|
|
+ ** the usual smaller. The VDBE opcodes OP_Ge and so on do not handle this
|
|
+ ** (and adding that capability causes a performance regression), so
|
|
+ ** instead if the BIGNULL flag is set then cases where either reg1 or
|
|
+ ** reg2 are NULL are handled separately in the following block. The code
|
|
+ ** generated is equivalent to:
|
|
+ **
|
|
+ ** if( reg1 IS NULL ){
|
|
+ ** if( op==OP_Ge ) goto lbl;
|
|
+ ** if( op==OP_Gt && reg2 IS NOT NULL ) goto lbl;
|
|
+ ** if( op==OP_Le && reg2 IS NULL ) goto lbl;
|
|
+ ** }else if( reg2 IS NULL ){
|
|
+ ** if( op==OP_Le ) goto lbl;
|
|
+ ** }
|
|
+ **
|
|
+ ** Additionally, if either reg1 or reg2 are NULL but the jump to lbl is
|
|
+ ** not taken, control jumps over the comparison operator coded below this
|
|
+ ** block. */
|
|
+ if( pOrderBy->a[0].sortFlags & KEYINFO_ORDER_BIGNULL ){
|
|
+ /* This block runs if reg1 contains a NULL. */
|
|
+ int addr = sqlite3VdbeAddOp1(v, OP_NotNull, reg1); VdbeCoverage(v);
|
|
+ switch( op ){
|
|
+ case OP_Ge:
|
|
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, lbl);
|
|
+ break;
|
|
+ case OP_Gt:
|
|
+ sqlite3VdbeAddOp2(v, OP_NotNull, reg2, lbl);
|
|
+ VdbeCoverage(v);
|
|
+ break;
|
|
+ case OP_Le:
|
|
+ sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl);
|
|
+ VdbeCoverage(v);
|
|
+ break;
|
|
+ default: assert( op==OP_Lt ); /* no-op */ break;
|
|
+ }
|
|
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
|
|
+
|
|
+ /* This block runs if reg1 is not NULL, but reg2 is. */
|
|
+ sqlite3VdbeJumpHere(v, addr);
|
|
+ sqlite3VdbeAddOp2(v, OP_IsNull, reg2, lbl); VdbeCoverage(v);
|
|
+ if( op==OP_Gt || op==OP_Ge ){
|
|
+ sqlite3VdbeChangeP2(v, -1, sqlite3VdbeCurrentAddr(v)+1);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ /* Compare registers reg2 and reg1, taking the jump if required. Note that
|
|
+ ** control skips over this test if the BIGNULL flag is set and either
|
|
+ ** reg1 or reg2 contain a NULL value. */
|
|
sqlite3VdbeAddOp3(v, op, reg2, lbl, reg1); VdbeCoverage(v);
|
|
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
|
|
+
|
|
assert( op==OP_Ge || op==OP_Gt || op==OP_Lt || op==OP_Le );
|
|
testcase(op==OP_Ge); VdbeCoverageIf(v, op==OP_Ge);
|
|
testcase(op==OP_Lt); VdbeCoverageIf(v, op==OP_Lt);
|
|
testcase(op==OP_Le); VdbeCoverageIf(v, op==OP_Le);
|
|
testcase(op==OP_Gt); VdbeCoverageIf(v, op==OP_Gt);
|
|
-
|
|
sqlite3ReleaseTempReg(pParse, reg1);
|
|
sqlite3ReleaseTempReg(pParse, reg2);
|
|
+
|
|
+ VdbeModuleComment((v, "CodeRangeTest: end"));
|
|
}
|
|
|
|
/*
|
|
@@ -147853,9 +152537,7 @@
|
|
Window *pMWin = p->pMWin;
|
|
int ret = 0;
|
|
Vdbe *v = p->pVdbe;
|
|
- int addrIf = 0;
|
|
int addrContinue = 0;
|
|
- int addrGoto = 0;
|
|
int bPeer = (pMWin->eFrmType!=TK_ROWS);
|
|
|
|
int lblDone = sqlite3VdbeMakeLabel(pParse);
|
|
@@ -147888,7 +152570,7 @@
|
|
);
|
|
}
|
|
}else{
|
|
- addrIf = sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, 0, 1);
|
|
+ sqlite3VdbeAddOp3(v, OP_IfPos, regCountdown, lblDone, 1);
|
|
VdbeCoverage(v);
|
|
}
|
|
}
|
|
@@ -147897,6 +152579,25 @@
|
|
windowAggFinal(p, 0);
|
|
}
|
|
addrContinue = sqlite3VdbeCurrentAddr(v);
|
|
+
|
|
+ /* If this is a (RANGE BETWEEN a FOLLOWING AND b FOLLOWING) or
|
|
+ ** (RANGE BETWEEN b PRECEDING AND a PRECEDING) frame, ensure the
|
|
+ ** start cursor does not advance past the end cursor within the
|
|
+ ** temporary table. It otherwise might, if (a>b). */
|
|
+ if( pMWin->eStart==pMWin->eEnd && regCountdown
|
|
+ && pMWin->eFrmType==TK_RANGE && op==WINDOW_AGGINVERSE
|
|
+ ){
|
|
+ int regRowid1 = sqlite3GetTempReg(pParse);
|
|
+ int regRowid2 = sqlite3GetTempReg(pParse);
|
|
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->start.csr, regRowid1);
|
|
+ sqlite3VdbeAddOp2(v, OP_Rowid, p->end.csr, regRowid2);
|
|
+ sqlite3VdbeAddOp3(v, OP_Ge, regRowid2, lblDone, regRowid1);
|
|
+ VdbeCoverage(v);
|
|
+ sqlite3ReleaseTempReg(pParse, regRowid1);
|
|
+ sqlite3ReleaseTempReg(pParse, regRowid2);
|
|
+ assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_FOLLOWING );
|
|
+ }
|
|
+
|
|
switch( op ){
|
|
case WINDOW_RETURN_ROW:
|
|
csr = p->current.csr;
|
|
@@ -147911,7 +152612,7 @@
|
|
assert( pMWin->regEndRowid );
|
|
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regStartRowid, 1);
|
|
}else{
|
|
- windowAggStep(pParse, pMWin, csr, 1, p->regArg);
|
|
+ windowAggStep(p, pMWin, csr, 1, p->regArg);
|
|
}
|
|
break;
|
|
|
|
@@ -147923,7 +152624,7 @@
|
|
assert( pMWin->regEndRowid );
|
|
sqlite3VdbeAddOp2(v, OP_AddImm, pMWin->regEndRowid, 1);
|
|
}else{
|
|
- windowAggStep(pParse, pMWin, csr, 0, p->regArg);
|
|
+ windowAggStep(p, pMWin, csr, 0, p->regArg);
|
|
}
|
|
break;
|
|
}
|
|
@@ -147941,7 +152642,7 @@
|
|
sqlite3VdbeAddOp2(v, OP_Next, csr, sqlite3VdbeCurrentAddr(v)+1+bPeer);
|
|
VdbeCoverage(v);
|
|
if( bPeer ){
|
|
- addrGoto = sqlite3VdbeAddOp0(v, OP_Goto);
|
|
+ sqlite3VdbeAddOp2(v, OP_Goto, 0, lblDone);
|
|
}
|
|
}
|
|
|
|
@@ -147957,8 +152658,6 @@
|
|
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNextRange);
|
|
}
|
|
sqlite3VdbeResolveLabel(v, lblDone);
|
|
- if( addrGoto ) sqlite3VdbeJumpHere(v, addrGoto);
|
|
- if( addrIf ) sqlite3VdbeJumpHere(v, addrIf);
|
|
return ret;
|
|
}
|
|
|
|
@@ -147974,6 +152673,7 @@
|
|
pNew = sqlite3DbMallocZero(db, sizeof(Window));
|
|
if( pNew ){
|
|
pNew->zName = sqlite3DbStrDup(db, p->zName);
|
|
+ pNew->zBase = sqlite3DbStrDup(db, p->zBase);
|
|
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
|
|
pNew->pFunc = p->pFunc;
|
|
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
|
|
@@ -147982,9 +152682,15 @@
|
|
pNew->eEnd = p->eEnd;
|
|
pNew->eStart = p->eStart;
|
|
pNew->eExclude = p->eExclude;
|
|
+ pNew->regResult = p->regResult;
|
|
+ pNew->regAccum = p->regAccum;
|
|
+ pNew->iArgCol = p->iArgCol;
|
|
+ pNew->iEphCsr = p->iEphCsr;
|
|
+ pNew->bExprArgs = p->bExprArgs;
|
|
pNew->pStart = sqlite3ExprDup(db, p->pStart, 0);
|
|
pNew->pEnd = sqlite3ExprDup(db, p->pEnd, 0);
|
|
pNew->pOwner = pOwner;
|
|
+ pNew->bImplicitFrame = p->bImplicitFrame;
|
|
}
|
|
}
|
|
return pNew;
|
|
@@ -148308,7 +153014,7 @@
|
|
** regEnd = <expr2>
|
|
** regStart = <expr1>
|
|
** }else{
|
|
-** if( (csrEnd.key + regEnd) <= csrCurrent.key ){
|
|
+** while( (csrEnd.key + regEnd) <= csrCurrent.key ){
|
|
** AGGSTEP
|
|
** }
|
|
** while( (csrStart.key + regStart) < csrCurrent.key ){
|
|
@@ -148381,8 +153087,6 @@
|
|
int addrGosubFlush = 0; /* Address of OP_Gosub to flush: */
|
|
int addrInteger = 0; /* Address of OP_Integer */
|
|
int addrEmpty; /* Address of OP_Rewind in flush: */
|
|
- int regStart = 0; /* Value of <expr> PRECEDING */
|
|
- int regEnd = 0; /* Value of <expr> FOLLOWING */
|
|
int regNew; /* Array of registers holding new input row */
|
|
int regRecord; /* regNew array in record form */
|
|
int regRowid; /* Rowid for regRecord in eph table */
|
|
@@ -148391,6 +153095,8 @@
|
|
int regFlushPart = 0; /* Register for "Gosub flush_partition" */
|
|
WindowCodeArg s; /* Context object for sub-routines */
|
|
int lblWhereEnd; /* Label just before sqlite3WhereEnd() code */
|
|
+ int regStart = 0; /* Value of <expr> PRECEDING */
|
|
+ int regEnd = 0; /* Value of <expr> FOLLOWING */
|
|
|
|
assert( pMWin->eStart==TK_PRECEDING || pMWin->eStart==TK_CURRENT
|
|
|| pMWin->eStart==TK_FOLLOWING || pMWin->eStart==TK_UNBOUNDED
|
|
@@ -148521,14 +153227,14 @@
|
|
|
|
if( regStart ){
|
|
sqlite3ExprCode(pParse, pMWin->pStart, regStart);
|
|
- windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE ? 3 : 0));
|
|
+ windowCheckValue(pParse, regStart, 0 + (pMWin->eFrmType==TK_RANGE?3:0));
|
|
}
|
|
if( regEnd ){
|
|
sqlite3ExprCode(pParse, pMWin->pEnd, regEnd);
|
|
- windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE ? 3 : 0));
|
|
+ windowCheckValue(pParse, regEnd, 1 + (pMWin->eFrmType==TK_RANGE?3:0));
|
|
}
|
|
|
|
- if( pMWin->eStart==pMWin->eEnd && regStart ){
|
|
+ if( pMWin->eFrmType!=TK_RANGE && pMWin->eStart==pMWin->eEnd && regStart ){
|
|
int op = ((pMWin->eStart==TK_FOLLOWING) ? OP_Ge : OP_Le);
|
|
int addrGe = sqlite3VdbeAddOp3(v, op, regStart, 0, regEnd);
|
|
VdbeCoverageNeverNullIf(v, op==OP_Ge); /* NeverNull because bound <expr> */
|
|
@@ -148777,8 +153483,9 @@
|
|
** shared across database connections.
|
|
*/
|
|
static void disableLookaside(Parse *pParse){
|
|
+ sqlite3 *db = pParse->db;
|
|
pParse->disableLookaside++;
|
|
- pParse->db->lookaside.bDisable++;
|
|
+ DisableLookaside;
|
|
}
|
|
|
|
|
|
@@ -148788,6 +153495,7 @@
|
|
** SQLITE_LIMIT_COMPOUND_SELECT.
|
|
*/
|
|
static void parserDoubleLinkSelect(Parse *pParse, Select *p){
|
|
+ assert( p!=0 );
|
|
if( p->pPrior ){
|
|
Select *pNext = 0, *pLoop;
|
|
int mxSelect, cnt = 0;
|
|
@@ -148814,8 +153522,9 @@
|
|
if( p ){
|
|
/* memset(p, 0, sizeof(Expr)); */
|
|
p->op = (u8)op;
|
|
- p->affinity = 0;
|
|
+ p->affExpr = 0;
|
|
p->flags = EP_Leaf;
|
|
+ ExprClearVVAProperties(p);
|
|
p->iAgg = -1;
|
|
p->pLeft = p->pRight = 0;
|
|
p->x.pList = 0;
|
|
@@ -148941,28 +153650,28 @@
|
|
#endif
|
|
/************* Begin control #defines *****************************************/
|
|
#define YYCODETYPE unsigned short int
|
|
-#define YYNOCODE 302
|
|
+#define YYNOCODE 310
|
|
#define YYACTIONTYPE unsigned short int
|
|
-#define YYWILDCARD 95
|
|
+#define YYWILDCARD 100
|
|
#define sqlite3ParserTOKENTYPE Token
|
|
typedef union {
|
|
int yyinit;
|
|
sqlite3ParserTOKENTYPE yy0;
|
|
- TriggerStep* yy11;
|
|
- IdList* yy76;
|
|
- ExprList* yy94;
|
|
- Upsert* yy95;
|
|
- int yy100;
|
|
- Expr* yy102;
|
|
- struct {int value; int mask;} yy199;
|
|
- u8 yy218;
|
|
- With* yy243;
|
|
- struct TrigEvent yy298;
|
|
- Window* yy379;
|
|
- struct FrameBound yy389;
|
|
- Select* yy391;
|
|
- SrcList* yy407;
|
|
- const char* yy528;
|
|
+ SrcList* yy47;
|
|
+ u8 yy58;
|
|
+ struct FrameBound yy77;
|
|
+ With* yy131;
|
|
+ int yy192;
|
|
+ Expr* yy202;
|
|
+ struct {int value; int mask;} yy207;
|
|
+ struct TrigEvent yy230;
|
|
+ ExprList* yy242;
|
|
+ Window* yy303;
|
|
+ Upsert* yy318;
|
|
+ const char* yy436;
|
|
+ TriggerStep* yy447;
|
|
+ Select* yy539;
|
|
+ IdList* yy600;
|
|
} YYMINORTYPE;
|
|
#ifndef YYSTACKDEPTH
|
|
#define YYSTACKDEPTH 100
|
|
@@ -148978,17 +153687,18 @@
|
|
#define sqlite3ParserCTX_FETCH Parse *pParse=yypParser->pParse;
|
|
#define sqlite3ParserCTX_STORE yypParser->pParse=pParse;
|
|
#define YYFALLBACK 1
|
|
-#define YYNSTATE 540
|
|
-#define YYNRULE 376
|
|
-#define YYNTOKEN 176
|
|
-#define YY_MAX_SHIFT 539
|
|
-#define YY_MIN_SHIFTREDUCE 783
|
|
-#define YY_MAX_SHIFTREDUCE 1158
|
|
-#define YY_ERROR_ACTION 1159
|
|
-#define YY_ACCEPT_ACTION 1160
|
|
-#define YY_NO_ACTION 1161
|
|
-#define YY_MIN_REDUCE 1162
|
|
-#define YY_MAX_REDUCE 1537
|
|
+#define YYNSTATE 551
|
|
+#define YYNRULE 385
|
|
+#define YYNRULE_WITH_ACTION 325
|
|
+#define YYNTOKEN 181
|
|
+#define YY_MAX_SHIFT 550
|
|
+#define YY_MIN_SHIFTREDUCE 801
|
|
+#define YY_MAX_SHIFTREDUCE 1185
|
|
+#define YY_ERROR_ACTION 1186
|
|
+#define YY_ACCEPT_ACTION 1187
|
|
+#define YY_NO_ACTION 1188
|
|
+#define YY_MIN_REDUCE 1189
|
|
+#define YY_MAX_REDUCE 1573
|
|
/************* End control #defines *******************************************/
|
|
#define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
|
|
|
|
@@ -149055,601 +153765,583 @@
|
|
** yy_default[] Default action for each state.
|
|
**
|
|
*********** Begin parsing tables **********************************************/
|
|
-#define YY_ACTTAB_COUNT (2142)
|
|
+#define YY_ACTTAB_COUNT (1958)
|
|
static const YYACTIONTYPE yy_action[] = {
|
|
- /* 0 */ 112, 109, 209, 112, 109, 209, 1160, 1, 1, 539,
|
|
- /* 10 */ 2, 1164, 490, 1193, 1293, 534, 289, 1196, 134, 383,
|
|
- /* 20 */ 1485, 1428, 1164, 1229, 1208, 1242, 1195, 289, 491, 134,
|
|
- /* 30 */ 373, 915, 1229, 443, 16, 16, 1242, 70, 70, 916,
|
|
- /* 40 */ 242, 1292, 296, 119, 120, 110, 1136, 1136, 981, 984,
|
|
- /* 50 */ 974, 974, 117, 117, 118, 118, 118, 118, 264, 264,
|
|
- /* 60 */ 190, 264, 264, 264, 264, 112, 109, 209, 362, 264,
|
|
- /* 70 */ 264, 531, 376, 497, 531, 1134, 531, 1501, 239, 206,
|
|
- /* 80 */ 338, 9, 531, 242, 219, 1203, 118, 118, 118, 118,
|
|
- /* 90 */ 111, 439, 112, 109, 209, 219, 116, 116, 116, 116,
|
|
- /* 100 */ 115, 115, 114, 114, 114, 113, 414, 115, 115, 114,
|
|
- /* 110 */ 114, 114, 113, 414, 418, 12, 383, 400, 1134, 114,
|
|
- /* 120 */ 114, 114, 113, 414, 1115, 418, 1134, 1392, 116, 116,
|
|
- /* 130 */ 116, 116, 115, 115, 114, 114, 114, 113, 414, 961,
|
|
- /* 140 */ 119, 120, 110, 1136, 1136, 981, 984, 974, 974, 117,
|
|
- /* 150 */ 117, 118, 118, 118, 118, 952, 534, 414, 941, 951,
|
|
- /* 160 */ 1481, 539, 2, 1164, 1505, 534, 160, 175, 289, 1134,
|
|
- /* 170 */ 134, 434, 312, 297, 1115, 1116, 1117, 1242, 70, 70,
|
|
- /* 180 */ 1089, 338, 1089, 118, 118, 118, 118, 42, 42, 448,
|
|
- /* 190 */ 951, 951, 953, 116, 116, 116, 116, 115, 115, 114,
|
|
- /* 200 */ 114, 114, 113, 414, 1115, 311, 264, 264, 82, 441,
|
|
- /* 210 */ 264, 264, 190, 383, 284, 12, 288, 525, 407, 531,
|
|
- /* 220 */ 96, 159, 458, 531, 371, 116, 116, 116, 116, 115,
|
|
- /* 230 */ 115, 114, 114, 114, 113, 414, 219, 119, 120, 110,
|
|
- /* 240 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118,
|
|
- /* 250 */ 118, 118, 511, 1477, 1115, 1116, 1117, 113, 414, 534,
|
|
- /* 260 */ 528, 528, 528, 121, 534, 1427, 418, 116, 116, 116,
|
|
- /* 270 */ 116, 115, 115, 114, 114, 114, 113, 414, 1464, 351,
|
|
- /* 280 */ 270, 42, 42, 383, 187, 1115, 70, 70, 533, 433,
|
|
- /* 290 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113,
|
|
- /* 300 */ 414, 534, 1339, 405, 159, 411, 410, 119, 120, 110,
|
|
- /* 310 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118,
|
|
- /* 320 */ 118, 118, 285, 42, 42, 349, 411, 410, 514, 479,
|
|
- /* 330 */ 1458, 79, 1084, 6, 1140, 1115, 1116, 1117, 480, 1142,
|
|
- /* 340 */ 501, 1115, 1084, 123, 238, 1084, 136, 1141, 1234, 1234,
|
|
- /* 350 */ 1143, 383, 1143, 1115, 167, 426, 80, 447, 512, 1451,
|
|
- /* 360 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113,
|
|
- /* 370 */ 414, 1143, 1466, 1143, 350, 119, 120, 110, 1136, 1136,
|
|
- /* 380 */ 981, 984, 974, 974, 117, 117, 118, 118, 118, 118,
|
|
- /* 390 */ 402, 1115, 1116, 1117, 500, 534, 250, 267, 336, 474,
|
|
- /* 400 */ 331, 473, 236, 1115, 1116, 1117, 231, 1115, 329, 471,
|
|
- /* 410 */ 468, 467, 509, 1458, 1464, 505, 6, 70, 70, 466,
|
|
- /* 420 */ 181, 380, 379, 534, 971, 971, 982, 985, 116, 116,
|
|
- /* 430 */ 116, 116, 115, 115, 114, 114, 114, 113, 414, 1115,
|
|
- /* 440 */ 412, 412, 412, 496, 1115, 69, 69, 235, 383, 288,
|
|
- /* 450 */ 525, 273, 326, 516, 337, 458, 1084, 1115, 1116, 1117,
|
|
- /* 460 */ 1232, 1232, 492, 160, 508, 441, 1084, 1067, 1531, 1084,
|
|
- /* 470 */ 207, 1531, 119, 120, 110, 1136, 1136, 981, 984, 974,
|
|
- /* 480 */ 974, 117, 117, 118, 118, 118, 118, 881, 534, 1115,
|
|
- /* 490 */ 1116, 1117, 975, 534, 1115, 1116, 1117, 534, 421, 534,
|
|
- /* 500 */ 141, 534, 176, 356, 517, 1119, 32, 511, 482, 388,
|
|
- /* 510 */ 70, 70, 818, 288, 525, 70, 70, 441, 499, 50,
|
|
- /* 520 */ 50, 70, 70, 70, 70, 116, 116, 116, 116, 115,
|
|
- /* 530 */ 115, 114, 114, 114, 113, 414, 274, 264, 264, 1115,
|
|
- /* 540 */ 1065, 264, 264, 1115, 355, 383, 409, 961, 1439, 822,
|
|
- /* 550 */ 531, 516, 190, 419, 531, 483, 1119, 516, 337, 516,
|
|
- /* 560 */ 518, 1115, 818, 952, 382, 458, 515, 951, 481, 119,
|
|
- /* 570 */ 120, 110, 1136, 1136, 981, 984, 974, 974, 117, 117,
|
|
- /* 580 */ 118, 118, 118, 118, 1338, 278, 1045, 278, 275, 1115,
|
|
- /* 590 */ 1116, 1117, 259, 1115, 1116, 1117, 534, 5, 951, 951,
|
|
- /* 600 */ 953, 1046, 231, 3, 143, 471, 468, 467, 1391, 463,
|
|
- /* 610 */ 1115, 1115, 1116, 1117, 1452, 466, 1047, 836, 70, 70,
|
|
- /* 620 */ 480, 534, 116, 116, 116, 116, 115, 115, 114, 114,
|
|
- /* 630 */ 114, 113, 414, 95, 1115, 287, 235, 856, 902, 420,
|
|
- /* 640 */ 1115, 534, 383, 13, 13, 381, 815, 857, 472, 112,
|
|
- /* 650 */ 109, 209, 1115, 337, 413, 309, 837, 394, 1436, 534,
|
|
- /* 660 */ 1115, 1116, 1117, 54, 54, 291, 119, 120, 110, 1136,
|
|
- /* 670 */ 1136, 981, 984, 974, 974, 117, 117, 118, 118, 118,
|
|
- /* 680 */ 118, 13, 13, 1084, 1115, 1116, 1117, 901, 264, 264,
|
|
- /* 690 */ 1115, 1116, 1117, 1084, 292, 399, 1084, 800, 388, 140,
|
|
- /* 700 */ 295, 531, 1115, 1116, 1117, 403, 447, 532, 534, 870,
|
|
- /* 710 */ 870, 534, 1240, 534, 329, 534, 1185, 389, 534, 116,
|
|
- /* 720 */ 116, 116, 116, 115, 115, 114, 114, 114, 113, 414,
|
|
- /* 730 */ 13, 13, 1024, 13, 13, 13, 13, 13, 13, 383,
|
|
- /* 740 */ 13, 13, 424, 1100, 401, 264, 264, 277, 160, 184,
|
|
- /* 750 */ 1182, 185, 1533, 369, 513, 484, 432, 487, 531, 424,
|
|
- /* 760 */ 423, 1397, 941, 119, 120, 110, 1136, 1136, 981, 984,
|
|
- /* 770 */ 974, 974, 117, 117, 118, 118, 118, 118, 1397, 1399,
|
|
- /* 780 */ 425, 519, 392, 264, 264, 1029, 1029, 455, 264, 264,
|
|
- /* 790 */ 264, 264, 1004, 304, 261, 1278, 531, 900, 288, 525,
|
|
- /* 800 */ 310, 531, 493, 531, 1067, 1532, 458, 387, 1532, 311,
|
|
- /* 810 */ 429, 299, 534, 107, 264, 264, 116, 116, 116, 116,
|
|
- /* 820 */ 115, 115, 114, 114, 114, 113, 414, 531, 424, 1384,
|
|
- /* 830 */ 507, 258, 258, 1246, 55, 55, 383, 1277, 265, 265,
|
|
- /* 840 */ 962, 324, 434, 312, 531, 531, 506, 1397, 1026, 1241,
|
|
- /* 850 */ 298, 531, 1026, 445, 301, 1095, 303, 534, 368, 1156,
|
|
- /* 860 */ 119, 120, 110, 1136, 1136, 981, 984, 974, 974, 117,
|
|
- /* 870 */ 117, 118, 118, 118, 118, 1045, 534, 1065, 534, 15,
|
|
- /* 880 */ 15, 1084, 208, 1324, 453, 452, 534, 1324, 534, 449,
|
|
- /* 890 */ 1046, 1084, 494, 458, 1084, 234, 233, 232, 44, 44,
|
|
- /* 900 */ 56, 56, 319, 1095, 322, 1047, 534, 900, 57, 57,
|
|
- /* 910 */ 58, 58, 534, 116, 116, 116, 116, 115, 115, 114,
|
|
- /* 920 */ 114, 114, 113, 414, 534, 514, 522, 534, 59, 59,
|
|
- /* 930 */ 302, 1157, 534, 383, 60, 60, 1237, 946, 788, 789,
|
|
- /* 940 */ 790, 1459, 1456, 446, 6, 6, 61, 61, 1212, 45,
|
|
- /* 950 */ 45, 534, 396, 383, 46, 46, 397, 119, 120, 110,
|
|
- /* 960 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118,
|
|
- /* 970 */ 118, 118, 428, 48, 48, 534, 392, 119, 120, 110,
|
|
- /* 980 */ 1136, 1136, 981, 984, 974, 974, 117, 117, 118, 118,
|
|
- /* 990 */ 118, 118, 1324, 368, 1066, 447, 825, 49, 49, 534,
|
|
- /* 1000 */ 458, 357, 534, 353, 534, 138, 534, 337, 1478, 478,
|
|
- /* 1010 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113,
|
|
- /* 1020 */ 414, 62, 62, 392, 63, 63, 64, 64, 14, 14,
|
|
- /* 1030 */ 116, 116, 116, 116, 115, 115, 114, 114, 114, 113,
|
|
- /* 1040 */ 414, 534, 810, 317, 271, 534, 1457, 825, 534, 6,
|
|
- /* 1050 */ 534, 1324, 534, 142, 534, 1442, 534, 212, 534, 1324,
|
|
- /* 1060 */ 534, 398, 305, 65, 65, 534, 1157, 125, 125, 476,
|
|
- /* 1070 */ 66, 66, 51, 51, 67, 67, 68, 68, 52, 52,
|
|
- /* 1080 */ 147, 147, 148, 148, 534, 98, 534, 75, 75, 276,
|
|
- /* 1090 */ 534, 272, 534, 810, 534, 876, 534, 527, 389, 534,
|
|
- /* 1100 */ 875, 534, 1151, 202, 534, 383, 53, 53, 71, 71,
|
|
- /* 1110 */ 288, 525, 126, 126, 72, 72, 127, 127, 128, 128,
|
|
- /* 1120 */ 454, 124, 124, 146, 146, 383, 145, 145, 408, 119,
|
|
- /* 1130 */ 120, 110, 1136, 1136, 981, 984, 974, 974, 117, 117,
|
|
- /* 1140 */ 118, 118, 118, 118, 534, 900, 534, 95, 534, 119,
|
|
- /* 1150 */ 120, 110, 1136, 1136, 981, 984, 974, 974, 117, 117,
|
|
- /* 1160 */ 118, 118, 118, 118, 390, 161, 132, 132, 131, 131,
|
|
- /* 1170 */ 129, 129, 534, 915, 534, 1455, 534, 1454, 6, 1416,
|
|
- /* 1180 */ 6, 916, 116, 116, 116, 116, 115, 115, 114, 114,
|
|
- /* 1190 */ 114, 113, 414, 1415, 130, 130, 74, 74, 76, 76,
|
|
- /* 1200 */ 534, 30, 116, 116, 116, 116, 115, 115, 114, 114,
|
|
- /* 1210 */ 114, 113, 414, 534, 263, 206, 534, 1133, 1504, 93,
|
|
- /* 1220 */ 876, 845, 73, 73, 102, 875, 100, 139, 17, 38,
|
|
- /* 1230 */ 208, 1062, 31, 450, 370, 43, 43, 101, 47, 47,
|
|
- /* 1240 */ 827, 216, 436, 308, 943, 440, 95, 241, 241, 442,
|
|
- /* 1250 */ 313, 464, 241, 95, 237, 900, 327, 383, 266, 95,
|
|
- /* 1260 */ 835, 834, 193, 335, 938, 314, 1011, 435, 842, 843,
|
|
- /* 1270 */ 955, 1007, 909, 334, 237, 241, 873, 383, 1023, 107,
|
|
- /* 1280 */ 1023, 119, 120, 110, 1136, 1136, 981, 984, 974, 974,
|
|
- /* 1290 */ 117, 117, 118, 118, 118, 118, 1022, 808, 1022, 1274,
|
|
- /* 1300 */ 137, 119, 108, 110, 1136, 1136, 981, 984, 974, 974,
|
|
- /* 1310 */ 117, 117, 118, 118, 118, 118, 874, 1011, 318, 107,
|
|
- /* 1320 */ 321, 955, 323, 325, 1225, 1211, 197, 1210, 1209, 330,
|
|
- /* 1330 */ 339, 1265, 340, 283, 116, 116, 116, 116, 115, 115,
|
|
- /* 1340 */ 114, 114, 114, 113, 414, 1286, 1323, 1261, 1471, 1272,
|
|
- /* 1350 */ 520, 218, 521, 1329, 116, 116, 116, 116, 115, 115,
|
|
- /* 1360 */ 114, 114, 114, 113, 414, 1192, 1184, 1173, 1172, 1174,
|
|
- /* 1370 */ 1494, 1488, 459, 256, 383, 1258, 342, 199, 367, 344,
|
|
- /* 1380 */ 211, 195, 307, 444, 11, 346, 469, 333, 1308, 1316,
|
|
- /* 1390 */ 375, 427, 203, 360, 383, 1388, 188, 1387, 189, 120,
|
|
- /* 1400 */ 110, 1136, 1136, 981, 984, 974, 974, 117, 117, 118,
|
|
- /* 1410 */ 118, 118, 118, 1208, 1151, 300, 348, 1491, 245, 1148,
|
|
- /* 1420 */ 110, 1136, 1136, 981, 984, 974, 974, 117, 117, 118,
|
|
- /* 1430 */ 118, 118, 118, 198, 1435, 1433, 524, 78, 391, 163,
|
|
- /* 1440 */ 82, 1393, 438, 173, 81, 105, 526, 1313, 4, 35,
|
|
- /* 1450 */ 157, 116, 116, 116, 116, 115, 115, 114, 114, 114,
|
|
- /* 1460 */ 113, 414, 529, 165, 93, 430, 1305, 168, 169, 431,
|
|
- /* 1470 */ 462, 116, 116, 116, 116, 115, 115, 114, 114, 114,
|
|
- /* 1480 */ 113, 414, 170, 171, 221, 415, 372, 437, 1319, 177,
|
|
- /* 1490 */ 374, 36, 451, 225, 1382, 87, 457, 523, 257, 1404,
|
|
- /* 1500 */ 316, 105, 526, 227, 4, 182, 460, 160, 320, 228,
|
|
- /* 1510 */ 377, 1175, 475, 229, 1228, 404, 1227, 1226, 529, 827,
|
|
- /* 1520 */ 961, 1219, 378, 1200, 1199, 406, 103, 103, 1218, 332,
|
|
- /* 1530 */ 8, 281, 1198, 104, 1503, 415, 536, 535, 486, 282,
|
|
- /* 1540 */ 951, 415, 489, 495, 92, 244, 1269, 341, 243, 122,
|
|
- /* 1550 */ 1270, 343, 514, 523, 1268, 1462, 10, 288, 525, 345,
|
|
- /* 1560 */ 1461, 354, 99, 352, 503, 94, 1267, 347, 1251, 502,
|
|
- /* 1570 */ 498, 951, 951, 953, 954, 27, 961, 1250, 194, 358,
|
|
- /* 1580 */ 251, 359, 103, 103, 1181, 34, 537, 1110, 252, 104,
|
|
- /* 1590 */ 254, 415, 536, 535, 255, 1368, 951, 1420, 286, 538,
|
|
- /* 1600 */ 1170, 1165, 1421, 135, 1419, 1418, 149, 150, 279, 784,
|
|
- /* 1610 */ 416, 196, 151, 290, 210, 200, 77, 385, 269, 386,
|
|
- /* 1620 */ 133, 162, 935, 1021, 201, 1019, 153, 951, 951, 953,
|
|
- /* 1630 */ 954, 27, 1480, 1104, 417, 164, 217, 268, 859, 166,
|
|
- /* 1640 */ 306, 1035, 366, 366, 365, 253, 363, 220, 172, 797,
|
|
- /* 1650 */ 939, 155, 105, 526, 393, 4, 395, 174, 156, 83,
|
|
- /* 1660 */ 1038, 84, 213, 85, 294, 222, 86, 223, 1034, 529,
|
|
- /* 1670 */ 144, 18, 293, 224, 315, 456, 241, 1027, 1145, 178,
|
|
- /* 1680 */ 226, 179, 37, 799, 334, 461, 230, 465, 470, 838,
|
|
- /* 1690 */ 180, 88, 415, 19, 280, 328, 20, 89, 90, 158,
|
|
- /* 1700 */ 191, 477, 215, 1097, 523, 204, 192, 987, 91, 1070,
|
|
- /* 1710 */ 152, 39, 485, 154, 1071, 503, 40, 488, 205, 260,
|
|
- /* 1720 */ 504, 262, 105, 526, 214, 4, 908, 961, 183, 240,
|
|
- /* 1730 */ 903, 107, 1086, 103, 103, 21, 22, 1088, 23, 529,
|
|
- /* 1740 */ 104, 24, 415, 536, 535, 1090, 1093, 951, 1094, 25,
|
|
- /* 1750 */ 1074, 33, 7, 26, 510, 1002, 247, 186, 384, 95,
|
|
- /* 1760 */ 988, 986, 415, 288, 525, 990, 1044, 246, 1043, 991,
|
|
- /* 1770 */ 28, 41, 530, 956, 523, 809, 106, 29, 951, 951,
|
|
- /* 1780 */ 953, 954, 27, 869, 361, 503, 422, 248, 364, 1105,
|
|
- /* 1790 */ 502, 249, 1161, 1496, 1495, 1161, 1161, 961, 1161, 1161,
|
|
- /* 1800 */ 1161, 1161, 1161, 103, 103, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 1810 */ 104, 1161, 415, 536, 535, 1104, 417, 951, 1161, 268,
|
|
- /* 1820 */ 1161, 1161, 1161, 1161, 366, 366, 365, 253, 363, 1161,
|
|
- /* 1830 */ 1161, 797, 1161, 1161, 1161, 1161, 105, 526, 1161, 4,
|
|
- /* 1840 */ 1161, 1161, 1161, 1161, 213, 1161, 294, 1161, 951, 951,
|
|
- /* 1850 */ 953, 954, 27, 529, 293, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 1860 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 1870 */ 1161, 1161, 1161, 1161, 1161, 1161, 415, 1161, 1161, 1161,
|
|
- /* 1880 */ 1161, 1161, 1161, 1161, 215, 1161, 1161, 1161, 523, 1161,
|
|
- /* 1890 */ 1161, 1161, 152, 1161, 1161, 154, 105, 526, 1161, 4,
|
|
- /* 1900 */ 1161, 1161, 1161, 1161, 1161, 1161, 214, 1161, 1161, 1161,
|
|
- /* 1910 */ 1161, 961, 1161, 529, 1161, 1161, 1161, 103, 103, 880,
|
|
- /* 1920 */ 1161, 1161, 1161, 1161, 104, 1161, 415, 536, 535, 1161,
|
|
- /* 1930 */ 1161, 951, 1161, 1161, 1161, 1161, 415, 1161, 1161, 1161,
|
|
- /* 1940 */ 384, 1161, 1161, 1161, 1161, 288, 525, 1161, 523, 1161,
|
|
- /* 1950 */ 1161, 1161, 1161, 1161, 1161, 1161, 97, 526, 1161, 4,
|
|
- /* 1960 */ 1161, 1161, 951, 951, 953, 954, 27, 1161, 422, 1161,
|
|
- /* 1970 */ 1161, 961, 1161, 529, 1161, 1161, 1161, 103, 103, 1161,
|
|
- /* 1980 */ 1161, 1161, 1161, 1161, 104, 1161, 415, 536, 535, 1161,
|
|
- /* 1990 */ 1161, 951, 268, 1161, 1161, 1161, 415, 366, 366, 365,
|
|
- /* 2000 */ 253, 363, 1161, 1161, 797, 1161, 1161, 1161, 523, 1161,
|
|
- /* 2010 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 213, 1161, 294,
|
|
- /* 2020 */ 1161, 1161, 951, 951, 953, 954, 27, 293, 1161, 1161,
|
|
- /* 2030 */ 1161, 961, 1161, 1161, 1161, 1161, 1161, 103, 103, 1161,
|
|
- /* 2040 */ 1161, 1161, 1161, 1161, 104, 1161, 415, 536, 535, 1161,
|
|
- /* 2050 */ 1161, 951, 1161, 1161, 1161, 1161, 1161, 215, 1161, 1161,
|
|
- /* 2060 */ 1161, 1161, 1161, 1161, 1161, 152, 1161, 1161, 154, 1161,
|
|
- /* 2070 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 214,
|
|
- /* 2080 */ 1161, 1161, 951, 951, 953, 954, 27, 1161, 1161, 1161,
|
|
- /* 2090 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 2100 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 2110 */ 1161, 1161, 1161, 384, 1161, 1161, 1161, 1161, 288, 525,
|
|
- /* 2120 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 2130 */ 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161, 1161,
|
|
- /* 2140 */ 1161, 422,
|
|
+ /* 0 */ 544, 1220, 544, 449, 1258, 544, 1237, 544, 114, 111,
|
|
+ /* 10 */ 211, 544, 1535, 544, 1258, 521, 114, 111, 211, 390,
|
|
+ /* 20 */ 1230, 342, 42, 42, 42, 42, 1223, 42, 42, 71,
|
|
+ /* 30 */ 71, 935, 1222, 71, 71, 71, 71, 1460, 1491, 936,
|
|
+ /* 40 */ 818, 451, 6, 121, 122, 112, 1163, 1163, 1004, 1007,
|
|
+ /* 50 */ 997, 997, 119, 119, 120, 120, 120, 120, 1541, 390,
|
|
+ /* 60 */ 1356, 1515, 550, 2, 1191, 194, 526, 434, 143, 291,
|
|
+ /* 70 */ 526, 136, 526, 369, 261, 502, 272, 383, 1271, 525,
|
|
+ /* 80 */ 501, 491, 164, 121, 122, 112, 1163, 1163, 1004, 1007,
|
|
+ /* 90 */ 997, 997, 119, 119, 120, 120, 120, 120, 1356, 440,
|
|
+ /* 100 */ 1512, 118, 118, 118, 118, 117, 117, 116, 116, 116,
|
|
+ /* 110 */ 115, 422, 266, 266, 266, 266, 1496, 356, 1498, 433,
|
|
+ /* 120 */ 355, 1496, 515, 522, 1483, 541, 1112, 541, 1112, 390,
|
|
+ /* 130 */ 403, 241, 208, 114, 111, 211, 98, 290, 535, 221,
|
|
+ /* 140 */ 1027, 118, 118, 118, 118, 117, 117, 116, 116, 116,
|
|
+ /* 150 */ 115, 422, 1140, 121, 122, 112, 1163, 1163, 1004, 1007,
|
|
+ /* 160 */ 997, 997, 119, 119, 120, 120, 120, 120, 404, 426,
|
|
+ /* 170 */ 117, 117, 116, 116, 116, 115, 422, 1416, 466, 123,
|
|
+ /* 180 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
|
|
+ /* 190 */ 422, 116, 116, 116, 115, 422, 538, 538, 538, 390,
|
|
+ /* 200 */ 503, 120, 120, 120, 120, 113, 1049, 1140, 1141, 1142,
|
|
+ /* 210 */ 1049, 118, 118, 118, 118, 117, 117, 116, 116, 116,
|
|
+ /* 220 */ 115, 422, 1459, 121, 122, 112, 1163, 1163, 1004, 1007,
|
|
+ /* 230 */ 997, 997, 119, 119, 120, 120, 120, 120, 390, 442,
|
|
+ /* 240 */ 314, 83, 461, 81, 357, 380, 1140, 80, 118, 118,
|
|
+ /* 250 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 179,
|
|
+ /* 260 */ 432, 422, 121, 122, 112, 1163, 1163, 1004, 1007, 997,
|
|
+ /* 270 */ 997, 119, 119, 120, 120, 120, 120, 432, 431, 266,
|
|
+ /* 280 */ 266, 118, 118, 118, 118, 117, 117, 116, 116, 116,
|
|
+ /* 290 */ 115, 422, 541, 1107, 901, 504, 1140, 114, 111, 211,
|
|
+ /* 300 */ 1429, 1140, 1141, 1142, 206, 489, 1107, 390, 447, 1107,
|
|
+ /* 310 */ 543, 328, 120, 120, 120, 120, 298, 1429, 1431, 17,
|
|
+ /* 320 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
|
|
+ /* 330 */ 422, 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997,
|
|
+ /* 340 */ 119, 119, 120, 120, 120, 120, 390, 1356, 432, 1140,
|
|
+ /* 350 */ 480, 1140, 1141, 1142, 994, 994, 1005, 1008, 443, 118,
|
|
+ /* 360 */ 118, 118, 118, 117, 117, 116, 116, 116, 115, 422,
|
|
+ /* 370 */ 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
|
|
+ /* 380 */ 119, 120, 120, 120, 120, 1052, 1052, 463, 1429, 118,
|
|
+ /* 390 */ 118, 118, 118, 117, 117, 116, 116, 116, 115, 422,
|
|
+ /* 400 */ 1140, 449, 544, 1424, 1140, 1141, 1142, 233, 964, 1140,
|
|
+ /* 410 */ 479, 476, 475, 171, 358, 390, 164, 405, 412, 840,
|
|
+ /* 420 */ 474, 164, 185, 332, 71, 71, 1241, 998, 118, 118,
|
|
+ /* 430 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 121,
|
|
+ /* 440 */ 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119, 119,
|
|
+ /* 450 */ 120, 120, 120, 120, 390, 1140, 1141, 1142, 833, 12,
|
|
+ /* 460 */ 313, 507, 163, 354, 1140, 1141, 1142, 114, 111, 211,
|
|
+ /* 470 */ 506, 290, 535, 544, 276, 180, 290, 535, 121, 122,
|
|
+ /* 480 */ 112, 1163, 1163, 1004, 1007, 997, 997, 119, 119, 120,
|
|
+ /* 490 */ 120, 120, 120, 343, 482, 71, 71, 118, 118, 118,
|
|
+ /* 500 */ 118, 117, 117, 116, 116, 116, 115, 422, 1140, 209,
|
|
+ /* 510 */ 409, 521, 1140, 1107, 1569, 376, 252, 269, 340, 485,
|
|
+ /* 520 */ 335, 484, 238, 390, 511, 362, 1107, 1125, 331, 1107,
|
|
+ /* 530 */ 191, 407, 286, 32, 455, 441, 118, 118, 118, 118,
|
|
+ /* 540 */ 117, 117, 116, 116, 116, 115, 422, 121, 122, 112,
|
|
+ /* 550 */ 1163, 1163, 1004, 1007, 997, 997, 119, 119, 120, 120,
|
|
+ /* 560 */ 120, 120, 390, 1140, 1141, 1142, 985, 1140, 1141, 1142,
|
|
+ /* 570 */ 1140, 233, 490, 1490, 479, 476, 475, 6, 163, 544,
|
|
+ /* 580 */ 510, 544, 115, 422, 474, 5, 121, 122, 112, 1163,
|
|
+ /* 590 */ 1163, 1004, 1007, 997, 997, 119, 119, 120, 120, 120,
|
|
+ /* 600 */ 120, 13, 13, 13, 13, 118, 118, 118, 118, 117,
|
|
+ /* 610 */ 117, 116, 116, 116, 115, 422, 401, 500, 406, 544,
|
|
+ /* 620 */ 1484, 542, 1140, 890, 890, 1140, 1141, 1142, 1471, 1140,
|
|
+ /* 630 */ 275, 390, 806, 807, 808, 969, 420, 420, 420, 16,
|
|
+ /* 640 */ 16, 55, 55, 1240, 118, 118, 118, 118, 117, 117,
|
|
+ /* 650 */ 116, 116, 116, 115, 422, 121, 122, 112, 1163, 1163,
|
|
+ /* 660 */ 1004, 1007, 997, 997, 119, 119, 120, 120, 120, 120,
|
|
+ /* 670 */ 390, 1187, 1, 1, 550, 2, 1191, 1140, 1141, 1142,
|
|
+ /* 680 */ 194, 291, 896, 136, 1140, 1141, 1142, 895, 519, 1490,
|
|
+ /* 690 */ 1271, 3, 378, 6, 121, 122, 112, 1163, 1163, 1004,
|
|
+ /* 700 */ 1007, 997, 997, 119, 119, 120, 120, 120, 120, 856,
|
|
+ /* 710 */ 544, 922, 544, 118, 118, 118, 118, 117, 117, 116,
|
|
+ /* 720 */ 116, 116, 115, 422, 266, 266, 1090, 1567, 1140, 549,
|
|
+ /* 730 */ 1567, 1191, 13, 13, 13, 13, 291, 541, 136, 390,
|
|
+ /* 740 */ 483, 419, 418, 964, 342, 1271, 466, 408, 857, 279,
|
|
+ /* 750 */ 140, 221, 118, 118, 118, 118, 117, 117, 116, 116,
|
|
+ /* 760 */ 116, 115, 422, 121, 122, 112, 1163, 1163, 1004, 1007,
|
|
+ /* 770 */ 997, 997, 119, 119, 120, 120, 120, 120, 544, 266,
|
|
+ /* 780 */ 266, 426, 390, 1140, 1141, 1142, 1170, 828, 1170, 466,
|
|
+ /* 790 */ 429, 145, 541, 1144, 399, 313, 437, 301, 836, 1488,
|
|
+ /* 800 */ 71, 71, 410, 6, 1088, 471, 221, 100, 112, 1163,
|
|
+ /* 810 */ 1163, 1004, 1007, 997, 997, 119, 119, 120, 120, 120,
|
|
+ /* 820 */ 120, 118, 118, 118, 118, 117, 117, 116, 116, 116,
|
|
+ /* 830 */ 115, 422, 237, 1423, 544, 449, 426, 287, 984, 544,
|
|
+ /* 840 */ 236, 235, 234, 828, 97, 527, 427, 1263, 1263, 1144,
|
|
+ /* 850 */ 492, 306, 428, 836, 975, 544, 71, 71, 974, 1239,
|
|
+ /* 860 */ 544, 51, 51, 300, 118, 118, 118, 118, 117, 117,
|
|
+ /* 870 */ 116, 116, 116, 115, 422, 194, 103, 70, 70, 266,
|
|
+ /* 880 */ 266, 544, 71, 71, 266, 266, 30, 389, 342, 974,
|
|
+ /* 890 */ 974, 976, 541, 526, 1107, 326, 390, 541, 493, 395,
|
|
+ /* 900 */ 1468, 195, 528, 13, 13, 1356, 240, 1107, 277, 280,
|
|
+ /* 910 */ 1107, 280, 303, 455, 305, 331, 390, 31, 188, 417,
|
|
+ /* 920 */ 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
|
|
+ /* 930 */ 119, 120, 120, 120, 120, 142, 390, 363, 455, 984,
|
|
+ /* 940 */ 121, 122, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
|
|
+ /* 950 */ 119, 120, 120, 120, 120, 975, 321, 1140, 324, 974,
|
|
+ /* 960 */ 121, 110, 112, 1163, 1163, 1004, 1007, 997, 997, 119,
|
|
+ /* 970 */ 119, 120, 120, 120, 120, 462, 375, 1183, 118, 118,
|
|
+ /* 980 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 1140,
|
|
+ /* 990 */ 974, 974, 976, 304, 9, 364, 244, 360, 118, 118,
|
|
+ /* 1000 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 312,
|
|
+ /* 1010 */ 544, 342, 1140, 1141, 1142, 299, 290, 535, 118, 118,
|
|
+ /* 1020 */ 118, 118, 117, 117, 116, 116, 116, 115, 422, 1261,
|
|
+ /* 1030 */ 1261, 1161, 13, 13, 278, 419, 418, 466, 390, 921,
|
|
+ /* 1040 */ 260, 260, 289, 1167, 1140, 1141, 1142, 189, 1169, 266,
|
|
+ /* 1050 */ 266, 466, 388, 541, 1184, 544, 1168, 263, 144, 487,
|
|
+ /* 1060 */ 920, 544, 541, 122, 112, 1163, 1163, 1004, 1007, 997,
|
|
+ /* 1070 */ 997, 119, 119, 120, 120, 120, 120, 71, 71, 1140,
|
|
+ /* 1080 */ 1170, 1270, 1170, 13, 13, 896, 1068, 1161, 544, 466,
|
|
+ /* 1090 */ 895, 107, 536, 1489, 4, 1266, 1107, 6, 523, 1047,
|
|
+ /* 1100 */ 12, 1069, 1090, 1568, 311, 453, 1568, 518, 539, 1107,
|
|
+ /* 1110 */ 56, 56, 1107, 1487, 421, 1356, 1070, 6, 343, 285,
|
|
+ /* 1120 */ 118, 118, 118, 118, 117, 117, 116, 116, 116, 115,
|
|
+ /* 1130 */ 422, 423, 1269, 319, 1140, 1141, 1142, 876, 266, 266,
|
|
+ /* 1140 */ 1275, 107, 536, 533, 4, 1486, 293, 877, 1209, 6,
|
|
+ /* 1150 */ 210, 541, 541, 164, 1540, 494, 414, 865, 539, 267,
|
|
+ /* 1160 */ 267, 1212, 396, 509, 497, 204, 266, 266, 394, 529,
|
|
+ /* 1170 */ 8, 984, 541, 517, 544, 920, 456, 105, 105, 541,
|
|
+ /* 1180 */ 1088, 423, 266, 266, 106, 415, 423, 546, 545, 266,
|
|
+ /* 1190 */ 266, 974, 516, 533, 1371, 541, 15, 15, 266, 266,
|
|
+ /* 1200 */ 454, 1118, 541, 266, 266, 1068, 1370, 513, 290, 535,
|
|
+ /* 1210 */ 544, 541, 512, 97, 442, 314, 541, 544, 920, 125,
|
|
+ /* 1220 */ 1069, 984, 974, 974, 976, 977, 27, 105, 105, 399,
|
|
+ /* 1230 */ 341, 1509, 44, 44, 106, 1070, 423, 546, 545, 57,
|
|
+ /* 1240 */ 57, 974, 341, 1509, 107, 536, 544, 4, 460, 399,
|
|
+ /* 1250 */ 214, 1118, 457, 294, 375, 1089, 532, 297, 544, 537,
|
|
+ /* 1260 */ 396, 539, 290, 535, 104, 244, 102, 524, 58, 58,
|
|
+ /* 1270 */ 544, 109, 974, 974, 976, 977, 27, 1514, 1129, 425,
|
|
+ /* 1280 */ 59, 59, 270, 237, 423, 138, 95, 373, 373, 372,
|
|
+ /* 1290 */ 255, 370, 60, 60, 815, 1178, 533, 544, 273, 544,
|
|
+ /* 1300 */ 1161, 843, 387, 386, 544, 1307, 544, 215, 210, 296,
|
|
+ /* 1310 */ 513, 847, 544, 265, 208, 514, 1306, 295, 274, 61,
|
|
+ /* 1320 */ 61, 62, 62, 436, 984, 1160, 45, 45, 46, 46,
|
|
+ /* 1330 */ 105, 105, 1184, 920, 47, 47, 1474, 106, 544, 423,
|
|
+ /* 1340 */ 546, 545, 218, 544, 974, 935, 1085, 217, 544, 377,
|
|
+ /* 1350 */ 395, 107, 536, 936, 4, 156, 1161, 843, 158, 544,
|
|
+ /* 1360 */ 49, 49, 141, 544, 38, 50, 50, 544, 539, 307,
|
|
+ /* 1370 */ 63, 63, 544, 1448, 216, 974, 974, 976, 977, 27,
|
|
+ /* 1380 */ 444, 64, 64, 544, 1447, 65, 65, 544, 524, 14,
|
|
+ /* 1390 */ 14, 423, 458, 544, 66, 66, 310, 544, 316, 97,
|
|
+ /* 1400 */ 1034, 544, 961, 533, 268, 127, 127, 544, 391, 67,
|
|
+ /* 1410 */ 67, 544, 978, 290, 535, 52, 52, 513, 544, 68,
|
|
+ /* 1420 */ 68, 1294, 512, 69, 69, 397, 165, 855, 854, 53,
|
|
+ /* 1430 */ 53, 984, 966, 151, 151, 243, 430, 105, 105, 199,
|
|
+ /* 1440 */ 152, 152, 448, 1303, 106, 243, 423, 546, 545, 1129,
|
|
+ /* 1450 */ 425, 974, 320, 270, 862, 863, 1034, 220, 373, 373,
|
|
+ /* 1460 */ 372, 255, 370, 450, 323, 815, 243, 544, 978, 544,
|
|
+ /* 1470 */ 107, 536, 544, 4, 544, 938, 939, 325, 215, 1046,
|
|
+ /* 1480 */ 296, 1046, 974, 974, 976, 977, 27, 539, 295, 76,
|
|
+ /* 1490 */ 76, 54, 54, 327, 72, 72, 128, 128, 1503, 1254,
|
|
+ /* 1500 */ 107, 536, 544, 4, 1045, 544, 1045, 531, 1238, 544,
|
|
+ /* 1510 */ 423, 544, 315, 334, 544, 97, 544, 539, 217, 544,
|
|
+ /* 1520 */ 472, 1528, 533, 239, 73, 73, 156, 129, 129, 158,
|
|
+ /* 1530 */ 467, 130, 130, 126, 126, 344, 150, 150, 149, 149,
|
|
+ /* 1540 */ 423, 134, 134, 329, 1030, 216, 97, 239, 929, 345,
|
|
+ /* 1550 */ 984, 243, 533, 1315, 339, 544, 105, 105, 900, 1355,
|
|
+ /* 1560 */ 544, 1290, 258, 106, 338, 423, 546, 545, 544, 1301,
|
|
+ /* 1570 */ 974, 893, 99, 536, 109, 4, 544, 133, 133, 391,
|
|
+ /* 1580 */ 984, 197, 131, 131, 290, 535, 105, 105, 530, 539,
|
|
+ /* 1590 */ 132, 132, 1361, 106, 1219, 423, 546, 545, 75, 75,
|
|
+ /* 1600 */ 974, 974, 974, 976, 977, 27, 544, 430, 826, 1211,
|
|
+ /* 1610 */ 894, 139, 423, 109, 544, 1200, 1199, 1201, 1522, 544,
|
|
+ /* 1620 */ 201, 544, 11, 374, 533, 1287, 347, 349, 77, 77,
|
|
+ /* 1630 */ 1340, 974, 974, 976, 977, 27, 74, 74, 351, 213,
|
|
+ /* 1640 */ 435, 43, 43, 48, 48, 302, 477, 309, 1348, 382,
|
|
+ /* 1650 */ 353, 452, 984, 337, 1237, 1420, 1419, 205, 105, 105,
|
|
+ /* 1660 */ 192, 367, 193, 534, 1525, 106, 1178, 423, 546, 545,
|
|
+ /* 1670 */ 247, 167, 974, 270, 1467, 200, 1465, 1175, 373, 373,
|
|
+ /* 1680 */ 372, 255, 370, 398, 79, 815, 83, 82, 1425, 446,
|
|
+ /* 1690 */ 161, 177, 169, 95, 1337, 438, 172, 173, 215, 174,
|
|
+ /* 1700 */ 296, 175, 35, 974, 974, 976, 977, 27, 295, 1345,
|
|
+ /* 1710 */ 439, 470, 223, 36, 379, 445, 1414, 381, 459, 1351,
|
|
+ /* 1720 */ 181, 227, 88, 465, 259, 229, 1436, 318, 186, 468,
|
|
+ /* 1730 */ 322, 230, 384, 1202, 231, 486, 1257, 1256, 217, 411,
|
|
+ /* 1740 */ 1255, 1248, 90, 847, 206, 413, 156, 505, 1539, 158,
|
|
+ /* 1750 */ 1226, 1538, 283, 1508, 1227, 336, 385, 284, 1225, 496,
|
|
+ /* 1760 */ 1537, 1298, 94, 346, 348, 216, 1247, 499, 1299, 245,
|
|
+ /* 1770 */ 246, 1297, 416, 350, 1494, 124, 1493, 10, 524, 361,
|
|
+ /* 1780 */ 1400, 101, 96, 288, 508, 253, 1135, 1208, 34, 1296,
|
|
+ /* 1790 */ 547, 254, 256, 257, 392, 548, 1197, 1192, 359, 391,
|
|
+ /* 1800 */ 1280, 1279, 196, 365, 290, 535, 366, 352, 1452, 1322,
|
|
+ /* 1810 */ 1321, 1453, 153, 137, 281, 154, 802, 424, 155, 1451,
|
|
+ /* 1820 */ 1450, 198, 292, 202, 203, 78, 212, 430, 271, 135,
|
|
+ /* 1830 */ 1044, 1042, 958, 168, 219, 157, 170, 879, 308, 222,
|
|
+ /* 1840 */ 1058, 176, 159, 962, 400, 84, 402, 178, 85, 86,
|
|
+ /* 1850 */ 87, 166, 160, 393, 1061, 224, 225, 1057, 146, 18,
|
|
+ /* 1860 */ 226, 317, 1050, 1172, 243, 464, 182, 228, 37, 183,
|
|
+ /* 1870 */ 817, 469, 338, 232, 330, 481, 184, 89, 845, 19,
|
|
+ /* 1880 */ 20, 92, 473, 478, 333, 91, 162, 858, 147, 488,
|
|
+ /* 1890 */ 282, 1123, 148, 1010, 928, 1093, 39, 93, 40, 495,
|
|
+ /* 1900 */ 1094, 187, 498, 207, 262, 264, 923, 242, 1109, 109,
|
|
+ /* 1910 */ 1113, 1111, 1097, 33, 21, 1117, 520, 1025, 22, 23,
|
|
+ /* 1920 */ 24, 1116, 25, 190, 97, 1011, 1009, 26, 1013, 1067,
|
|
+ /* 1930 */ 248, 7, 1066, 249, 1014, 28, 41, 889, 979, 827,
|
|
+ /* 1940 */ 108, 29, 250, 540, 251, 1530, 371, 368, 1131, 1130,
|
|
+ /* 1950 */ 1188, 1188, 1188, 1188, 1188, 1188, 1188, 1529,
|
|
};
|
|
static const YYCODETYPE yy_lookahead[] = {
|
|
- /* 0 */ 260, 261, 262, 260, 261, 262, 176, 177, 178, 179,
|
|
- /* 10 */ 180, 181, 184, 206, 209, 184, 186, 206, 188, 19,
|
|
- /* 20 */ 179, 281, 181, 213, 214, 195, 206, 186, 195, 188,
|
|
- /* 30 */ 195, 31, 222, 184, 206, 207, 195, 206, 207, 39,
|
|
- /* 40 */ 24, 209, 184, 43, 44, 45, 46, 47, 48, 49,
|
|
- /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 228, 229,
|
|
- /* 60 */ 184, 228, 229, 228, 229, 260, 261, 262, 192, 228,
|
|
- /* 70 */ 229, 241, 196, 242, 241, 59, 241, 205, 245, 246,
|
|
- /* 80 */ 184, 22, 241, 24, 254, 213, 54, 55, 56, 57,
|
|
- /* 90 */ 58, 256, 260, 261, 262, 254, 96, 97, 98, 99,
|
|
- /* 100 */ 100, 101, 102, 103, 104, 105, 106, 100, 101, 102,
|
|
- /* 110 */ 103, 104, 105, 106, 284, 203, 19, 221, 59, 102,
|
|
- /* 120 */ 103, 104, 105, 106, 59, 284, 110, 269, 96, 97,
|
|
- /* 130 */ 98, 99, 100, 101, 102, 103, 104, 105, 106, 94,
|
|
- /* 140 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
|
- /* 150 */ 53, 54, 55, 56, 57, 110, 184, 106, 73, 114,
|
|
- /* 160 */ 178, 179, 180, 181, 219, 184, 81, 22, 186, 110,
|
|
- /* 170 */ 188, 121, 122, 195, 109, 110, 111, 195, 206, 207,
|
|
- /* 180 */ 83, 184, 85, 54, 55, 56, 57, 206, 207, 277,
|
|
- /* 190 */ 145, 146, 147, 96, 97, 98, 99, 100, 101, 102,
|
|
- /* 200 */ 103, 104, 105, 106, 59, 120, 228, 229, 143, 184,
|
|
- /* 210 */ 228, 229, 184, 19, 242, 203, 131, 132, 221, 241,
|
|
- /* 220 */ 26, 184, 184, 241, 196, 96, 97, 98, 99, 100,
|
|
- /* 230 */ 101, 102, 103, 104, 105, 106, 254, 43, 44, 45,
|
|
- /* 240 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
|
- /* 250 */ 56, 57, 184, 184, 109, 110, 111, 105, 106, 184,
|
|
- /* 260 */ 200, 201, 202, 69, 184, 227, 284, 96, 97, 98,
|
|
- /* 270 */ 99, 100, 101, 102, 103, 104, 105, 106, 297, 298,
|
|
- /* 280 */ 255, 206, 207, 19, 272, 59, 206, 207, 184, 277,
|
|
- /* 290 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
|
|
- /* 300 */ 106, 184, 259, 19, 184, 100, 101, 43, 44, 45,
|
|
- /* 310 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
|
- /* 320 */ 56, 57, 242, 206, 207, 184, 100, 101, 138, 292,
|
|
- /* 330 */ 293, 67, 76, 296, 108, 109, 110, 111, 295, 113,
|
|
- /* 340 */ 84, 59, 86, 22, 26, 89, 156, 121, 224, 225,
|
|
- /* 350 */ 145, 19, 147, 59, 72, 256, 24, 184, 290, 291,
|
|
- /* 360 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
|
|
- /* 370 */ 106, 145, 297, 147, 299, 43, 44, 45, 46, 47,
|
|
- /* 380 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
|
- /* 390 */ 106, 109, 110, 111, 138, 184, 112, 113, 114, 115,
|
|
- /* 400 */ 116, 117, 118, 109, 110, 111, 112, 59, 124, 115,
|
|
- /* 410 */ 116, 117, 292, 293, 297, 298, 296, 206, 207, 125,
|
|
- /* 420 */ 72, 100, 101, 184, 46, 47, 48, 49, 96, 97,
|
|
- /* 430 */ 98, 99, 100, 101, 102, 103, 104, 105, 106, 59,
|
|
- /* 440 */ 200, 201, 202, 184, 59, 206, 207, 46, 19, 131,
|
|
- /* 450 */ 132, 278, 23, 242, 184, 184, 76, 109, 110, 111,
|
|
- /* 460 */ 224, 225, 251, 81, 84, 184, 86, 22, 23, 89,
|
|
- /* 470 */ 184, 26, 43, 44, 45, 46, 47, 48, 49, 50,
|
|
- /* 480 */ 51, 52, 53, 54, 55, 56, 57, 102, 184, 109,
|
|
- /* 490 */ 110, 111, 114, 184, 109, 110, 111, 184, 227, 184,
|
|
- /* 500 */ 230, 184, 22, 264, 195, 59, 22, 184, 195, 108,
|
|
- /* 510 */ 206, 207, 59, 131, 132, 206, 207, 184, 138, 206,
|
|
- /* 520 */ 207, 206, 207, 206, 207, 96, 97, 98, 99, 100,
|
|
- /* 530 */ 101, 102, 103, 104, 105, 106, 255, 228, 229, 59,
|
|
- /* 540 */ 95, 228, 229, 59, 184, 19, 242, 94, 184, 23,
|
|
- /* 550 */ 241, 242, 184, 282, 241, 242, 110, 242, 184, 242,
|
|
- /* 560 */ 251, 59, 109, 110, 196, 184, 251, 114, 251, 43,
|
|
- /* 570 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
|
- /* 580 */ 54, 55, 56, 57, 259, 217, 12, 219, 255, 109,
|
|
- /* 590 */ 110, 111, 203, 109, 110, 111, 184, 22, 145, 146,
|
|
- /* 600 */ 147, 27, 112, 22, 230, 115, 116, 117, 227, 19,
|
|
- /* 610 */ 59, 109, 110, 111, 291, 125, 42, 35, 206, 207,
|
|
- /* 620 */ 295, 184, 96, 97, 98, 99, 100, 101, 102, 103,
|
|
- /* 630 */ 104, 105, 106, 26, 59, 233, 46, 63, 136, 184,
|
|
- /* 640 */ 59, 184, 19, 206, 207, 243, 23, 73, 66, 260,
|
|
- /* 650 */ 261, 262, 59, 184, 242, 195, 74, 220, 184, 184,
|
|
- /* 660 */ 109, 110, 111, 206, 207, 184, 43, 44, 45, 46,
|
|
- /* 670 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
|
- /* 680 */ 57, 206, 207, 76, 109, 110, 111, 136, 228, 229,
|
|
- /* 690 */ 109, 110, 111, 86, 184, 220, 89, 21, 108, 230,
|
|
- /* 700 */ 184, 241, 109, 110, 111, 123, 184, 127, 184, 129,
|
|
- /* 710 */ 130, 184, 195, 184, 124, 184, 198, 199, 184, 96,
|
|
- /* 720 */ 97, 98, 99, 100, 101, 102, 103, 104, 105, 106,
|
|
- /* 730 */ 206, 207, 11, 206, 207, 206, 207, 206, 207, 19,
|
|
- /* 740 */ 206, 207, 184, 23, 220, 228, 229, 220, 81, 220,
|
|
- /* 750 */ 195, 220, 287, 288, 220, 195, 80, 195, 241, 201,
|
|
- /* 760 */ 202, 184, 73, 43, 44, 45, 46, 47, 48, 49,
|
|
- /* 770 */ 50, 51, 52, 53, 54, 55, 56, 57, 201, 202,
|
|
- /* 780 */ 113, 195, 184, 228, 229, 120, 121, 122, 228, 229,
|
|
- /* 790 */ 228, 229, 116, 16, 23, 184, 241, 26, 131, 132,
|
|
- /* 800 */ 278, 241, 19, 241, 22, 23, 184, 189, 26, 120,
|
|
- /* 810 */ 121, 122, 184, 26, 228, 229, 96, 97, 98, 99,
|
|
- /* 820 */ 100, 101, 102, 103, 104, 105, 106, 241, 270, 153,
|
|
- /* 830 */ 66, 228, 229, 229, 206, 207, 19, 184, 228, 229,
|
|
- /* 840 */ 23, 16, 121, 122, 241, 241, 82, 270, 29, 227,
|
|
- /* 850 */ 252, 241, 33, 19, 77, 91, 79, 184, 22, 23,
|
|
- /* 860 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
|
- /* 870 */ 53, 54, 55, 56, 57, 12, 184, 95, 184, 206,
|
|
- /* 880 */ 207, 76, 111, 184, 65, 267, 184, 184, 184, 271,
|
|
- /* 890 */ 27, 86, 109, 184, 89, 120, 121, 122, 206, 207,
|
|
- /* 900 */ 206, 207, 77, 139, 79, 42, 184, 136, 206, 207,
|
|
- /* 910 */ 206, 207, 184, 96, 97, 98, 99, 100, 101, 102,
|
|
- /* 920 */ 103, 104, 105, 106, 184, 138, 63, 184, 206, 207,
|
|
- /* 930 */ 153, 95, 184, 19, 206, 207, 227, 23, 7, 8,
|
|
- /* 940 */ 9, 293, 293, 109, 296, 296, 206, 207, 215, 206,
|
|
- /* 950 */ 207, 184, 253, 19, 206, 207, 253, 43, 44, 45,
|
|
- /* 960 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
|
- /* 970 */ 56, 57, 184, 206, 207, 184, 184, 43, 44, 45,
|
|
- /* 980 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
|
- /* 990 */ 56, 57, 184, 22, 23, 184, 59, 206, 207, 184,
|
|
- /* 1000 */ 184, 238, 184, 240, 184, 22, 184, 184, 157, 158,
|
|
- /* 1010 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
|
|
- /* 1020 */ 106, 206, 207, 184, 206, 207, 206, 207, 206, 207,
|
|
- /* 1030 */ 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
|
|
- /* 1040 */ 106, 184, 59, 227, 252, 184, 293, 110, 184, 296,
|
|
- /* 1050 */ 184, 184, 184, 230, 184, 184, 184, 15, 184, 184,
|
|
- /* 1060 */ 184, 253, 184, 206, 207, 184, 95, 206, 207, 102,
|
|
- /* 1070 */ 206, 207, 206, 207, 206, 207, 206, 207, 206, 207,
|
|
- /* 1080 */ 206, 207, 206, 207, 184, 151, 184, 206, 207, 278,
|
|
- /* 1090 */ 184, 252, 184, 110, 184, 128, 184, 198, 199, 184,
|
|
- /* 1100 */ 133, 184, 60, 26, 184, 19, 206, 207, 206, 207,
|
|
- /* 1110 */ 131, 132, 206, 207, 206, 207, 206, 207, 206, 207,
|
|
- /* 1120 */ 253, 206, 207, 206, 207, 19, 206, 207, 253, 43,
|
|
- /* 1130 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
|
- /* 1140 */ 54, 55, 56, 57, 184, 26, 184, 26, 184, 43,
|
|
- /* 1150 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
|
- /* 1160 */ 54, 55, 56, 57, 285, 286, 206, 207, 206, 207,
|
|
- /* 1170 */ 206, 207, 184, 31, 184, 293, 184, 293, 296, 184,
|
|
- /* 1180 */ 296, 39, 96, 97, 98, 99, 100, 101, 102, 103,
|
|
- /* 1190 */ 104, 105, 106, 184, 206, 207, 206, 207, 206, 207,
|
|
- /* 1200 */ 184, 22, 96, 97, 98, 99, 100, 101, 102, 103,
|
|
- /* 1210 */ 104, 105, 106, 184, 245, 246, 184, 26, 23, 142,
|
|
- /* 1220 */ 128, 26, 206, 207, 150, 133, 152, 22, 22, 24,
|
|
- /* 1230 */ 111, 23, 53, 184, 26, 206, 207, 151, 206, 207,
|
|
- /* 1240 */ 119, 24, 122, 23, 23, 23, 26, 26, 26, 23,
|
|
- /* 1250 */ 23, 23, 26, 26, 26, 136, 23, 19, 22, 26,
|
|
- /* 1260 */ 113, 114, 24, 114, 144, 184, 59, 61, 7, 8,
|
|
- /* 1270 */ 59, 23, 23, 124, 26, 26, 23, 19, 145, 26,
|
|
- /* 1280 */ 147, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
|
- /* 1290 */ 52, 53, 54, 55, 56, 57, 145, 23, 147, 184,
|
|
- /* 1300 */ 26, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
|
- /* 1310 */ 52, 53, 54, 55, 56, 57, 23, 110, 184, 26,
|
|
- /* 1320 */ 184, 110, 184, 184, 184, 215, 135, 215, 184, 184,
|
|
- /* 1330 */ 184, 247, 184, 244, 96, 97, 98, 99, 100, 101,
|
|
- /* 1340 */ 102, 103, 104, 105, 106, 184, 184, 184, 301, 184,
|
|
- /* 1350 */ 184, 134, 225, 184, 96, 97, 98, 99, 100, 101,
|
|
- /* 1360 */ 102, 103, 104, 105, 106, 184, 184, 184, 184, 184,
|
|
- /* 1370 */ 134, 184, 274, 273, 19, 244, 244, 204, 182, 244,
|
|
- /* 1380 */ 283, 231, 279, 279, 232, 244, 210, 209, 235, 235,
|
|
- /* 1390 */ 235, 248, 218, 234, 19, 209, 238, 209, 238, 44,
|
|
- /* 1400 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
|
|
- /* 1410 */ 55, 56, 57, 214, 60, 248, 248, 187, 134, 38,
|
|
- /* 1420 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
|
|
- /* 1430 */ 55, 56, 57, 232, 191, 191, 266, 280, 191, 283,
|
|
- /* 1440 */ 143, 269, 108, 22, 280, 19, 20, 258, 22, 257,
|
|
- /* 1450 */ 43, 96, 97, 98, 99, 100, 101, 102, 103, 104,
|
|
- /* 1460 */ 105, 106, 36, 223, 142, 18, 235, 226, 226, 191,
|
|
- /* 1470 */ 18, 96, 97, 98, 99, 100, 101, 102, 103, 104,
|
|
- /* 1480 */ 105, 106, 226, 226, 190, 59, 235, 235, 223, 223,
|
|
- /* 1490 */ 258, 257, 191, 190, 235, 150, 62, 71, 191, 276,
|
|
- /* 1500 */ 275, 19, 20, 190, 22, 22, 211, 81, 191, 190,
|
|
- /* 1510 */ 211, 191, 108, 190, 208, 64, 208, 208, 36, 119,
|
|
- /* 1520 */ 94, 216, 211, 208, 210, 106, 100, 101, 216, 208,
|
|
- /* 1530 */ 48, 268, 208, 107, 208, 109, 110, 111, 211, 268,
|
|
- /* 1540 */ 114, 59, 211, 137, 108, 88, 250, 249, 191, 141,
|
|
- /* 1550 */ 250, 249, 138, 71, 250, 300, 22, 131, 132, 249,
|
|
- /* 1560 */ 300, 191, 150, 238, 82, 140, 250, 249, 239, 87,
|
|
- /* 1570 */ 139, 145, 146, 147, 148, 149, 94, 239, 237, 236,
|
|
- /* 1580 */ 25, 235, 100, 101, 194, 26, 193, 13, 185, 107,
|
|
- /* 1590 */ 185, 109, 110, 111, 6, 263, 114, 203, 265, 183,
|
|
- /* 1600 */ 183, 183, 203, 212, 203, 203, 197, 197, 212, 4,
|
|
- /* 1610 */ 3, 22, 197, 155, 15, 204, 203, 289, 93, 289,
|
|
- /* 1620 */ 16, 286, 132, 23, 204, 23, 123, 145, 146, 147,
|
|
- /* 1630 */ 148, 149, 0, 1, 2, 143, 24, 5, 20, 135,
|
|
- /* 1640 */ 16, 1, 10, 11, 12, 13, 14, 137, 135, 17,
|
|
- /* 1650 */ 144, 123, 19, 20, 61, 22, 37, 143, 123, 53,
|
|
- /* 1660 */ 109, 53, 30, 53, 32, 34, 53, 134, 1, 36,
|
|
- /* 1670 */ 5, 22, 40, 108, 153, 41, 26, 68, 75, 68,
|
|
- /* 1680 */ 134, 108, 24, 20, 124, 19, 118, 67, 67, 28,
|
|
- /* 1690 */ 22, 22, 59, 22, 67, 23, 22, 22, 142, 37,
|
|
- /* 1700 */ 23, 22, 70, 23, 71, 157, 23, 23, 26, 23,
|
|
- /* 1710 */ 78, 22, 24, 81, 23, 82, 22, 24, 134, 23,
|
|
- /* 1720 */ 87, 23, 19, 20, 92, 22, 109, 94, 22, 34,
|
|
- /* 1730 */ 136, 26, 85, 100, 101, 34, 34, 83, 34, 36,
|
|
- /* 1740 */ 107, 34, 109, 110, 111, 75, 90, 114, 75, 34,
|
|
- /* 1750 */ 23, 22, 44, 34, 24, 23, 22, 26, 126, 26,
|
|
- /* 1760 */ 23, 23, 59, 131, 132, 23, 23, 26, 23, 11,
|
|
- /* 1770 */ 22, 22, 26, 23, 71, 23, 22, 22, 145, 146,
|
|
- /* 1780 */ 147, 148, 149, 128, 23, 82, 154, 134, 15, 1,
|
|
- /* 1790 */ 87, 134, 302, 134, 134, 302, 302, 94, 302, 302,
|
|
- /* 1800 */ 302, 302, 302, 100, 101, 302, 302, 302, 302, 302,
|
|
- /* 1810 */ 107, 302, 109, 110, 111, 1, 2, 114, 302, 5,
|
|
- /* 1820 */ 302, 302, 302, 302, 10, 11, 12, 13, 14, 302,
|
|
- /* 1830 */ 302, 17, 302, 302, 302, 302, 19, 20, 302, 22,
|
|
- /* 1840 */ 302, 302, 302, 302, 30, 302, 32, 302, 145, 146,
|
|
- /* 1850 */ 147, 148, 149, 36, 40, 302, 302, 302, 302, 302,
|
|
- /* 1860 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 1870 */ 302, 302, 302, 302, 302, 302, 59, 302, 302, 302,
|
|
- /* 1880 */ 302, 302, 302, 302, 70, 302, 302, 302, 71, 302,
|
|
- /* 1890 */ 302, 302, 78, 302, 302, 81, 19, 20, 302, 22,
|
|
- /* 1900 */ 302, 302, 302, 302, 302, 302, 92, 302, 302, 302,
|
|
- /* 1910 */ 302, 94, 302, 36, 302, 302, 302, 100, 101, 102,
|
|
- /* 1920 */ 302, 302, 302, 302, 107, 302, 109, 110, 111, 302,
|
|
- /* 1930 */ 302, 114, 302, 302, 302, 302, 59, 302, 302, 302,
|
|
- /* 1940 */ 126, 302, 302, 302, 302, 131, 132, 302, 71, 302,
|
|
- /* 1950 */ 302, 302, 302, 302, 302, 302, 19, 20, 302, 22,
|
|
- /* 1960 */ 302, 302, 145, 146, 147, 148, 149, 302, 154, 302,
|
|
- /* 1970 */ 302, 94, 302, 36, 302, 302, 302, 100, 101, 302,
|
|
- /* 1980 */ 302, 302, 302, 302, 107, 302, 109, 110, 111, 302,
|
|
- /* 1990 */ 302, 114, 5, 302, 302, 302, 59, 10, 11, 12,
|
|
- /* 2000 */ 13, 14, 302, 302, 17, 302, 302, 302, 71, 302,
|
|
- /* 2010 */ 302, 302, 302, 302, 302, 302, 302, 30, 302, 32,
|
|
- /* 2020 */ 302, 302, 145, 146, 147, 148, 149, 40, 302, 302,
|
|
- /* 2030 */ 302, 94, 302, 302, 302, 302, 302, 100, 101, 302,
|
|
- /* 2040 */ 302, 302, 302, 302, 107, 302, 109, 110, 111, 302,
|
|
- /* 2050 */ 302, 114, 302, 302, 302, 302, 302, 70, 302, 302,
|
|
- /* 2060 */ 302, 302, 302, 302, 302, 78, 302, 302, 81, 302,
|
|
- /* 2070 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 92,
|
|
- /* 2080 */ 302, 302, 145, 146, 147, 148, 149, 302, 302, 302,
|
|
- /* 2090 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 2100 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 2110 */ 302, 302, 302, 126, 302, 302, 302, 302, 131, 132,
|
|
- /* 2120 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 2130 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 2140 */ 302, 154, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 2150 */ 302, 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
- /* 2160 */ 302, 302, 302, 302, 302, 302, 302, 302, 302,
|
|
+ /* 0 */ 189, 211, 189, 189, 218, 189, 220, 189, 267, 268,
|
|
+ /* 10 */ 269, 189, 210, 189, 228, 189, 267, 268, 269, 19,
|
|
+ /* 20 */ 218, 189, 211, 212, 211, 212, 211, 211, 212, 211,
|
|
+ /* 30 */ 212, 31, 211, 211, 212, 211, 212, 288, 300, 39,
|
|
+ /* 40 */ 21, 189, 304, 43, 44, 45, 46, 47, 48, 49,
|
|
+ /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 225, 19,
|
|
+ /* 60 */ 189, 183, 184, 185, 186, 189, 248, 263, 236, 191,
|
|
+ /* 70 */ 248, 193, 248, 197, 208, 257, 262, 201, 200, 257,
|
|
+ /* 80 */ 200, 257, 81, 43, 44, 45, 46, 47, 48, 49,
|
|
+ /* 90 */ 50, 51, 52, 53, 54, 55, 56, 57, 189, 80,
|
|
+ /* 100 */ 189, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
|
+ /* 110 */ 110, 111, 234, 235, 234, 235, 305, 306, 305, 118,
|
|
+ /* 120 */ 307, 305, 306, 297, 298, 247, 86, 247, 88, 19,
|
|
+ /* 130 */ 259, 251, 252, 267, 268, 269, 26, 136, 137, 261,
|
|
+ /* 140 */ 121, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
|
+ /* 150 */ 110, 111, 59, 43, 44, 45, 46, 47, 48, 49,
|
|
+ /* 160 */ 50, 51, 52, 53, 54, 55, 56, 57, 259, 291,
|
|
+ /* 170 */ 105, 106, 107, 108, 109, 110, 111, 158, 189, 69,
|
|
+ /* 180 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
|
+ /* 190 */ 111, 107, 108, 109, 110, 111, 205, 206, 207, 19,
|
|
+ /* 200 */ 19, 54, 55, 56, 57, 58, 29, 114, 115, 116,
|
|
+ /* 210 */ 33, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
|
+ /* 220 */ 110, 111, 233, 43, 44, 45, 46, 47, 48, 49,
|
|
+ /* 230 */ 50, 51, 52, 53, 54, 55, 56, 57, 19, 126,
|
|
+ /* 240 */ 127, 148, 65, 24, 214, 200, 59, 67, 101, 102,
|
|
+ /* 250 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 22,
|
|
+ /* 260 */ 189, 111, 43, 44, 45, 46, 47, 48, 49, 50,
|
|
+ /* 270 */ 51, 52, 53, 54, 55, 56, 57, 206, 207, 234,
|
|
+ /* 280 */ 235, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
|
+ /* 290 */ 110, 111, 247, 76, 107, 114, 59, 267, 268, 269,
|
|
+ /* 300 */ 189, 114, 115, 116, 162, 163, 89, 19, 263, 92,
|
|
+ /* 310 */ 189, 23, 54, 55, 56, 57, 189, 206, 207, 22,
|
|
+ /* 320 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
|
+ /* 330 */ 111, 43, 44, 45, 46, 47, 48, 49, 50, 51,
|
|
+ /* 340 */ 52, 53, 54, 55, 56, 57, 19, 189, 277, 59,
|
|
+ /* 350 */ 23, 114, 115, 116, 46, 47, 48, 49, 61, 101,
|
|
+ /* 360 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
|
+ /* 370 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
|
+ /* 380 */ 53, 54, 55, 56, 57, 125, 126, 127, 277, 101,
|
|
+ /* 390 */ 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
|
|
+ /* 400 */ 59, 189, 189, 276, 114, 115, 116, 117, 73, 59,
|
|
+ /* 410 */ 120, 121, 122, 72, 214, 19, 81, 259, 19, 23,
|
|
+ /* 420 */ 130, 81, 72, 24, 211, 212, 221, 119, 101, 102,
|
|
+ /* 430 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 43,
|
|
+ /* 440 */ 44, 45, 46, 47, 48, 49, 50, 51, 52, 53,
|
|
+ /* 450 */ 54, 55, 56, 57, 19, 114, 115, 116, 23, 208,
|
|
+ /* 460 */ 125, 248, 189, 189, 114, 115, 116, 267, 268, 269,
|
|
+ /* 470 */ 189, 136, 137, 189, 262, 22, 136, 137, 43, 44,
|
|
+ /* 480 */ 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
|
|
+ /* 490 */ 55, 56, 57, 189, 95, 211, 212, 101, 102, 103,
|
|
+ /* 500 */ 104, 105, 106, 107, 108, 109, 110, 111, 59, 189,
|
|
+ /* 510 */ 111, 189, 59, 76, 294, 295, 117, 118, 119, 120,
|
|
+ /* 520 */ 121, 122, 123, 19, 87, 189, 89, 23, 129, 92,
|
|
+ /* 530 */ 279, 227, 248, 22, 189, 284, 101, 102, 103, 104,
|
|
+ /* 540 */ 105, 106, 107, 108, 109, 110, 111, 43, 44, 45,
|
|
+ /* 550 */ 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
|
+ /* 560 */ 56, 57, 19, 114, 115, 116, 23, 114, 115, 116,
|
|
+ /* 570 */ 59, 117, 299, 300, 120, 121, 122, 304, 189, 189,
|
|
+ /* 580 */ 143, 189, 110, 111, 130, 22, 43, 44, 45, 46,
|
|
+ /* 590 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
|
+ /* 600 */ 57, 211, 212, 211, 212, 101, 102, 103, 104, 105,
|
|
+ /* 610 */ 106, 107, 108, 109, 110, 111, 226, 189, 226, 189,
|
|
+ /* 620 */ 298, 132, 59, 134, 135, 114, 115, 116, 189, 59,
|
|
+ /* 630 */ 285, 19, 7, 8, 9, 23, 205, 206, 207, 211,
|
|
+ /* 640 */ 212, 211, 212, 221, 101, 102, 103, 104, 105, 106,
|
|
+ /* 650 */ 107, 108, 109, 110, 111, 43, 44, 45, 46, 47,
|
|
+ /* 660 */ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
|
|
+ /* 670 */ 19, 181, 182, 183, 184, 185, 186, 114, 115, 116,
|
|
+ /* 680 */ 189, 191, 133, 193, 114, 115, 116, 138, 299, 300,
|
|
+ /* 690 */ 200, 22, 201, 304, 43, 44, 45, 46, 47, 48,
|
|
+ /* 700 */ 49, 50, 51, 52, 53, 54, 55, 56, 57, 35,
|
|
+ /* 710 */ 189, 141, 189, 101, 102, 103, 104, 105, 106, 107,
|
|
+ /* 720 */ 108, 109, 110, 111, 234, 235, 22, 23, 59, 184,
|
|
+ /* 730 */ 26, 186, 211, 212, 211, 212, 191, 247, 193, 19,
|
|
+ /* 740 */ 66, 105, 106, 73, 189, 200, 189, 226, 74, 226,
|
|
+ /* 750 */ 22, 261, 101, 102, 103, 104, 105, 106, 107, 108,
|
|
+ /* 760 */ 109, 110, 111, 43, 44, 45, 46, 47, 48, 49,
|
|
+ /* 770 */ 50, 51, 52, 53, 54, 55, 56, 57, 189, 234,
|
|
+ /* 780 */ 235, 291, 19, 114, 115, 116, 150, 59, 152, 189,
|
|
+ /* 790 */ 233, 236, 247, 59, 189, 125, 126, 127, 59, 300,
|
|
+ /* 800 */ 211, 212, 128, 304, 100, 19, 261, 156, 45, 46,
|
|
+ /* 810 */ 47, 48, 49, 50, 51, 52, 53, 54, 55, 56,
|
|
+ /* 820 */ 57, 101, 102, 103, 104, 105, 106, 107, 108, 109,
|
|
+ /* 830 */ 110, 111, 46, 233, 189, 189, 291, 248, 99, 189,
|
|
+ /* 840 */ 125, 126, 127, 115, 26, 200, 289, 230, 231, 115,
|
|
+ /* 850 */ 200, 16, 189, 114, 115, 189, 211, 212, 119, 221,
|
|
+ /* 860 */ 189, 211, 212, 258, 101, 102, 103, 104, 105, 106,
|
|
+ /* 870 */ 107, 108, 109, 110, 111, 189, 156, 211, 212, 234,
|
|
+ /* 880 */ 235, 189, 211, 212, 234, 235, 22, 201, 189, 150,
|
|
+ /* 890 */ 151, 152, 247, 248, 76, 16, 19, 247, 248, 113,
|
|
+ /* 900 */ 189, 24, 257, 211, 212, 189, 26, 89, 262, 223,
|
|
+ /* 910 */ 92, 225, 77, 189, 79, 129, 19, 53, 226, 248,
|
|
+ /* 920 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
|
+ /* 930 */ 53, 54, 55, 56, 57, 236, 19, 271, 189, 99,
|
|
+ /* 940 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
|
+ /* 950 */ 53, 54, 55, 56, 57, 115, 77, 59, 79, 119,
|
|
+ /* 960 */ 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
|
|
+ /* 970 */ 53, 54, 55, 56, 57, 259, 22, 23, 101, 102,
|
|
+ /* 980 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 59,
|
|
+ /* 990 */ 150, 151, 152, 158, 22, 244, 24, 246, 101, 102,
|
|
+ /* 1000 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 285,
|
|
+ /* 1010 */ 189, 189, 114, 115, 116, 200, 136, 137, 101, 102,
|
|
+ /* 1020 */ 103, 104, 105, 106, 107, 108, 109, 110, 111, 230,
|
|
+ /* 1030 */ 231, 59, 211, 212, 285, 105, 106, 189, 19, 141,
|
|
+ /* 1040 */ 234, 235, 239, 113, 114, 115, 116, 226, 118, 234,
|
|
+ /* 1050 */ 235, 189, 249, 247, 100, 189, 126, 23, 236, 107,
|
|
+ /* 1060 */ 26, 189, 247, 44, 45, 46, 47, 48, 49, 50,
|
|
+ /* 1070 */ 51, 52, 53, 54, 55, 56, 57, 211, 212, 59,
|
|
+ /* 1080 */ 150, 233, 152, 211, 212, 133, 12, 115, 189, 189,
|
|
+ /* 1090 */ 138, 19, 20, 300, 22, 233, 76, 304, 226, 11,
|
|
+ /* 1100 */ 208, 27, 22, 23, 200, 19, 26, 87, 36, 89,
|
|
+ /* 1110 */ 211, 212, 92, 300, 248, 189, 42, 304, 189, 250,
|
|
+ /* 1120 */ 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,
|
|
+ /* 1130 */ 111, 59, 200, 233, 114, 115, 116, 63, 234, 235,
|
|
+ /* 1140 */ 235, 19, 20, 71, 22, 300, 189, 73, 200, 304,
|
|
+ /* 1150 */ 116, 247, 247, 81, 23, 200, 227, 26, 36, 234,
|
|
+ /* 1160 */ 235, 203, 204, 143, 200, 26, 234, 235, 194, 200,
|
|
+ /* 1170 */ 48, 99, 247, 66, 189, 141, 284, 105, 106, 247,
|
|
+ /* 1180 */ 100, 59, 234, 235, 112, 259, 114, 115, 116, 234,
|
|
+ /* 1190 */ 235, 119, 85, 71, 266, 247, 211, 212, 234, 235,
|
|
+ /* 1200 */ 114, 94, 247, 234, 235, 12, 266, 85, 136, 137,
|
|
+ /* 1210 */ 189, 247, 90, 26, 126, 127, 247, 189, 26, 22,
|
|
+ /* 1220 */ 27, 99, 150, 151, 152, 153, 154, 105, 106, 189,
|
|
+ /* 1230 */ 302, 303, 211, 212, 112, 42, 114, 115, 116, 211,
|
|
+ /* 1240 */ 212, 119, 302, 303, 19, 20, 189, 22, 274, 189,
|
|
+ /* 1250 */ 15, 144, 278, 189, 22, 23, 63, 189, 189, 203,
|
|
+ /* 1260 */ 204, 36, 136, 137, 155, 24, 157, 143, 211, 212,
|
|
+ /* 1270 */ 189, 26, 150, 151, 152, 153, 154, 0, 1, 2,
|
|
+ /* 1280 */ 211, 212, 5, 46, 59, 161, 147, 10, 11, 12,
|
|
+ /* 1290 */ 13, 14, 211, 212, 17, 60, 71, 189, 258, 189,
|
|
+ /* 1300 */ 59, 59, 105, 106, 189, 189, 189, 30, 116, 32,
|
|
+ /* 1310 */ 85, 124, 189, 251, 252, 90, 189, 40, 258, 211,
|
|
+ /* 1320 */ 212, 211, 212, 189, 99, 26, 211, 212, 211, 212,
|
|
+ /* 1330 */ 105, 106, 100, 141, 211, 212, 189, 112, 189, 114,
|
|
+ /* 1340 */ 115, 116, 24, 189, 119, 31, 23, 70, 189, 26,
|
|
+ /* 1350 */ 113, 19, 20, 39, 22, 78, 115, 115, 81, 189,
|
|
+ /* 1360 */ 211, 212, 22, 189, 24, 211, 212, 189, 36, 189,
|
|
+ /* 1370 */ 211, 212, 189, 189, 97, 150, 151, 152, 153, 154,
|
|
+ /* 1380 */ 127, 211, 212, 189, 189, 211, 212, 189, 143, 211,
|
|
+ /* 1390 */ 212, 59, 189, 189, 211, 212, 23, 189, 189, 26,
|
|
+ /* 1400 */ 59, 189, 149, 71, 22, 211, 212, 189, 131, 211,
|
|
+ /* 1410 */ 212, 189, 59, 136, 137, 211, 212, 85, 189, 211,
|
|
+ /* 1420 */ 212, 253, 90, 211, 212, 292, 293, 118, 119, 211,
|
|
+ /* 1430 */ 212, 99, 23, 211, 212, 26, 159, 105, 106, 140,
|
|
+ /* 1440 */ 211, 212, 23, 189, 112, 26, 114, 115, 116, 1,
|
|
+ /* 1450 */ 2, 119, 189, 5, 7, 8, 115, 139, 10, 11,
|
|
+ /* 1460 */ 12, 13, 14, 23, 189, 17, 26, 189, 115, 189,
|
|
+ /* 1470 */ 19, 20, 189, 22, 189, 83, 84, 189, 30, 150,
|
|
+ /* 1480 */ 32, 152, 150, 151, 152, 153, 154, 36, 40, 211,
|
|
+ /* 1490 */ 212, 211, 212, 189, 211, 212, 211, 212, 309, 189,
|
|
+ /* 1500 */ 19, 20, 189, 22, 150, 189, 152, 231, 189, 189,
|
|
+ /* 1510 */ 59, 189, 23, 189, 189, 26, 189, 36, 70, 189,
|
|
+ /* 1520 */ 23, 139, 71, 26, 211, 212, 78, 211, 212, 81,
|
|
+ /* 1530 */ 281, 211, 212, 211, 212, 189, 211, 212, 211, 212,
|
|
+ /* 1540 */ 59, 211, 212, 23, 23, 97, 26, 26, 23, 189,
|
|
+ /* 1550 */ 99, 26, 71, 189, 119, 189, 105, 106, 107, 189,
|
|
+ /* 1560 */ 189, 189, 280, 112, 129, 114, 115, 116, 189, 189,
|
|
+ /* 1570 */ 119, 23, 19, 20, 26, 22, 189, 211, 212, 131,
|
|
+ /* 1580 */ 99, 237, 211, 212, 136, 137, 105, 106, 189, 36,
|
|
+ /* 1590 */ 211, 212, 189, 112, 189, 114, 115, 116, 211, 212,
|
|
+ /* 1600 */ 119, 150, 151, 152, 153, 154, 189, 159, 23, 189,
|
|
+ /* 1610 */ 23, 26, 59, 26, 189, 189, 189, 189, 189, 189,
|
|
+ /* 1620 */ 209, 189, 238, 187, 71, 250, 250, 250, 211, 212,
|
|
+ /* 1630 */ 241, 150, 151, 152, 153, 154, 211, 212, 250, 290,
|
|
+ /* 1640 */ 254, 211, 212, 211, 212, 254, 215, 286, 241, 241,
|
|
+ /* 1650 */ 254, 286, 99, 214, 220, 214, 214, 224, 105, 106,
|
|
+ /* 1660 */ 244, 240, 244, 273, 192, 112, 60, 114, 115, 116,
|
|
+ /* 1670 */ 139, 290, 119, 5, 196, 238, 196, 38, 10, 11,
|
|
+ /* 1680 */ 12, 13, 14, 196, 287, 17, 148, 287, 276, 113,
|
|
+ /* 1690 */ 43, 22, 229, 147, 241, 18, 232, 232, 30, 232,
|
|
+ /* 1700 */ 32, 232, 264, 150, 151, 152, 153, 154, 40, 265,
|
|
+ /* 1710 */ 196, 18, 195, 264, 241, 241, 241, 265, 196, 229,
|
|
+ /* 1720 */ 229, 195, 155, 62, 196, 195, 283, 282, 22, 216,
|
|
+ /* 1730 */ 196, 195, 216, 196, 195, 113, 213, 213, 70, 64,
|
|
+ /* 1740 */ 213, 222, 22, 124, 162, 111, 78, 142, 219, 81,
|
|
+ /* 1750 */ 215, 219, 275, 303, 213, 213, 216, 275, 213, 216,
|
|
+ /* 1760 */ 213, 256, 113, 255, 255, 97, 222, 216, 256, 196,
|
|
+ /* 1770 */ 91, 256, 82, 255, 308, 146, 308, 22, 143, 196,
|
|
+ /* 1780 */ 270, 155, 145, 272, 144, 25, 13, 199, 26, 256,
|
|
+ /* 1790 */ 198, 190, 190, 6, 296, 188, 188, 188, 244, 131,
|
|
+ /* 1800 */ 245, 245, 243, 242, 136, 137, 241, 255, 208, 260,
|
|
+ /* 1810 */ 260, 208, 202, 217, 217, 202, 4, 3, 202, 208,
|
|
+ /* 1820 */ 208, 22, 160, 209, 209, 208, 15, 159, 98, 16,
|
|
+ /* 1830 */ 23, 23, 137, 148, 24, 128, 140, 20, 16, 142,
|
|
+ /* 1840 */ 1, 140, 128, 149, 61, 53, 37, 148, 53, 53,
|
|
+ /* 1850 */ 53, 293, 128, 296, 114, 34, 139, 1, 5, 22,
|
|
+ /* 1860 */ 113, 158, 68, 75, 26, 41, 68, 139, 24, 113,
|
|
+ /* 1870 */ 20, 19, 129, 123, 23, 96, 22, 22, 59, 22,
|
|
+ /* 1880 */ 22, 147, 67, 67, 24, 22, 37, 28, 23, 22,
|
|
+ /* 1890 */ 67, 23, 23, 23, 114, 23, 22, 26, 22, 24,
|
|
+ /* 1900 */ 23, 22, 24, 139, 23, 23, 141, 34, 88, 26,
|
|
+ /* 1910 */ 75, 86, 23, 22, 34, 75, 24, 23, 34, 34,
|
|
+ /* 1920 */ 34, 93, 34, 26, 26, 23, 23, 34, 23, 23,
|
|
+ /* 1930 */ 26, 44, 23, 22, 11, 22, 22, 133, 23, 23,
|
|
+ /* 1940 */ 22, 22, 139, 26, 139, 139, 15, 23, 1, 1,
|
|
+ /* 1950 */ 310, 310, 310, 310, 310, 310, 310, 139, 310, 310,
|
|
+ /* 1960 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 1970 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 1980 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 1990 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2000 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2010 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2020 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2030 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2040 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2050 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2060 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2070 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2080 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2090 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2100 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2110 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2120 */ 310, 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
+ /* 2130 */ 310, 310, 310, 310, 310, 310, 310, 310, 310,
|
|
};
|
|
-#define YY_SHIFT_COUNT (539)
|
|
+#define YY_SHIFT_COUNT (550)
|
|
#define YY_SHIFT_MIN (0)
|
|
-#define YY_SHIFT_MAX (1987)
|
|
+#define YY_SHIFT_MAX (1948)
|
|
static const unsigned short int yy_shift_ofst[] = {
|
|
- /* 0 */ 1814, 1632, 1987, 1426, 1426, 382, 1482, 1633, 1703, 1877,
|
|
- /* 10 */ 1877, 1877, 85, 0, 0, 264, 1106, 1877, 1877, 1877,
|
|
- /* 20 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
|
|
- /* 30 */ 226, 226, 380, 380, 294, 667, 382, 382, 382, 382,
|
|
- /* 40 */ 382, 382, 97, 194, 332, 429, 526, 623, 720, 817,
|
|
- /* 50 */ 914, 934, 1086, 1238, 1106, 1106, 1106, 1106, 1106, 1106,
|
|
- /* 60 */ 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106, 1106,
|
|
- /* 70 */ 1106, 1106, 1258, 1106, 1355, 1375, 1375, 1817, 1877, 1877,
|
|
- /* 80 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
|
|
- /* 90 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
|
|
- /* 100 */ 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
|
|
- /* 110 */ 1937, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877, 1877,
|
|
- /* 120 */ 1877, 1877, 1877, 1877, 32, 129, 129, 129, 129, 129,
|
|
- /* 130 */ 171, 7, 17, 593, 676, 590, 593, 205, 205, 593,
|
|
- /* 140 */ 318, 318, 318, 318, 50, 152, 51, 2142, 2142, 284,
|
|
- /* 150 */ 284, 284, 65, 145, 282, 145, 145, 574, 574, 256,
|
|
- /* 160 */ 348, 445, 782, 593, 593, 593, 593, 593, 593, 593,
|
|
- /* 170 */ 593, 593, 593, 593, 593, 593, 593, 593, 593, 593,
|
|
- /* 180 */ 593, 593, 593, 593, 607, 607, 593, 721, 805, 805,
|
|
- /* 190 */ 446, 851, 851, 446, 190, 979, 2142, 2142, 2142, 453,
|
|
- /* 200 */ 45, 45, 480, 490, 484, 385, 575, 502, 551, 581,
|
|
- /* 210 */ 593, 593, 593, 593, 593, 593, 593, 593, 593, 689,
|
|
- /* 220 */ 593, 593, 593, 593, 593, 593, 593, 593, 593, 593,
|
|
- /* 230 */ 593, 593, 582, 582, 582, 593, 593, 593, 593, 771,
|
|
- /* 240 */ 593, 593, 593, 59, 764, 593, 593, 863, 593, 593,
|
|
- /* 250 */ 593, 593, 593, 593, 593, 593, 665, 819, 580, 16,
|
|
- /* 260 */ 16, 16, 16, 1119, 580, 580, 967, 321, 931, 1042,
|
|
- /* 270 */ 1077, 783, 783, 834, 1077, 1077, 834, 1121, 1195, 401,
|
|
- /* 280 */ 1142, 1142, 1142, 783, 787, 787, 1074, 1191, 1092, 1205,
|
|
- /* 290 */ 1354, 1284, 1284, 1381, 1381, 1284, 1297, 1334, 1421, 1407,
|
|
- /* 300 */ 1322, 1447, 1447, 1447, 1447, 1284, 1452, 1322, 1322, 1334,
|
|
- /* 310 */ 1421, 1407, 1407, 1322, 1284, 1452, 1345, 1434, 1284, 1452,
|
|
- /* 320 */ 1483, 1284, 1452, 1284, 1452, 1483, 1404, 1404, 1404, 1451,
|
|
- /* 330 */ 1483, 1404, 1400, 1404, 1451, 1404, 1404, 1483, 1419, 1419,
|
|
- /* 340 */ 1483, 1406, 1436, 1406, 1436, 1406, 1436, 1406, 1436, 1284,
|
|
- /* 350 */ 1457, 1457, 1408, 1414, 1534, 1284, 1412, 1408, 1425, 1431,
|
|
- /* 360 */ 1322, 1555, 1559, 1574, 1574, 1588, 1588, 1588, 2142, 2142,
|
|
- /* 370 */ 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142, 2142,
|
|
- /* 380 */ 2142, 2142, 2142, 378, 777, 836, 971, 825, 775, 983,
|
|
- /* 390 */ 1208, 1179, 1217, 1120, 1220, 1206, 1221, 1222, 1226, 1227,
|
|
- /* 400 */ 1228, 1233, 937, 1147, 1261, 1149, 1207, 1248, 1249, 1253,
|
|
- /* 410 */ 1133, 1151, 1274, 1293, 1211, 1236, 1605, 1607, 1589, 1458,
|
|
- /* 420 */ 1599, 1525, 1604, 1600, 1602, 1490, 1492, 1503, 1612, 1504,
|
|
- /* 430 */ 1618, 1510, 1624, 1640, 1513, 1506, 1528, 1593, 1619, 1514,
|
|
- /* 440 */ 1606, 1608, 1610, 1613, 1535, 1551, 1631, 1533, 1667, 1665,
|
|
- /* 450 */ 1649, 1565, 1521, 1609, 1650, 1611, 1603, 1634, 1546, 1573,
|
|
- /* 460 */ 1658, 1663, 1666, 1560, 1568, 1668, 1620, 1669, 1671, 1672,
|
|
- /* 470 */ 1674, 1621, 1661, 1675, 1627, 1662, 1677, 1556, 1679, 1680,
|
|
- /* 480 */ 1548, 1683, 1684, 1682, 1686, 1689, 1688, 1691, 1694, 1693,
|
|
- /* 490 */ 1584, 1696, 1698, 1617, 1695, 1706, 1594, 1705, 1701, 1702,
|
|
- /* 500 */ 1704, 1707, 1647, 1670, 1654, 1708, 1673, 1656, 1715, 1727,
|
|
- /* 510 */ 1729, 1730, 1731, 1733, 1719, 1732, 1705, 1737, 1738, 1742,
|
|
- /* 520 */ 1743, 1741, 1745, 1734, 1758, 1748, 1749, 1750, 1752, 1754,
|
|
- /* 530 */ 1755, 1746, 1655, 1653, 1657, 1659, 1660, 1761, 1773, 1788,
|
|
+ /* 0 */ 1448, 1277, 1668, 1072, 1072, 340, 1122, 1225, 1332, 1481,
|
|
+ /* 10 */ 1481, 1481, 335, 0, 0, 180, 897, 1481, 1481, 1481,
|
|
+ /* 20 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
|
|
+ /* 30 */ 930, 930, 1020, 1020, 290, 1, 340, 340, 340, 340,
|
|
+ /* 40 */ 340, 340, 40, 110, 219, 288, 327, 396, 435, 504,
|
|
+ /* 50 */ 543, 612, 651, 720, 877, 897, 897, 897, 897, 897,
|
|
+ /* 60 */ 897, 897, 897, 897, 897, 897, 897, 897, 897, 897,
|
|
+ /* 70 */ 897, 897, 897, 917, 897, 1019, 763, 763, 1451, 1481,
|
|
+ /* 80 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
|
|
+ /* 90 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
|
|
+ /* 100 */ 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
|
|
+ /* 110 */ 1481, 1481, 1553, 1481, 1481, 1481, 1481, 1481, 1481, 1481,
|
|
+ /* 120 */ 1481, 1481, 1481, 1481, 1481, 1481, 147, 258, 258, 258,
|
|
+ /* 130 */ 258, 258, 79, 65, 84, 449, 19, 786, 449, 636,
|
|
+ /* 140 */ 636, 449, 880, 880, 880, 880, 113, 142, 142, 472,
|
|
+ /* 150 */ 150, 1958, 1958, 399, 399, 399, 93, 237, 341, 237,
|
|
+ /* 160 */ 237, 1074, 1074, 437, 350, 704, 1080, 449, 449, 449,
|
|
+ /* 170 */ 449, 449, 449, 449, 449, 449, 449, 449, 449, 449,
|
|
+ /* 180 */ 449, 449, 449, 449, 449, 449, 449, 449, 818, 818,
|
|
+ /* 190 */ 449, 1088, 217, 217, 734, 734, 1124, 1126, 1958, 1958,
|
|
+ /* 200 */ 1958, 739, 840, 840, 453, 454, 511, 187, 563, 570,
|
|
+ /* 210 */ 898, 669, 449, 449, 449, 449, 449, 449, 449, 449,
|
|
+ /* 220 */ 449, 670, 449, 449, 449, 449, 449, 449, 449, 449,
|
|
+ /* 230 */ 449, 449, 449, 449, 674, 674, 674, 449, 449, 449,
|
|
+ /* 240 */ 449, 1034, 449, 449, 449, 972, 1107, 449, 449, 1193,
|
|
+ /* 250 */ 449, 449, 449, 449, 449, 449, 449, 449, 260, 177,
|
|
+ /* 260 */ 489, 1241, 1241, 1241, 1241, 1192, 489, 489, 952, 1197,
|
|
+ /* 270 */ 625, 1235, 1139, 181, 181, 1086, 1139, 1139, 1086, 1187,
|
|
+ /* 280 */ 1131, 1237, 1314, 1314, 1314, 181, 1245, 1245, 1109, 1299,
|
|
+ /* 290 */ 549, 1340, 1606, 1531, 1531, 1639, 1639, 1531, 1538, 1576,
|
|
+ /* 300 */ 1669, 1647, 1546, 1677, 1677, 1677, 1677, 1531, 1693, 1546,
|
|
+ /* 310 */ 1546, 1576, 1669, 1647, 1647, 1546, 1531, 1693, 1567, 1661,
|
|
+ /* 320 */ 1531, 1693, 1706, 1531, 1693, 1531, 1693, 1706, 1622, 1622,
|
|
+ /* 330 */ 1622, 1675, 1720, 1720, 1706, 1622, 1619, 1622, 1675, 1622,
|
|
+ /* 340 */ 1622, 1582, 1706, 1634, 1634, 1706, 1605, 1649, 1605, 1649,
|
|
+ /* 350 */ 1605, 1649, 1605, 1649, 1531, 1679, 1679, 1690, 1690, 1629,
|
|
+ /* 360 */ 1635, 1755, 1531, 1626, 1629, 1637, 1640, 1546, 1760, 1762,
|
|
+ /* 370 */ 1773, 1773, 1787, 1787, 1787, 1958, 1958, 1958, 1958, 1958,
|
|
+ /* 380 */ 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958, 1958,
|
|
+ /* 390 */ 308, 835, 954, 1232, 879, 715, 728, 1323, 864, 1318,
|
|
+ /* 400 */ 1253, 1373, 297, 1409, 1419, 1440, 1489, 1497, 1520, 1242,
|
|
+ /* 410 */ 1309, 1447, 1435, 1341, 1521, 1525, 1392, 1548, 1329, 1354,
|
|
+ /* 420 */ 1585, 1587, 1353, 1382, 1812, 1814, 1799, 1662, 1811, 1730,
|
|
+ /* 430 */ 1813, 1807, 1808, 1695, 1685, 1707, 1810, 1696, 1817, 1697,
|
|
+ /* 440 */ 1822, 1839, 1701, 1694, 1714, 1783, 1809, 1699, 1792, 1795,
|
|
+ /* 450 */ 1796, 1797, 1724, 1740, 1821, 1717, 1856, 1853, 1837, 1747,
|
|
+ /* 460 */ 1703, 1794, 1838, 1798, 1788, 1824, 1728, 1756, 1844, 1850,
|
|
+ /* 470 */ 1852, 1743, 1750, 1854, 1815, 1855, 1857, 1851, 1858, 1816,
|
|
+ /* 480 */ 1819, 1860, 1779, 1859, 1863, 1823, 1849, 1865, 1734, 1867,
|
|
+ /* 490 */ 1868, 1869, 1870, 1871, 1872, 1874, 1875, 1877, 1876, 1878,
|
|
+ /* 500 */ 1764, 1881, 1882, 1780, 1873, 1879, 1765, 1883, 1880, 1884,
|
|
+ /* 510 */ 1885, 1886, 1820, 1835, 1825, 1887, 1840, 1828, 1888, 1889,
|
|
+ /* 520 */ 1891, 1892, 1897, 1898, 1893, 1894, 1883, 1902, 1903, 1905,
|
|
+ /* 530 */ 1906, 1904, 1909, 1911, 1923, 1913, 1914, 1915, 1916, 1918,
|
|
+ /* 540 */ 1919, 1917, 1804, 1803, 1805, 1806, 1818, 1924, 1931, 1947,
|
|
+ /* 550 */ 1948,
|
|
};
|
|
-#define YY_REDUCE_COUNT (382)
|
|
-#define YY_REDUCE_MIN (-260)
|
|
-#define YY_REDUCE_MAX (1420)
|
|
+#define YY_REDUCE_COUNT (389)
|
|
+#define YY_REDUCE_MIN (-262)
|
|
+#define YY_REDUCE_MAX (1617)
|
|
static const short yy_reduce_ofst[] = {
|
|
- /* 0 */ -170, -18, -159, 309, 313, -167, -19, 75, 117, 211,
|
|
- /* 10 */ 315, 317, -165, -195, -168, -260, 389, 437, 475, 524,
|
|
- /* 20 */ 527, -169, 529, 531, -28, 80, 534, 239, 304, 412,
|
|
- /* 30 */ 558, 577, 37, 120, 368, -22, 460, 517, 555, 560,
|
|
- /* 40 */ 562, 586, -257, -257, -257, -257, -257, -257, -257, -257,
|
|
- /* 50 */ -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
|
|
- /* 60 */ -257, -257, -257, -257, -257, -257, -257, -257, -257, -257,
|
|
- /* 70 */ -257, -257, -257, -257, -257, -257, -257, -172, 457, 628,
|
|
- /* 80 */ 673, 692, 694, 702, 704, 722, 728, 740, 743, 748,
|
|
- /* 90 */ 767, 791, 815, 818, 820, 822, 857, 861, 864, 866,
|
|
- /* 100 */ 868, 870, 872, 874, 876, 881, 900, 902, 906, 908,
|
|
- /* 110 */ 910, 912, 915, 917, 920, 960, 962, 964, 988, 990,
|
|
- /* 120 */ 992, 1016, 1029, 1032, -257, -257, -257, -257, -257, -257,
|
|
- /* 130 */ -257, -257, -257, 271, 618, -190, 68, 60, 240, -124,
|
|
- /* 140 */ 603, 610, 603, 610, 12, -257, -257, -257, -257, -128,
|
|
- /* 150 */ -128, -128, -142, 25, 270, 281, 333, 124, 236, 648,
|
|
- /* 160 */ 374, 465, 465, 28, 598, 792, 839, 469, 38, 381,
|
|
- /* 170 */ 622, 709, 173, 699, 522, 703, 808, 811, 867, 816,
|
|
- /* 180 */ -104, 823, -3, 875, 649, 753, 323, -88, 882, 884,
|
|
- /* 190 */ 518, 43, 325, 899, 763, 604, 879, 969, 402, -193,
|
|
- /* 200 */ -189, -180, -151, -55, 69, 104, 141, 259, 286, 360,
|
|
- /* 210 */ 364, 455, 474, 481, 510, 516, 611, 653, 788, 99,
|
|
- /* 220 */ 871, 878, 995, 1009, 1049, 1081, 1115, 1134, 1136, 1138,
|
|
- /* 230 */ 1139, 1140, 733, 1110, 1112, 1144, 1145, 1146, 1148, 1084,
|
|
- /* 240 */ 1161, 1162, 1163, 1089, 1047, 1165, 1166, 1127, 1169, 104,
|
|
- /* 250 */ 1181, 1182, 1183, 1184, 1185, 1187, 1098, 1100, 1150, 1131,
|
|
- /* 260 */ 1132, 1135, 1141, 1084, 1150, 1150, 1152, 1173, 1196, 1097,
|
|
- /* 270 */ 1153, 1143, 1167, 1103, 1154, 1155, 1104, 1176, 1174, 1199,
|
|
- /* 280 */ 1178, 1186, 1188, 1168, 1158, 1160, 1170, 1159, 1201, 1230,
|
|
- /* 290 */ 1156, 1243, 1244, 1157, 1164, 1247, 1172, 1189, 1192, 1240,
|
|
- /* 300 */ 1231, 1241, 1242, 1256, 1257, 1278, 1294, 1251, 1252, 1232,
|
|
- /* 310 */ 1234, 1265, 1266, 1259, 1301, 1303, 1223, 1225, 1307, 1313,
|
|
- /* 320 */ 1295, 1317, 1319, 1320, 1323, 1299, 1306, 1308, 1309, 1305,
|
|
- /* 330 */ 1311, 1315, 1314, 1321, 1312, 1324, 1326, 1327, 1263, 1271,
|
|
- /* 340 */ 1331, 1296, 1298, 1300, 1302, 1304, 1310, 1316, 1318, 1357,
|
|
- /* 350 */ 1255, 1260, 1329, 1325, 1332, 1370, 1333, 1338, 1341, 1343,
|
|
- /* 360 */ 1346, 1390, 1393, 1403, 1405, 1416, 1417, 1418, 1328, 1330,
|
|
- /* 370 */ 1335, 1409, 1394, 1399, 1401, 1402, 1410, 1391, 1396, 1411,
|
|
- /* 380 */ 1420, 1413, 1415,
|
|
+ /* 0 */ 490, -122, 545, 645, 650, -120, -189, -187, -184, -182,
|
|
+ /* 10 */ -178, -176, 45, 30, 200, -251, -134, 390, 392, 521,
|
|
+ /* 20 */ 523, 213, 692, 821, 284, 589, 872, 666, 671, 866,
|
|
+ /* 30 */ 71, 111, 273, 389, 686, 815, 904, 932, 948, 955,
|
|
+ /* 40 */ 964, 969, -259, -259, -259, -259, -259, -259, -259, -259,
|
|
+ /* 50 */ -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
|
|
+ /* 60 */ -259, -259, -259, -259, -259, -259, -259, -259, -259, -259,
|
|
+ /* 70 */ -259, -259, -259, -259, -259, -259, -259, -259, 428, 430,
|
|
+ /* 80 */ 899, 985, 1021, 1028, 1057, 1069, 1081, 1108, 1110, 1115,
|
|
+ /* 90 */ 1117, 1123, 1149, 1154, 1159, 1170, 1174, 1178, 1183, 1194,
|
|
+ /* 100 */ 1198, 1204, 1208, 1212, 1218, 1222, 1229, 1278, 1280, 1283,
|
|
+ /* 110 */ 1285, 1313, 1316, 1320, 1322, 1325, 1327, 1330, 1366, 1371,
|
|
+ /* 120 */ 1379, 1387, 1417, 1425, 1430, 1432, -259, -259, -259, -259,
|
|
+ /* 130 */ -259, -259, -259, -259, -259, 557, 974, -214, -174, -9,
|
|
+ /* 140 */ 431, -124, 806, 925, 806, 925, 251, 928, 940, -259,
|
|
+ /* 150 */ -259, -259, -259, -198, -198, -198, 127, -186, -168, 212,
|
|
+ /* 160 */ 646, 617, 799, -262, 555, 220, 220, 491, 605, 1040,
|
|
+ /* 170 */ 1060, 699, -11, 600, 848, 862, 345, -129, 724, -91,
|
|
+ /* 180 */ 158, 749, 716, 900, 304, 822, 929, 926, 499, 793,
|
|
+ /* 190 */ 322, 892, 813, 845, 958, 1056, 751, 905, 1133, 1062,
|
|
+ /* 200 */ 803, -210, -185, -179, -148, -167, -89, 121, 274, 281,
|
|
+ /* 210 */ 320, 336, 439, 663, 711, 957, 1064, 1068, 1116, 1127,
|
|
+ /* 220 */ 1134, -196, 1147, 1180, 1184, 1195, 1203, 1209, 1254, 1263,
|
|
+ /* 230 */ 1275, 1288, 1304, 1310, 205, 422, 638, 1319, 1324, 1346,
|
|
+ /* 240 */ 1360, 1168, 1364, 1370, 1372, 869, 1189, 1380, 1399, 1276,
|
|
+ /* 250 */ 1403, 121, 1405, 1420, 1426, 1427, 1428, 1429, 1249, 1282,
|
|
+ /* 260 */ 1344, 1375, 1376, 1377, 1388, 1168, 1344, 1344, 1384, 1411,
|
|
+ /* 270 */ 1436, 1349, 1389, 1386, 1391, 1361, 1407, 1408, 1365, 1431,
|
|
+ /* 280 */ 1433, 1434, 1439, 1441, 1442, 1396, 1416, 1418, 1390, 1421,
|
|
+ /* 290 */ 1437, 1472, 1381, 1478, 1480, 1397, 1400, 1487, 1412, 1444,
|
|
+ /* 300 */ 1438, 1463, 1453, 1464, 1465, 1467, 1469, 1514, 1517, 1473,
|
|
+ /* 310 */ 1474, 1452, 1449, 1490, 1491, 1475, 1522, 1526, 1443, 1445,
|
|
+ /* 320 */ 1528, 1530, 1513, 1534, 1536, 1537, 1539, 1516, 1523, 1524,
|
|
+ /* 330 */ 1527, 1519, 1529, 1532, 1540, 1541, 1535, 1542, 1544, 1545,
|
|
+ /* 340 */ 1547, 1450, 1543, 1477, 1482, 1551, 1505, 1508, 1512, 1509,
|
|
+ /* 350 */ 1515, 1518, 1533, 1552, 1573, 1466, 1468, 1549, 1550, 1555,
|
|
+ /* 360 */ 1554, 1510, 1583, 1511, 1556, 1559, 1561, 1565, 1588, 1592,
|
|
+ /* 370 */ 1601, 1602, 1607, 1608, 1609, 1498, 1557, 1558, 1610, 1600,
|
|
+ /* 380 */ 1603, 1611, 1612, 1613, 1596, 1597, 1614, 1615, 1617, 1616,
|
|
};
|
|
static const YYACTIONTYPE yy_default[] = {
|
|
- /* 0 */ 1537, 1537, 1537, 1377, 1159, 1266, 1159, 1159, 1159, 1377,
|
|
- /* 10 */ 1377, 1377, 1159, 1296, 1296, 1430, 1190, 1159, 1159, 1159,
|
|
- /* 20 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1376, 1159, 1159,
|
|
- /* 30 */ 1159, 1159, 1460, 1460, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 40 */ 1159, 1159, 1159, 1302, 1159, 1159, 1159, 1159, 1159, 1378,
|
|
- /* 50 */ 1379, 1159, 1159, 1159, 1429, 1431, 1394, 1312, 1311, 1310,
|
|
- /* 60 */ 1309, 1412, 1283, 1307, 1300, 1304, 1372, 1373, 1371, 1375,
|
|
- /* 70 */ 1379, 1378, 1159, 1303, 1343, 1357, 1342, 1159, 1159, 1159,
|
|
- /* 80 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 90 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 100 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 110 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 120 */ 1159, 1159, 1159, 1159, 1351, 1356, 1362, 1355, 1352, 1345,
|
|
- /* 130 */ 1344, 1346, 1347, 1159, 1180, 1230, 1159, 1159, 1159, 1159,
|
|
- /* 140 */ 1448, 1447, 1159, 1159, 1190, 1348, 1349, 1359, 1358, 1437,
|
|
- /* 150 */ 1493, 1492, 1395, 1159, 1159, 1159, 1159, 1159, 1159, 1460,
|
|
- /* 160 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 170 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 180 */ 1159, 1159, 1159, 1159, 1460, 1460, 1159, 1190, 1460, 1460,
|
|
- /* 190 */ 1186, 1337, 1336, 1186, 1290, 1159, 1443, 1266, 1257, 1159,
|
|
- /* 200 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 210 */ 1159, 1159, 1159, 1434, 1432, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 220 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 230 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 240 */ 1159, 1159, 1159, 1262, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 250 */ 1159, 1159, 1159, 1159, 1159, 1487, 1159, 1407, 1244, 1262,
|
|
- /* 260 */ 1262, 1262, 1262, 1264, 1245, 1243, 1256, 1191, 1166, 1529,
|
|
- /* 270 */ 1306, 1285, 1285, 1526, 1306, 1306, 1526, 1205, 1507, 1202,
|
|
- /* 280 */ 1296, 1296, 1296, 1285, 1290, 1290, 1374, 1263, 1256, 1159,
|
|
- /* 290 */ 1529, 1271, 1271, 1528, 1528, 1271, 1395, 1315, 1321, 1233,
|
|
- /* 300 */ 1306, 1239, 1239, 1239, 1239, 1271, 1177, 1306, 1306, 1315,
|
|
- /* 310 */ 1321, 1233, 1233, 1306, 1271, 1177, 1411, 1523, 1271, 1177,
|
|
- /* 320 */ 1385, 1271, 1177, 1271, 1177, 1385, 1231, 1231, 1231, 1220,
|
|
- /* 330 */ 1385, 1231, 1205, 1231, 1220, 1231, 1231, 1385, 1389, 1389,
|
|
- /* 340 */ 1385, 1289, 1284, 1289, 1284, 1289, 1284, 1289, 1284, 1271,
|
|
- /* 350 */ 1470, 1470, 1301, 1290, 1380, 1271, 1159, 1301, 1299, 1297,
|
|
- /* 360 */ 1306, 1183, 1223, 1490, 1490, 1486, 1486, 1486, 1534, 1534,
|
|
- /* 370 */ 1443, 1502, 1190, 1190, 1190, 1190, 1502, 1207, 1207, 1191,
|
|
- /* 380 */ 1191, 1190, 1502, 1159, 1159, 1159, 1159, 1159, 1159, 1497,
|
|
- /* 390 */ 1159, 1396, 1275, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 400 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 410 */ 1159, 1159, 1159, 1159, 1159, 1326, 1159, 1162, 1440, 1159,
|
|
- /* 420 */ 1159, 1438, 1159, 1159, 1159, 1159, 1159, 1159, 1276, 1159,
|
|
- /* 430 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 440 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1525, 1159, 1159,
|
|
- /* 450 */ 1159, 1159, 1159, 1159, 1410, 1409, 1159, 1159, 1273, 1159,
|
|
- /* 460 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 470 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 480 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 490 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1298, 1159, 1159,
|
|
- /* 500 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 510 */ 1159, 1159, 1475, 1291, 1159, 1159, 1516, 1159, 1159, 1159,
|
|
- /* 520 */ 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159, 1159,
|
|
- /* 530 */ 1159, 1511, 1247, 1328, 1159, 1327, 1331, 1159, 1171, 1159,
|
|
+ /* 0 */ 1573, 1573, 1573, 1409, 1186, 1295, 1186, 1186, 1186, 1409,
|
|
+ /* 10 */ 1409, 1409, 1186, 1325, 1325, 1462, 1217, 1186, 1186, 1186,
|
|
+ /* 20 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1408, 1186, 1186,
|
|
+ /* 30 */ 1186, 1186, 1492, 1492, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 40 */ 1186, 1186, 1186, 1334, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 50 */ 1410, 1411, 1186, 1186, 1186, 1461, 1463, 1426, 1344, 1343,
|
|
+ /* 60 */ 1342, 1341, 1444, 1312, 1339, 1332, 1336, 1404, 1405, 1403,
|
|
+ /* 70 */ 1407, 1411, 1410, 1186, 1335, 1375, 1389, 1374, 1186, 1186,
|
|
+ /* 80 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 90 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 100 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 110 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 120 */ 1186, 1186, 1186, 1186, 1186, 1186, 1383, 1388, 1394, 1387,
|
|
+ /* 130 */ 1384, 1377, 1376, 1378, 1379, 1186, 1207, 1259, 1186, 1186,
|
|
+ /* 140 */ 1186, 1186, 1480, 1479, 1186, 1186, 1217, 1369, 1368, 1380,
|
|
+ /* 150 */ 1381, 1391, 1390, 1469, 1527, 1526, 1427, 1186, 1186, 1186,
|
|
+ /* 160 */ 1186, 1186, 1186, 1492, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 170 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 180 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1492, 1492,
|
|
+ /* 190 */ 1186, 1217, 1492, 1492, 1213, 1213, 1319, 1186, 1475, 1295,
|
|
+ /* 200 */ 1286, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 210 */ 1186, 1186, 1186, 1186, 1186, 1466, 1464, 1186, 1186, 1186,
|
|
+ /* 220 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 230 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 240 */ 1186, 1186, 1186, 1186, 1186, 1291, 1186, 1186, 1186, 1186,
|
|
+ /* 250 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1521, 1186, 1439,
|
|
+ /* 260 */ 1273, 1291, 1291, 1291, 1291, 1293, 1274, 1272, 1285, 1218,
|
|
+ /* 270 */ 1193, 1565, 1338, 1314, 1314, 1562, 1338, 1338, 1562, 1234,
|
|
+ /* 280 */ 1543, 1229, 1325, 1325, 1325, 1314, 1319, 1319, 1406, 1292,
|
|
+ /* 290 */ 1285, 1186, 1565, 1300, 1300, 1564, 1564, 1300, 1427, 1347,
|
|
+ /* 300 */ 1353, 1262, 1338, 1268, 1268, 1268, 1268, 1300, 1204, 1338,
|
|
+ /* 310 */ 1338, 1347, 1353, 1262, 1262, 1338, 1300, 1204, 1443, 1559,
|
|
+ /* 320 */ 1300, 1204, 1417, 1300, 1204, 1300, 1204, 1417, 1260, 1260,
|
|
+ /* 330 */ 1260, 1249, 1186, 1186, 1417, 1260, 1234, 1260, 1249, 1260,
|
|
+ /* 340 */ 1260, 1510, 1417, 1421, 1421, 1417, 1318, 1313, 1318, 1313,
|
|
+ /* 350 */ 1318, 1313, 1318, 1313, 1300, 1502, 1502, 1328, 1328, 1333,
|
|
+ /* 360 */ 1319, 1412, 1300, 1186, 1333, 1331, 1329, 1338, 1210, 1252,
|
|
+ /* 370 */ 1524, 1524, 1520, 1520, 1520, 1570, 1570, 1475, 1536, 1217,
|
|
+ /* 380 */ 1217, 1217, 1217, 1536, 1236, 1236, 1218, 1218, 1217, 1536,
|
|
+ /* 390 */ 1186, 1186, 1186, 1186, 1186, 1186, 1531, 1186, 1428, 1304,
|
|
+ /* 400 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 410 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 420 */ 1186, 1186, 1186, 1358, 1186, 1189, 1472, 1186, 1186, 1470,
|
|
+ /* 430 */ 1186, 1186, 1186, 1186, 1186, 1186, 1305, 1186, 1186, 1186,
|
|
+ /* 440 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 450 */ 1186, 1186, 1186, 1186, 1186, 1561, 1186, 1186, 1186, 1186,
|
|
+ /* 460 */ 1186, 1186, 1442, 1441, 1186, 1186, 1302, 1186, 1186, 1186,
|
|
+ /* 470 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 480 */ 1232, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 490 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 500 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1330, 1186, 1186,
|
|
+ /* 510 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 520 */ 1186, 1186, 1507, 1320, 1186, 1186, 1552, 1186, 1186, 1186,
|
|
+ /* 530 */ 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186, 1186,
|
|
+ /* 540 */ 1186, 1547, 1276, 1360, 1186, 1359, 1363, 1186, 1198, 1186,
|
|
+ /* 550 */ 1186,
|
|
};
|
|
/********** End of lemon-generated parsing tables *****************************/
|
|
|
|
@@ -149751,6 +154443,9 @@
|
|
59, /* VIEW => ID */
|
|
59, /* VIRTUAL => ID */
|
|
59, /* WITH => ID */
|
|
+ 59, /* NULLS => ID */
|
|
+ 59, /* FIRST => ID */
|
|
+ 59, /* LAST => ID */
|
|
59, /* CURRENT => ID */
|
|
59, /* FOLLOWING => ID */
|
|
59, /* PARTITION => ID */
|
|
@@ -149761,9 +154456,92 @@
|
|
59, /* GROUPS => ID */
|
|
59, /* OTHERS => ID */
|
|
59, /* TIES => ID */
|
|
+ 59, /* GENERATED => ID */
|
|
+ 59, /* ALWAYS => ID */
|
|
59, /* REINDEX => ID */
|
|
59, /* RENAME => ID */
|
|
59, /* CTIME_KW => ID */
|
|
+ 0, /* ANY => nothing */
|
|
+ 0, /* BITAND => nothing */
|
|
+ 0, /* BITOR => nothing */
|
|
+ 0, /* LSHIFT => nothing */
|
|
+ 0, /* RSHIFT => nothing */
|
|
+ 0, /* PLUS => nothing */
|
|
+ 0, /* MINUS => nothing */
|
|
+ 0, /* STAR => nothing */
|
|
+ 0, /* SLASH => nothing */
|
|
+ 0, /* REM => nothing */
|
|
+ 0, /* CONCAT => nothing */
|
|
+ 0, /* COLLATE => nothing */
|
|
+ 0, /* BITNOT => nothing */
|
|
+ 0, /* ON => nothing */
|
|
+ 0, /* INDEXED => nothing */
|
|
+ 0, /* STRING => nothing */
|
|
+ 0, /* JOIN_KW => nothing */
|
|
+ 0, /* CONSTRAINT => nothing */
|
|
+ 0, /* DEFAULT => nothing */
|
|
+ 0, /* NULL => nothing */
|
|
+ 0, /* PRIMARY => nothing */
|
|
+ 0, /* UNIQUE => nothing */
|
|
+ 0, /* CHECK => nothing */
|
|
+ 0, /* REFERENCES => nothing */
|
|
+ 0, /* AUTOINCR => nothing */
|
|
+ 0, /* INSERT => nothing */
|
|
+ 0, /* DELETE => nothing */
|
|
+ 0, /* UPDATE => nothing */
|
|
+ 0, /* SET => nothing */
|
|
+ 0, /* DEFERRABLE => nothing */
|
|
+ 0, /* FOREIGN => nothing */
|
|
+ 0, /* DROP => nothing */
|
|
+ 0, /* UNION => nothing */
|
|
+ 0, /* ALL => nothing */
|
|
+ 0, /* EXCEPT => nothing */
|
|
+ 0, /* INTERSECT => nothing */
|
|
+ 0, /* SELECT => nothing */
|
|
+ 0, /* VALUES => nothing */
|
|
+ 0, /* DISTINCT => nothing */
|
|
+ 0, /* DOT => nothing */
|
|
+ 0, /* FROM => nothing */
|
|
+ 0, /* JOIN => nothing */
|
|
+ 0, /* USING => nothing */
|
|
+ 0, /* ORDER => nothing */
|
|
+ 0, /* GROUP => nothing */
|
|
+ 0, /* HAVING => nothing */
|
|
+ 0, /* LIMIT => nothing */
|
|
+ 0, /* WHERE => nothing */
|
|
+ 0, /* INTO => nothing */
|
|
+ 0, /* NOTHING => nothing */
|
|
+ 0, /* FLOAT => nothing */
|
|
+ 0, /* BLOB => nothing */
|
|
+ 0, /* INTEGER => nothing */
|
|
+ 0, /* VARIABLE => nothing */
|
|
+ 0, /* CASE => nothing */
|
|
+ 0, /* WHEN => nothing */
|
|
+ 0, /* THEN => nothing */
|
|
+ 0, /* ELSE => nothing */
|
|
+ 0, /* INDEX => nothing */
|
|
+ 0, /* ALTER => nothing */
|
|
+ 0, /* ADD => nothing */
|
|
+ 0, /* WINDOW => nothing */
|
|
+ 0, /* OVER => nothing */
|
|
+ 0, /* FILTER => nothing */
|
|
+ 0, /* COLUMN => nothing */
|
|
+ 0, /* AGG_FUNCTION => nothing */
|
|
+ 0, /* AGG_COLUMN => nothing */
|
|
+ 0, /* TRUEFALSE => nothing */
|
|
+ 0, /* ISNOT => nothing */
|
|
+ 0, /* FUNCTION => nothing */
|
|
+ 0, /* UMINUS => nothing */
|
|
+ 0, /* UPLUS => nothing */
|
|
+ 0, /* TRUTH => nothing */
|
|
+ 0, /* REGISTER => nothing */
|
|
+ 0, /* VECTOR => nothing */
|
|
+ 0, /* SELECT_COLUMN => nothing */
|
|
+ 0, /* IF_NULL_ROW => nothing */
|
|
+ 0, /* ASTERISK => nothing */
|
|
+ 0, /* SPAN => nothing */
|
|
+ 0, /* SPACE => nothing */
|
|
+ 0, /* ILLEGAL => nothing */
|
|
};
|
|
#endif /* YYFALLBACK */
|
|
|
|
@@ -149933,226 +154711,234 @@
|
|
/* 79 */ "VIEW",
|
|
/* 80 */ "VIRTUAL",
|
|
/* 81 */ "WITH",
|
|
- /* 82 */ "CURRENT",
|
|
- /* 83 */ "FOLLOWING",
|
|
- /* 84 */ "PARTITION",
|
|
- /* 85 */ "PRECEDING",
|
|
- /* 86 */ "RANGE",
|
|
- /* 87 */ "UNBOUNDED",
|
|
- /* 88 */ "EXCLUDE",
|
|
- /* 89 */ "GROUPS",
|
|
- /* 90 */ "OTHERS",
|
|
- /* 91 */ "TIES",
|
|
- /* 92 */ "REINDEX",
|
|
- /* 93 */ "RENAME",
|
|
- /* 94 */ "CTIME_KW",
|
|
- /* 95 */ "ANY",
|
|
- /* 96 */ "BITAND",
|
|
- /* 97 */ "BITOR",
|
|
- /* 98 */ "LSHIFT",
|
|
- /* 99 */ "RSHIFT",
|
|
- /* 100 */ "PLUS",
|
|
- /* 101 */ "MINUS",
|
|
- /* 102 */ "STAR",
|
|
- /* 103 */ "SLASH",
|
|
- /* 104 */ "REM",
|
|
- /* 105 */ "CONCAT",
|
|
- /* 106 */ "COLLATE",
|
|
- /* 107 */ "BITNOT",
|
|
- /* 108 */ "ON",
|
|
- /* 109 */ "INDEXED",
|
|
- /* 110 */ "STRING",
|
|
- /* 111 */ "JOIN_KW",
|
|
- /* 112 */ "CONSTRAINT",
|
|
- /* 113 */ "DEFAULT",
|
|
- /* 114 */ "NULL",
|
|
- /* 115 */ "PRIMARY",
|
|
- /* 116 */ "UNIQUE",
|
|
- /* 117 */ "CHECK",
|
|
- /* 118 */ "REFERENCES",
|
|
- /* 119 */ "AUTOINCR",
|
|
- /* 120 */ "INSERT",
|
|
- /* 121 */ "DELETE",
|
|
- /* 122 */ "UPDATE",
|
|
- /* 123 */ "SET",
|
|
- /* 124 */ "DEFERRABLE",
|
|
- /* 125 */ "FOREIGN",
|
|
- /* 126 */ "DROP",
|
|
- /* 127 */ "UNION",
|
|
- /* 128 */ "ALL",
|
|
- /* 129 */ "EXCEPT",
|
|
- /* 130 */ "INTERSECT",
|
|
- /* 131 */ "SELECT",
|
|
- /* 132 */ "VALUES",
|
|
- /* 133 */ "DISTINCT",
|
|
- /* 134 */ "DOT",
|
|
- /* 135 */ "FROM",
|
|
- /* 136 */ "JOIN",
|
|
- /* 137 */ "USING",
|
|
- /* 138 */ "ORDER",
|
|
- /* 139 */ "GROUP",
|
|
- /* 140 */ "HAVING",
|
|
- /* 141 */ "LIMIT",
|
|
- /* 142 */ "WHERE",
|
|
- /* 143 */ "INTO",
|
|
- /* 144 */ "NOTHING",
|
|
- /* 145 */ "FLOAT",
|
|
- /* 146 */ "BLOB",
|
|
- /* 147 */ "INTEGER",
|
|
- /* 148 */ "VARIABLE",
|
|
- /* 149 */ "CASE",
|
|
- /* 150 */ "WHEN",
|
|
- /* 151 */ "THEN",
|
|
- /* 152 */ "ELSE",
|
|
- /* 153 */ "INDEX",
|
|
- /* 154 */ "ALTER",
|
|
- /* 155 */ "ADD",
|
|
- /* 156 */ "WINDOW",
|
|
- /* 157 */ "OVER",
|
|
- /* 158 */ "FILTER",
|
|
- /* 159 */ "TRUEFALSE",
|
|
- /* 160 */ "ISNOT",
|
|
- /* 161 */ "FUNCTION",
|
|
- /* 162 */ "COLUMN",
|
|
- /* 163 */ "AGG_FUNCTION",
|
|
- /* 164 */ "AGG_COLUMN",
|
|
- /* 165 */ "UMINUS",
|
|
- /* 166 */ "UPLUS",
|
|
- /* 167 */ "TRUTH",
|
|
- /* 168 */ "REGISTER",
|
|
- /* 169 */ "VECTOR",
|
|
- /* 170 */ "SELECT_COLUMN",
|
|
- /* 171 */ "IF_NULL_ROW",
|
|
- /* 172 */ "ASTERISK",
|
|
- /* 173 */ "SPAN",
|
|
- /* 174 */ "SPACE",
|
|
- /* 175 */ "ILLEGAL",
|
|
- /* 176 */ "input",
|
|
- /* 177 */ "cmdlist",
|
|
- /* 178 */ "ecmd",
|
|
- /* 179 */ "cmdx",
|
|
- /* 180 */ "explain",
|
|
- /* 181 */ "cmd",
|
|
- /* 182 */ "transtype",
|
|
- /* 183 */ "trans_opt",
|
|
- /* 184 */ "nm",
|
|
- /* 185 */ "savepoint_opt",
|
|
- /* 186 */ "create_table",
|
|
- /* 187 */ "create_table_args",
|
|
- /* 188 */ "createkw",
|
|
- /* 189 */ "temp",
|
|
- /* 190 */ "ifnotexists",
|
|
- /* 191 */ "dbnm",
|
|
- /* 192 */ "columnlist",
|
|
- /* 193 */ "conslist_opt",
|
|
- /* 194 */ "table_options",
|
|
- /* 195 */ "select",
|
|
- /* 196 */ "columnname",
|
|
- /* 197 */ "carglist",
|
|
- /* 198 */ "typetoken",
|
|
- /* 199 */ "typename",
|
|
- /* 200 */ "signed",
|
|
- /* 201 */ "plus_num",
|
|
- /* 202 */ "minus_num",
|
|
- /* 203 */ "scanpt",
|
|
- /* 204 */ "scantok",
|
|
- /* 205 */ "ccons",
|
|
- /* 206 */ "term",
|
|
- /* 207 */ "expr",
|
|
- /* 208 */ "onconf",
|
|
- /* 209 */ "sortorder",
|
|
- /* 210 */ "autoinc",
|
|
- /* 211 */ "eidlist_opt",
|
|
- /* 212 */ "refargs",
|
|
- /* 213 */ "defer_subclause",
|
|
- /* 214 */ "refarg",
|
|
- /* 215 */ "refact",
|
|
- /* 216 */ "init_deferred_pred_opt",
|
|
- /* 217 */ "conslist",
|
|
- /* 218 */ "tconscomma",
|
|
- /* 219 */ "tcons",
|
|
- /* 220 */ "sortlist",
|
|
- /* 221 */ "eidlist",
|
|
- /* 222 */ "defer_subclause_opt",
|
|
- /* 223 */ "orconf",
|
|
- /* 224 */ "resolvetype",
|
|
- /* 225 */ "raisetype",
|
|
- /* 226 */ "ifexists",
|
|
- /* 227 */ "fullname",
|
|
- /* 228 */ "selectnowith",
|
|
- /* 229 */ "oneselect",
|
|
- /* 230 */ "wqlist",
|
|
- /* 231 */ "multiselect_op",
|
|
- /* 232 */ "distinct",
|
|
- /* 233 */ "selcollist",
|
|
- /* 234 */ "from",
|
|
- /* 235 */ "where_opt",
|
|
- /* 236 */ "groupby_opt",
|
|
- /* 237 */ "having_opt",
|
|
- /* 238 */ "orderby_opt",
|
|
- /* 239 */ "limit_opt",
|
|
- /* 240 */ "window_clause",
|
|
- /* 241 */ "values",
|
|
- /* 242 */ "nexprlist",
|
|
- /* 243 */ "sclp",
|
|
- /* 244 */ "as",
|
|
- /* 245 */ "seltablist",
|
|
- /* 246 */ "stl_prefix",
|
|
- /* 247 */ "joinop",
|
|
- /* 248 */ "indexed_opt",
|
|
- /* 249 */ "on_opt",
|
|
- /* 250 */ "using_opt",
|
|
- /* 251 */ "exprlist",
|
|
- /* 252 */ "xfullname",
|
|
- /* 253 */ "idlist",
|
|
- /* 254 */ "with",
|
|
- /* 255 */ "setlist",
|
|
- /* 256 */ "insert_cmd",
|
|
- /* 257 */ "idlist_opt",
|
|
- /* 258 */ "upsert",
|
|
- /* 259 */ "over_clause",
|
|
- /* 260 */ "likeop",
|
|
- /* 261 */ "between_op",
|
|
- /* 262 */ "in_op",
|
|
- /* 263 */ "paren_exprlist",
|
|
- /* 264 */ "case_operand",
|
|
- /* 265 */ "case_exprlist",
|
|
- /* 266 */ "case_else",
|
|
- /* 267 */ "uniqueflag",
|
|
- /* 268 */ "collate",
|
|
- /* 269 */ "vinto",
|
|
- /* 270 */ "nmnum",
|
|
- /* 271 */ "trigger_decl",
|
|
- /* 272 */ "trigger_cmd_list",
|
|
- /* 273 */ "trigger_time",
|
|
- /* 274 */ "trigger_event",
|
|
- /* 275 */ "foreach_clause",
|
|
- /* 276 */ "when_clause",
|
|
- /* 277 */ "trigger_cmd",
|
|
- /* 278 */ "trnm",
|
|
- /* 279 */ "tridxby",
|
|
- /* 280 */ "database_kw_opt",
|
|
- /* 281 */ "key_opt",
|
|
- /* 282 */ "add_column_fullname",
|
|
- /* 283 */ "kwcolumn_opt",
|
|
- /* 284 */ "create_vtab",
|
|
- /* 285 */ "vtabarglist",
|
|
- /* 286 */ "vtabarg",
|
|
- /* 287 */ "vtabargtoken",
|
|
- /* 288 */ "lp",
|
|
- /* 289 */ "anylist",
|
|
- /* 290 */ "windowdefn_list",
|
|
- /* 291 */ "windowdefn",
|
|
- /* 292 */ "window",
|
|
- /* 293 */ "frame_opt",
|
|
- /* 294 */ "part_opt",
|
|
- /* 295 */ "filter_opt",
|
|
- /* 296 */ "range_or_rows",
|
|
- /* 297 */ "frame_bound",
|
|
- /* 298 */ "frame_bound_s",
|
|
- /* 299 */ "frame_bound_e",
|
|
- /* 300 */ "frame_exclude_opt",
|
|
- /* 301 */ "frame_exclude",
|
|
+ /* 82 */ "NULLS",
|
|
+ /* 83 */ "FIRST",
|
|
+ /* 84 */ "LAST",
|
|
+ /* 85 */ "CURRENT",
|
|
+ /* 86 */ "FOLLOWING",
|
|
+ /* 87 */ "PARTITION",
|
|
+ /* 88 */ "PRECEDING",
|
|
+ /* 89 */ "RANGE",
|
|
+ /* 90 */ "UNBOUNDED",
|
|
+ /* 91 */ "EXCLUDE",
|
|
+ /* 92 */ "GROUPS",
|
|
+ /* 93 */ "OTHERS",
|
|
+ /* 94 */ "TIES",
|
|
+ /* 95 */ "GENERATED",
|
|
+ /* 96 */ "ALWAYS",
|
|
+ /* 97 */ "REINDEX",
|
|
+ /* 98 */ "RENAME",
|
|
+ /* 99 */ "CTIME_KW",
|
|
+ /* 100 */ "ANY",
|
|
+ /* 101 */ "BITAND",
|
|
+ /* 102 */ "BITOR",
|
|
+ /* 103 */ "LSHIFT",
|
|
+ /* 104 */ "RSHIFT",
|
|
+ /* 105 */ "PLUS",
|
|
+ /* 106 */ "MINUS",
|
|
+ /* 107 */ "STAR",
|
|
+ /* 108 */ "SLASH",
|
|
+ /* 109 */ "REM",
|
|
+ /* 110 */ "CONCAT",
|
|
+ /* 111 */ "COLLATE",
|
|
+ /* 112 */ "BITNOT",
|
|
+ /* 113 */ "ON",
|
|
+ /* 114 */ "INDEXED",
|
|
+ /* 115 */ "STRING",
|
|
+ /* 116 */ "JOIN_KW",
|
|
+ /* 117 */ "CONSTRAINT",
|
|
+ /* 118 */ "DEFAULT",
|
|
+ /* 119 */ "NULL",
|
|
+ /* 120 */ "PRIMARY",
|
|
+ /* 121 */ "UNIQUE",
|
|
+ /* 122 */ "CHECK",
|
|
+ /* 123 */ "REFERENCES",
|
|
+ /* 124 */ "AUTOINCR",
|
|
+ /* 125 */ "INSERT",
|
|
+ /* 126 */ "DELETE",
|
|
+ /* 127 */ "UPDATE",
|
|
+ /* 128 */ "SET",
|
|
+ /* 129 */ "DEFERRABLE",
|
|
+ /* 130 */ "FOREIGN",
|
|
+ /* 131 */ "DROP",
|
|
+ /* 132 */ "UNION",
|
|
+ /* 133 */ "ALL",
|
|
+ /* 134 */ "EXCEPT",
|
|
+ /* 135 */ "INTERSECT",
|
|
+ /* 136 */ "SELECT",
|
|
+ /* 137 */ "VALUES",
|
|
+ /* 138 */ "DISTINCT",
|
|
+ /* 139 */ "DOT",
|
|
+ /* 140 */ "FROM",
|
|
+ /* 141 */ "JOIN",
|
|
+ /* 142 */ "USING",
|
|
+ /* 143 */ "ORDER",
|
|
+ /* 144 */ "GROUP",
|
|
+ /* 145 */ "HAVING",
|
|
+ /* 146 */ "LIMIT",
|
|
+ /* 147 */ "WHERE",
|
|
+ /* 148 */ "INTO",
|
|
+ /* 149 */ "NOTHING",
|
|
+ /* 150 */ "FLOAT",
|
|
+ /* 151 */ "BLOB",
|
|
+ /* 152 */ "INTEGER",
|
|
+ /* 153 */ "VARIABLE",
|
|
+ /* 154 */ "CASE",
|
|
+ /* 155 */ "WHEN",
|
|
+ /* 156 */ "THEN",
|
|
+ /* 157 */ "ELSE",
|
|
+ /* 158 */ "INDEX",
|
|
+ /* 159 */ "ALTER",
|
|
+ /* 160 */ "ADD",
|
|
+ /* 161 */ "WINDOW",
|
|
+ /* 162 */ "OVER",
|
|
+ /* 163 */ "FILTER",
|
|
+ /* 164 */ "COLUMN",
|
|
+ /* 165 */ "AGG_FUNCTION",
|
|
+ /* 166 */ "AGG_COLUMN",
|
|
+ /* 167 */ "TRUEFALSE",
|
|
+ /* 168 */ "ISNOT",
|
|
+ /* 169 */ "FUNCTION",
|
|
+ /* 170 */ "UMINUS",
|
|
+ /* 171 */ "UPLUS",
|
|
+ /* 172 */ "TRUTH",
|
|
+ /* 173 */ "REGISTER",
|
|
+ /* 174 */ "VECTOR",
|
|
+ /* 175 */ "SELECT_COLUMN",
|
|
+ /* 176 */ "IF_NULL_ROW",
|
|
+ /* 177 */ "ASTERISK",
|
|
+ /* 178 */ "SPAN",
|
|
+ /* 179 */ "SPACE",
|
|
+ /* 180 */ "ILLEGAL",
|
|
+ /* 181 */ "input",
|
|
+ /* 182 */ "cmdlist",
|
|
+ /* 183 */ "ecmd",
|
|
+ /* 184 */ "cmdx",
|
|
+ /* 185 */ "explain",
|
|
+ /* 186 */ "cmd",
|
|
+ /* 187 */ "transtype",
|
|
+ /* 188 */ "trans_opt",
|
|
+ /* 189 */ "nm",
|
|
+ /* 190 */ "savepoint_opt",
|
|
+ /* 191 */ "create_table",
|
|
+ /* 192 */ "create_table_args",
|
|
+ /* 193 */ "createkw",
|
|
+ /* 194 */ "temp",
|
|
+ /* 195 */ "ifnotexists",
|
|
+ /* 196 */ "dbnm",
|
|
+ /* 197 */ "columnlist",
|
|
+ /* 198 */ "conslist_opt",
|
|
+ /* 199 */ "table_options",
|
|
+ /* 200 */ "select",
|
|
+ /* 201 */ "columnname",
|
|
+ /* 202 */ "carglist",
|
|
+ /* 203 */ "typetoken",
|
|
+ /* 204 */ "typename",
|
|
+ /* 205 */ "signed",
|
|
+ /* 206 */ "plus_num",
|
|
+ /* 207 */ "minus_num",
|
|
+ /* 208 */ "scanpt",
|
|
+ /* 209 */ "scantok",
|
|
+ /* 210 */ "ccons",
|
|
+ /* 211 */ "term",
|
|
+ /* 212 */ "expr",
|
|
+ /* 213 */ "onconf",
|
|
+ /* 214 */ "sortorder",
|
|
+ /* 215 */ "autoinc",
|
|
+ /* 216 */ "eidlist_opt",
|
|
+ /* 217 */ "refargs",
|
|
+ /* 218 */ "defer_subclause",
|
|
+ /* 219 */ "generated",
|
|
+ /* 220 */ "refarg",
|
|
+ /* 221 */ "refact",
|
|
+ /* 222 */ "init_deferred_pred_opt",
|
|
+ /* 223 */ "conslist",
|
|
+ /* 224 */ "tconscomma",
|
|
+ /* 225 */ "tcons",
|
|
+ /* 226 */ "sortlist",
|
|
+ /* 227 */ "eidlist",
|
|
+ /* 228 */ "defer_subclause_opt",
|
|
+ /* 229 */ "orconf",
|
|
+ /* 230 */ "resolvetype",
|
|
+ /* 231 */ "raisetype",
|
|
+ /* 232 */ "ifexists",
|
|
+ /* 233 */ "fullname",
|
|
+ /* 234 */ "selectnowith",
|
|
+ /* 235 */ "oneselect",
|
|
+ /* 236 */ "wqlist",
|
|
+ /* 237 */ "multiselect_op",
|
|
+ /* 238 */ "distinct",
|
|
+ /* 239 */ "selcollist",
|
|
+ /* 240 */ "from",
|
|
+ /* 241 */ "where_opt",
|
|
+ /* 242 */ "groupby_opt",
|
|
+ /* 243 */ "having_opt",
|
|
+ /* 244 */ "orderby_opt",
|
|
+ /* 245 */ "limit_opt",
|
|
+ /* 246 */ "window_clause",
|
|
+ /* 247 */ "values",
|
|
+ /* 248 */ "nexprlist",
|
|
+ /* 249 */ "sclp",
|
|
+ /* 250 */ "as",
|
|
+ /* 251 */ "seltablist",
|
|
+ /* 252 */ "stl_prefix",
|
|
+ /* 253 */ "joinop",
|
|
+ /* 254 */ "indexed_opt",
|
|
+ /* 255 */ "on_opt",
|
|
+ /* 256 */ "using_opt",
|
|
+ /* 257 */ "exprlist",
|
|
+ /* 258 */ "xfullname",
|
|
+ /* 259 */ "idlist",
|
|
+ /* 260 */ "nulls",
|
|
+ /* 261 */ "with",
|
|
+ /* 262 */ "setlist",
|
|
+ /* 263 */ "insert_cmd",
|
|
+ /* 264 */ "idlist_opt",
|
|
+ /* 265 */ "upsert",
|
|
+ /* 266 */ "filter_over",
|
|
+ /* 267 */ "likeop",
|
|
+ /* 268 */ "between_op",
|
|
+ /* 269 */ "in_op",
|
|
+ /* 270 */ "paren_exprlist",
|
|
+ /* 271 */ "case_operand",
|
|
+ /* 272 */ "case_exprlist",
|
|
+ /* 273 */ "case_else",
|
|
+ /* 274 */ "uniqueflag",
|
|
+ /* 275 */ "collate",
|
|
+ /* 276 */ "vinto",
|
|
+ /* 277 */ "nmnum",
|
|
+ /* 278 */ "trigger_decl",
|
|
+ /* 279 */ "trigger_cmd_list",
|
|
+ /* 280 */ "trigger_time",
|
|
+ /* 281 */ "trigger_event",
|
|
+ /* 282 */ "foreach_clause",
|
|
+ /* 283 */ "when_clause",
|
|
+ /* 284 */ "trigger_cmd",
|
|
+ /* 285 */ "trnm",
|
|
+ /* 286 */ "tridxby",
|
|
+ /* 287 */ "database_kw_opt",
|
|
+ /* 288 */ "key_opt",
|
|
+ /* 289 */ "add_column_fullname",
|
|
+ /* 290 */ "kwcolumn_opt",
|
|
+ /* 291 */ "create_vtab",
|
|
+ /* 292 */ "vtabarglist",
|
|
+ /* 293 */ "vtabarg",
|
|
+ /* 294 */ "vtabargtoken",
|
|
+ /* 295 */ "lp",
|
|
+ /* 296 */ "anylist",
|
|
+ /* 297 */ "windowdefn_list",
|
|
+ /* 298 */ "windowdefn",
|
|
+ /* 299 */ "window",
|
|
+ /* 300 */ "frame_opt",
|
|
+ /* 301 */ "part_opt",
|
|
+ /* 302 */ "filter_clause",
|
|
+ /* 303 */ "over_clause",
|
|
+ /* 304 */ "range_or_rows",
|
|
+ /* 305 */ "frame_bound",
|
|
+ /* 306 */ "frame_bound_s",
|
|
+ /* 307 */ "frame_bound_e",
|
|
+ /* 308 */ "frame_exclude_opt",
|
|
+ /* 309 */ "frame_exclude",
|
|
};
|
|
#endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
|
|
|
|
@@ -150203,339 +154989,348 @@
|
|
/* 40 */ "ccons ::= REFERENCES nm eidlist_opt refargs",
|
|
/* 41 */ "ccons ::= defer_subclause",
|
|
/* 42 */ "ccons ::= COLLATE ID|STRING",
|
|
- /* 43 */ "autoinc ::=",
|
|
- /* 44 */ "autoinc ::= AUTOINCR",
|
|
- /* 45 */ "refargs ::=",
|
|
- /* 46 */ "refargs ::= refargs refarg",
|
|
- /* 47 */ "refarg ::= MATCH nm",
|
|
- /* 48 */ "refarg ::= ON INSERT refact",
|
|
- /* 49 */ "refarg ::= ON DELETE refact",
|
|
- /* 50 */ "refarg ::= ON UPDATE refact",
|
|
- /* 51 */ "refact ::= SET NULL",
|
|
- /* 52 */ "refact ::= SET DEFAULT",
|
|
- /* 53 */ "refact ::= CASCADE",
|
|
- /* 54 */ "refact ::= RESTRICT",
|
|
- /* 55 */ "refact ::= NO ACTION",
|
|
- /* 56 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
|
|
- /* 57 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
|
|
- /* 58 */ "init_deferred_pred_opt ::=",
|
|
- /* 59 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
|
|
- /* 60 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
|
|
- /* 61 */ "conslist_opt ::=",
|
|
- /* 62 */ "tconscomma ::= COMMA",
|
|
- /* 63 */ "tcons ::= CONSTRAINT nm",
|
|
- /* 64 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
|
|
- /* 65 */ "tcons ::= UNIQUE LP sortlist RP onconf",
|
|
- /* 66 */ "tcons ::= CHECK LP expr RP onconf",
|
|
- /* 67 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
|
|
- /* 68 */ "defer_subclause_opt ::=",
|
|
- /* 69 */ "onconf ::=",
|
|
- /* 70 */ "onconf ::= ON CONFLICT resolvetype",
|
|
- /* 71 */ "orconf ::=",
|
|
- /* 72 */ "orconf ::= OR resolvetype",
|
|
- /* 73 */ "resolvetype ::= IGNORE",
|
|
- /* 74 */ "resolvetype ::= REPLACE",
|
|
- /* 75 */ "cmd ::= DROP TABLE ifexists fullname",
|
|
- /* 76 */ "ifexists ::= IF EXISTS",
|
|
- /* 77 */ "ifexists ::=",
|
|
- /* 78 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
|
|
- /* 79 */ "cmd ::= DROP VIEW ifexists fullname",
|
|
- /* 80 */ "cmd ::= select",
|
|
- /* 81 */ "select ::= WITH wqlist selectnowith",
|
|
- /* 82 */ "select ::= WITH RECURSIVE wqlist selectnowith",
|
|
- /* 83 */ "select ::= selectnowith",
|
|
- /* 84 */ "selectnowith ::= selectnowith multiselect_op oneselect",
|
|
- /* 85 */ "multiselect_op ::= UNION",
|
|
- /* 86 */ "multiselect_op ::= UNION ALL",
|
|
- /* 87 */ "multiselect_op ::= EXCEPT|INTERSECT",
|
|
- /* 88 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
|
|
- /* 89 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
|
|
- /* 90 */ "values ::= VALUES LP nexprlist RP",
|
|
- /* 91 */ "values ::= values COMMA LP nexprlist RP",
|
|
- /* 92 */ "distinct ::= DISTINCT",
|
|
- /* 93 */ "distinct ::= ALL",
|
|
- /* 94 */ "distinct ::=",
|
|
- /* 95 */ "sclp ::=",
|
|
- /* 96 */ "selcollist ::= sclp scanpt expr scanpt as",
|
|
- /* 97 */ "selcollist ::= sclp scanpt STAR",
|
|
- /* 98 */ "selcollist ::= sclp scanpt nm DOT STAR",
|
|
- /* 99 */ "as ::= AS nm",
|
|
- /* 100 */ "as ::=",
|
|
- /* 101 */ "from ::=",
|
|
- /* 102 */ "from ::= FROM seltablist",
|
|
- /* 103 */ "stl_prefix ::= seltablist joinop",
|
|
- /* 104 */ "stl_prefix ::=",
|
|
- /* 105 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
|
|
- /* 106 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
|
|
- /* 107 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
|
|
- /* 108 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
|
|
- /* 109 */ "dbnm ::=",
|
|
- /* 110 */ "dbnm ::= DOT nm",
|
|
- /* 111 */ "fullname ::= nm",
|
|
- /* 112 */ "fullname ::= nm DOT nm",
|
|
- /* 113 */ "xfullname ::= nm",
|
|
- /* 114 */ "xfullname ::= nm DOT nm",
|
|
- /* 115 */ "xfullname ::= nm DOT nm AS nm",
|
|
- /* 116 */ "xfullname ::= nm AS nm",
|
|
- /* 117 */ "joinop ::= COMMA|JOIN",
|
|
- /* 118 */ "joinop ::= JOIN_KW JOIN",
|
|
- /* 119 */ "joinop ::= JOIN_KW nm JOIN",
|
|
- /* 120 */ "joinop ::= JOIN_KW nm nm JOIN",
|
|
- /* 121 */ "on_opt ::= ON expr",
|
|
- /* 122 */ "on_opt ::=",
|
|
- /* 123 */ "indexed_opt ::=",
|
|
- /* 124 */ "indexed_opt ::= INDEXED BY nm",
|
|
- /* 125 */ "indexed_opt ::= NOT INDEXED",
|
|
- /* 126 */ "using_opt ::= USING LP idlist RP",
|
|
- /* 127 */ "using_opt ::=",
|
|
- /* 128 */ "orderby_opt ::=",
|
|
- /* 129 */ "orderby_opt ::= ORDER BY sortlist",
|
|
- /* 130 */ "sortlist ::= sortlist COMMA expr sortorder",
|
|
- /* 131 */ "sortlist ::= expr sortorder",
|
|
- /* 132 */ "sortorder ::= ASC",
|
|
- /* 133 */ "sortorder ::= DESC",
|
|
- /* 134 */ "sortorder ::=",
|
|
- /* 135 */ "groupby_opt ::=",
|
|
- /* 136 */ "groupby_opt ::= GROUP BY nexprlist",
|
|
- /* 137 */ "having_opt ::=",
|
|
- /* 138 */ "having_opt ::= HAVING expr",
|
|
- /* 139 */ "limit_opt ::=",
|
|
- /* 140 */ "limit_opt ::= LIMIT expr",
|
|
- /* 141 */ "limit_opt ::= LIMIT expr OFFSET expr",
|
|
- /* 142 */ "limit_opt ::= LIMIT expr COMMA expr",
|
|
- /* 143 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
|
|
- /* 144 */ "where_opt ::=",
|
|
- /* 145 */ "where_opt ::= WHERE expr",
|
|
- /* 146 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt",
|
|
- /* 147 */ "setlist ::= setlist COMMA nm EQ expr",
|
|
- /* 148 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
|
|
- /* 149 */ "setlist ::= nm EQ expr",
|
|
- /* 150 */ "setlist ::= LP idlist RP EQ expr",
|
|
- /* 151 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
|
|
- /* 152 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
|
|
- /* 153 */ "upsert ::=",
|
|
- /* 154 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
|
|
- /* 155 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
|
|
- /* 156 */ "upsert ::= ON CONFLICT DO NOTHING",
|
|
- /* 157 */ "insert_cmd ::= INSERT orconf",
|
|
- /* 158 */ "insert_cmd ::= REPLACE",
|
|
- /* 159 */ "idlist_opt ::=",
|
|
- /* 160 */ "idlist_opt ::= LP idlist RP",
|
|
- /* 161 */ "idlist ::= idlist COMMA nm",
|
|
- /* 162 */ "idlist ::= nm",
|
|
- /* 163 */ "expr ::= LP expr RP",
|
|
- /* 164 */ "expr ::= ID|INDEXED",
|
|
- /* 165 */ "expr ::= JOIN_KW",
|
|
- /* 166 */ "expr ::= nm DOT nm",
|
|
- /* 167 */ "expr ::= nm DOT nm DOT nm",
|
|
- /* 168 */ "term ::= NULL|FLOAT|BLOB",
|
|
- /* 169 */ "term ::= STRING",
|
|
- /* 170 */ "term ::= INTEGER",
|
|
- /* 171 */ "expr ::= VARIABLE",
|
|
- /* 172 */ "expr ::= expr COLLATE ID|STRING",
|
|
- /* 173 */ "expr ::= CAST LP expr AS typetoken RP",
|
|
- /* 174 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
|
|
- /* 175 */ "expr ::= ID|INDEXED LP STAR RP",
|
|
- /* 176 */ "expr ::= ID|INDEXED LP distinct exprlist RP over_clause",
|
|
- /* 177 */ "expr ::= ID|INDEXED LP STAR RP over_clause",
|
|
- /* 178 */ "term ::= CTIME_KW",
|
|
- /* 179 */ "expr ::= LP nexprlist COMMA expr RP",
|
|
- /* 180 */ "expr ::= expr AND expr",
|
|
- /* 181 */ "expr ::= expr OR expr",
|
|
- /* 182 */ "expr ::= expr LT|GT|GE|LE expr",
|
|
- /* 183 */ "expr ::= expr EQ|NE expr",
|
|
- /* 184 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
|
|
- /* 185 */ "expr ::= expr PLUS|MINUS expr",
|
|
- /* 186 */ "expr ::= expr STAR|SLASH|REM expr",
|
|
- /* 187 */ "expr ::= expr CONCAT expr",
|
|
- /* 188 */ "likeop ::= NOT LIKE_KW|MATCH",
|
|
- /* 189 */ "expr ::= expr likeop expr",
|
|
- /* 190 */ "expr ::= expr likeop expr ESCAPE expr",
|
|
- /* 191 */ "expr ::= expr ISNULL|NOTNULL",
|
|
- /* 192 */ "expr ::= expr NOT NULL",
|
|
- /* 193 */ "expr ::= expr IS expr",
|
|
- /* 194 */ "expr ::= expr IS NOT expr",
|
|
- /* 195 */ "expr ::= NOT expr",
|
|
- /* 196 */ "expr ::= BITNOT expr",
|
|
- /* 197 */ "expr ::= PLUS|MINUS expr",
|
|
- /* 198 */ "between_op ::= BETWEEN",
|
|
- /* 199 */ "between_op ::= NOT BETWEEN",
|
|
- /* 200 */ "expr ::= expr between_op expr AND expr",
|
|
- /* 201 */ "in_op ::= IN",
|
|
- /* 202 */ "in_op ::= NOT IN",
|
|
- /* 203 */ "expr ::= expr in_op LP exprlist RP",
|
|
- /* 204 */ "expr ::= LP select RP",
|
|
- /* 205 */ "expr ::= expr in_op LP select RP",
|
|
- /* 206 */ "expr ::= expr in_op nm dbnm paren_exprlist",
|
|
- /* 207 */ "expr ::= EXISTS LP select RP",
|
|
- /* 208 */ "expr ::= CASE case_operand case_exprlist case_else END",
|
|
- /* 209 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
|
|
- /* 210 */ "case_exprlist ::= WHEN expr THEN expr",
|
|
- /* 211 */ "case_else ::= ELSE expr",
|
|
- /* 212 */ "case_else ::=",
|
|
- /* 213 */ "case_operand ::= expr",
|
|
- /* 214 */ "case_operand ::=",
|
|
- /* 215 */ "exprlist ::=",
|
|
- /* 216 */ "nexprlist ::= nexprlist COMMA expr",
|
|
- /* 217 */ "nexprlist ::= expr",
|
|
- /* 218 */ "paren_exprlist ::=",
|
|
- /* 219 */ "paren_exprlist ::= LP exprlist RP",
|
|
- /* 220 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
|
|
- /* 221 */ "uniqueflag ::= UNIQUE",
|
|
- /* 222 */ "uniqueflag ::=",
|
|
- /* 223 */ "eidlist_opt ::=",
|
|
- /* 224 */ "eidlist_opt ::= LP eidlist RP",
|
|
- /* 225 */ "eidlist ::= eidlist COMMA nm collate sortorder",
|
|
- /* 226 */ "eidlist ::= nm collate sortorder",
|
|
- /* 227 */ "collate ::=",
|
|
- /* 228 */ "collate ::= COLLATE ID|STRING",
|
|
- /* 229 */ "cmd ::= DROP INDEX ifexists fullname",
|
|
- /* 230 */ "cmd ::= VACUUM vinto",
|
|
- /* 231 */ "cmd ::= VACUUM nm vinto",
|
|
- /* 232 */ "vinto ::= INTO expr",
|
|
- /* 233 */ "vinto ::=",
|
|
- /* 234 */ "cmd ::= PRAGMA nm dbnm",
|
|
- /* 235 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
|
|
- /* 236 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
|
|
- /* 237 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
|
|
- /* 238 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
|
|
- /* 239 */ "plus_num ::= PLUS INTEGER|FLOAT",
|
|
- /* 240 */ "minus_num ::= MINUS INTEGER|FLOAT",
|
|
- /* 241 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
|
|
- /* 242 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
|
|
- /* 243 */ "trigger_time ::= BEFORE|AFTER",
|
|
- /* 244 */ "trigger_time ::= INSTEAD OF",
|
|
- /* 245 */ "trigger_time ::=",
|
|
- /* 246 */ "trigger_event ::= DELETE|INSERT",
|
|
- /* 247 */ "trigger_event ::= UPDATE",
|
|
- /* 248 */ "trigger_event ::= UPDATE OF idlist",
|
|
- /* 249 */ "when_clause ::=",
|
|
- /* 250 */ "when_clause ::= WHEN expr",
|
|
- /* 251 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
|
|
- /* 252 */ "trigger_cmd_list ::= trigger_cmd SEMI",
|
|
- /* 253 */ "trnm ::= nm DOT nm",
|
|
- /* 254 */ "tridxby ::= INDEXED BY nm",
|
|
- /* 255 */ "tridxby ::= NOT INDEXED",
|
|
- /* 256 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
|
|
- /* 257 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
|
|
- /* 258 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
|
|
- /* 259 */ "trigger_cmd ::= scanpt select scanpt",
|
|
- /* 260 */ "expr ::= RAISE LP IGNORE RP",
|
|
- /* 261 */ "expr ::= RAISE LP raisetype COMMA nm RP",
|
|
- /* 262 */ "raisetype ::= ROLLBACK",
|
|
- /* 263 */ "raisetype ::= ABORT",
|
|
- /* 264 */ "raisetype ::= FAIL",
|
|
- /* 265 */ "cmd ::= DROP TRIGGER ifexists fullname",
|
|
- /* 266 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
|
|
- /* 267 */ "cmd ::= DETACH database_kw_opt expr",
|
|
- /* 268 */ "key_opt ::=",
|
|
- /* 269 */ "key_opt ::= KEY expr",
|
|
- /* 270 */ "cmd ::= REINDEX",
|
|
- /* 271 */ "cmd ::= REINDEX nm dbnm",
|
|
- /* 272 */ "cmd ::= ANALYZE",
|
|
- /* 273 */ "cmd ::= ANALYZE nm dbnm",
|
|
- /* 274 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
|
|
- /* 275 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
|
|
- /* 276 */ "add_column_fullname ::= fullname",
|
|
- /* 277 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
|
|
- /* 278 */ "cmd ::= create_vtab",
|
|
- /* 279 */ "cmd ::= create_vtab LP vtabarglist RP",
|
|
- /* 280 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
|
|
- /* 281 */ "vtabarg ::=",
|
|
- /* 282 */ "vtabargtoken ::= ANY",
|
|
- /* 283 */ "vtabargtoken ::= lp anylist RP",
|
|
- /* 284 */ "lp ::= LP",
|
|
- /* 285 */ "with ::= WITH wqlist",
|
|
- /* 286 */ "with ::= WITH RECURSIVE wqlist",
|
|
- /* 287 */ "wqlist ::= nm eidlist_opt AS LP select RP",
|
|
- /* 288 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
|
|
- /* 289 */ "windowdefn_list ::= windowdefn",
|
|
- /* 290 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
|
|
- /* 291 */ "windowdefn ::= nm AS LP window RP",
|
|
- /* 292 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
|
|
- /* 293 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
|
|
- /* 294 */ "window ::= ORDER BY sortlist frame_opt",
|
|
- /* 295 */ "window ::= nm ORDER BY sortlist frame_opt",
|
|
- /* 296 */ "window ::= frame_opt",
|
|
- /* 297 */ "window ::= nm frame_opt",
|
|
- /* 298 */ "frame_opt ::=",
|
|
- /* 299 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
|
|
- /* 300 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
|
|
- /* 301 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
|
|
- /* 302 */ "frame_bound_s ::= frame_bound",
|
|
- /* 303 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
|
|
- /* 304 */ "frame_bound_e ::= frame_bound",
|
|
- /* 305 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
|
|
- /* 306 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
|
|
- /* 307 */ "frame_bound ::= CURRENT ROW",
|
|
- /* 308 */ "frame_exclude_opt ::=",
|
|
- /* 309 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
|
|
- /* 310 */ "frame_exclude ::= NO OTHERS",
|
|
- /* 311 */ "frame_exclude ::= CURRENT ROW",
|
|
- /* 312 */ "frame_exclude ::= GROUP|TIES",
|
|
- /* 313 */ "window_clause ::= WINDOW windowdefn_list",
|
|
- /* 314 */ "over_clause ::= filter_opt OVER LP window RP",
|
|
- /* 315 */ "over_clause ::= filter_opt OVER nm",
|
|
- /* 316 */ "filter_opt ::=",
|
|
- /* 317 */ "filter_opt ::= FILTER LP WHERE expr RP",
|
|
- /* 318 */ "input ::= cmdlist",
|
|
- /* 319 */ "cmdlist ::= cmdlist ecmd",
|
|
- /* 320 */ "cmdlist ::= ecmd",
|
|
- /* 321 */ "ecmd ::= SEMI",
|
|
- /* 322 */ "ecmd ::= cmdx SEMI",
|
|
- /* 323 */ "ecmd ::= explain cmdx",
|
|
- /* 324 */ "trans_opt ::=",
|
|
- /* 325 */ "trans_opt ::= TRANSACTION",
|
|
- /* 326 */ "trans_opt ::= TRANSACTION nm",
|
|
- /* 327 */ "savepoint_opt ::= SAVEPOINT",
|
|
- /* 328 */ "savepoint_opt ::=",
|
|
- /* 329 */ "cmd ::= create_table create_table_args",
|
|
- /* 330 */ "columnlist ::= columnlist COMMA columnname carglist",
|
|
- /* 331 */ "columnlist ::= columnname carglist",
|
|
- /* 332 */ "nm ::= ID|INDEXED",
|
|
- /* 333 */ "nm ::= STRING",
|
|
- /* 334 */ "nm ::= JOIN_KW",
|
|
- /* 335 */ "typetoken ::= typename",
|
|
- /* 336 */ "typename ::= ID|STRING",
|
|
- /* 337 */ "signed ::= plus_num",
|
|
- /* 338 */ "signed ::= minus_num",
|
|
- /* 339 */ "carglist ::= carglist ccons",
|
|
- /* 340 */ "carglist ::=",
|
|
- /* 341 */ "ccons ::= NULL onconf",
|
|
- /* 342 */ "conslist_opt ::= COMMA conslist",
|
|
- /* 343 */ "conslist ::= conslist tconscomma tcons",
|
|
- /* 344 */ "conslist ::= tcons",
|
|
- /* 345 */ "tconscomma ::=",
|
|
- /* 346 */ "defer_subclause_opt ::= defer_subclause",
|
|
- /* 347 */ "resolvetype ::= raisetype",
|
|
- /* 348 */ "selectnowith ::= oneselect",
|
|
- /* 349 */ "oneselect ::= values",
|
|
- /* 350 */ "sclp ::= selcollist COMMA",
|
|
- /* 351 */ "as ::= ID|STRING",
|
|
- /* 352 */ "expr ::= term",
|
|
- /* 353 */ "likeop ::= LIKE_KW|MATCH",
|
|
- /* 354 */ "exprlist ::= nexprlist",
|
|
- /* 355 */ "nmnum ::= plus_num",
|
|
- /* 356 */ "nmnum ::= nm",
|
|
- /* 357 */ "nmnum ::= ON",
|
|
- /* 358 */ "nmnum ::= DELETE",
|
|
- /* 359 */ "nmnum ::= DEFAULT",
|
|
- /* 360 */ "plus_num ::= INTEGER|FLOAT",
|
|
- /* 361 */ "foreach_clause ::=",
|
|
- /* 362 */ "foreach_clause ::= FOR EACH ROW",
|
|
- /* 363 */ "trnm ::= nm",
|
|
- /* 364 */ "tridxby ::=",
|
|
- /* 365 */ "database_kw_opt ::= DATABASE",
|
|
- /* 366 */ "database_kw_opt ::=",
|
|
- /* 367 */ "kwcolumn_opt ::=",
|
|
- /* 368 */ "kwcolumn_opt ::= COLUMNKW",
|
|
- /* 369 */ "vtabarglist ::= vtabarg",
|
|
- /* 370 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
|
|
- /* 371 */ "vtabarg ::= vtabarg vtabargtoken",
|
|
- /* 372 */ "anylist ::=",
|
|
- /* 373 */ "anylist ::= anylist LP anylist RP",
|
|
- /* 374 */ "anylist ::= anylist ANY",
|
|
- /* 375 */ "with ::=",
|
|
+ /* 43 */ "generated ::= LP expr RP",
|
|
+ /* 44 */ "generated ::= LP expr RP ID",
|
|
+ /* 45 */ "autoinc ::=",
|
|
+ /* 46 */ "autoinc ::= AUTOINCR",
|
|
+ /* 47 */ "refargs ::=",
|
|
+ /* 48 */ "refargs ::= refargs refarg",
|
|
+ /* 49 */ "refarg ::= MATCH nm",
|
|
+ /* 50 */ "refarg ::= ON INSERT refact",
|
|
+ /* 51 */ "refarg ::= ON DELETE refact",
|
|
+ /* 52 */ "refarg ::= ON UPDATE refact",
|
|
+ /* 53 */ "refact ::= SET NULL",
|
|
+ /* 54 */ "refact ::= SET DEFAULT",
|
|
+ /* 55 */ "refact ::= CASCADE",
|
|
+ /* 56 */ "refact ::= RESTRICT",
|
|
+ /* 57 */ "refact ::= NO ACTION",
|
|
+ /* 58 */ "defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt",
|
|
+ /* 59 */ "defer_subclause ::= DEFERRABLE init_deferred_pred_opt",
|
|
+ /* 60 */ "init_deferred_pred_opt ::=",
|
|
+ /* 61 */ "init_deferred_pred_opt ::= INITIALLY DEFERRED",
|
|
+ /* 62 */ "init_deferred_pred_opt ::= INITIALLY IMMEDIATE",
|
|
+ /* 63 */ "conslist_opt ::=",
|
|
+ /* 64 */ "tconscomma ::= COMMA",
|
|
+ /* 65 */ "tcons ::= CONSTRAINT nm",
|
|
+ /* 66 */ "tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf",
|
|
+ /* 67 */ "tcons ::= UNIQUE LP sortlist RP onconf",
|
|
+ /* 68 */ "tcons ::= CHECK LP expr RP onconf",
|
|
+ /* 69 */ "tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt",
|
|
+ /* 70 */ "defer_subclause_opt ::=",
|
|
+ /* 71 */ "onconf ::=",
|
|
+ /* 72 */ "onconf ::= ON CONFLICT resolvetype",
|
|
+ /* 73 */ "orconf ::=",
|
|
+ /* 74 */ "orconf ::= OR resolvetype",
|
|
+ /* 75 */ "resolvetype ::= IGNORE",
|
|
+ /* 76 */ "resolvetype ::= REPLACE",
|
|
+ /* 77 */ "cmd ::= DROP TABLE ifexists fullname",
|
|
+ /* 78 */ "ifexists ::= IF EXISTS",
|
|
+ /* 79 */ "ifexists ::=",
|
|
+ /* 80 */ "cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select",
|
|
+ /* 81 */ "cmd ::= DROP VIEW ifexists fullname",
|
|
+ /* 82 */ "cmd ::= select",
|
|
+ /* 83 */ "select ::= WITH wqlist selectnowith",
|
|
+ /* 84 */ "select ::= WITH RECURSIVE wqlist selectnowith",
|
|
+ /* 85 */ "select ::= selectnowith",
|
|
+ /* 86 */ "selectnowith ::= selectnowith multiselect_op oneselect",
|
|
+ /* 87 */ "multiselect_op ::= UNION",
|
|
+ /* 88 */ "multiselect_op ::= UNION ALL",
|
|
+ /* 89 */ "multiselect_op ::= EXCEPT|INTERSECT",
|
|
+ /* 90 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt",
|
|
+ /* 91 */ "oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt",
|
|
+ /* 92 */ "values ::= VALUES LP nexprlist RP",
|
|
+ /* 93 */ "values ::= values COMMA LP nexprlist RP",
|
|
+ /* 94 */ "distinct ::= DISTINCT",
|
|
+ /* 95 */ "distinct ::= ALL",
|
|
+ /* 96 */ "distinct ::=",
|
|
+ /* 97 */ "sclp ::=",
|
|
+ /* 98 */ "selcollist ::= sclp scanpt expr scanpt as",
|
|
+ /* 99 */ "selcollist ::= sclp scanpt STAR",
|
|
+ /* 100 */ "selcollist ::= sclp scanpt nm DOT STAR",
|
|
+ /* 101 */ "as ::= AS nm",
|
|
+ /* 102 */ "as ::=",
|
|
+ /* 103 */ "from ::=",
|
|
+ /* 104 */ "from ::= FROM seltablist",
|
|
+ /* 105 */ "stl_prefix ::= seltablist joinop",
|
|
+ /* 106 */ "stl_prefix ::=",
|
|
+ /* 107 */ "seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt",
|
|
+ /* 108 */ "seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt",
|
|
+ /* 109 */ "seltablist ::= stl_prefix LP select RP as on_opt using_opt",
|
|
+ /* 110 */ "seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt",
|
|
+ /* 111 */ "dbnm ::=",
|
|
+ /* 112 */ "dbnm ::= DOT nm",
|
|
+ /* 113 */ "fullname ::= nm",
|
|
+ /* 114 */ "fullname ::= nm DOT nm",
|
|
+ /* 115 */ "xfullname ::= nm",
|
|
+ /* 116 */ "xfullname ::= nm DOT nm",
|
|
+ /* 117 */ "xfullname ::= nm DOT nm AS nm",
|
|
+ /* 118 */ "xfullname ::= nm AS nm",
|
|
+ /* 119 */ "joinop ::= COMMA|JOIN",
|
|
+ /* 120 */ "joinop ::= JOIN_KW JOIN",
|
|
+ /* 121 */ "joinop ::= JOIN_KW nm JOIN",
|
|
+ /* 122 */ "joinop ::= JOIN_KW nm nm JOIN",
|
|
+ /* 123 */ "on_opt ::= ON expr",
|
|
+ /* 124 */ "on_opt ::=",
|
|
+ /* 125 */ "indexed_opt ::=",
|
|
+ /* 126 */ "indexed_opt ::= INDEXED BY nm",
|
|
+ /* 127 */ "indexed_opt ::= NOT INDEXED",
|
|
+ /* 128 */ "using_opt ::= USING LP idlist RP",
|
|
+ /* 129 */ "using_opt ::=",
|
|
+ /* 130 */ "orderby_opt ::=",
|
|
+ /* 131 */ "orderby_opt ::= ORDER BY sortlist",
|
|
+ /* 132 */ "sortlist ::= sortlist COMMA expr sortorder nulls",
|
|
+ /* 133 */ "sortlist ::= expr sortorder nulls",
|
|
+ /* 134 */ "sortorder ::= ASC",
|
|
+ /* 135 */ "sortorder ::= DESC",
|
|
+ /* 136 */ "sortorder ::=",
|
|
+ /* 137 */ "nulls ::= NULLS FIRST",
|
|
+ /* 138 */ "nulls ::= NULLS LAST",
|
|
+ /* 139 */ "nulls ::=",
|
|
+ /* 140 */ "groupby_opt ::=",
|
|
+ /* 141 */ "groupby_opt ::= GROUP BY nexprlist",
|
|
+ /* 142 */ "having_opt ::=",
|
|
+ /* 143 */ "having_opt ::= HAVING expr",
|
|
+ /* 144 */ "limit_opt ::=",
|
|
+ /* 145 */ "limit_opt ::= LIMIT expr",
|
|
+ /* 146 */ "limit_opt ::= LIMIT expr OFFSET expr",
|
|
+ /* 147 */ "limit_opt ::= LIMIT expr COMMA expr",
|
|
+ /* 148 */ "cmd ::= with DELETE FROM xfullname indexed_opt where_opt",
|
|
+ /* 149 */ "where_opt ::=",
|
|
+ /* 150 */ "where_opt ::= WHERE expr",
|
|
+ /* 151 */ "cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt",
|
|
+ /* 152 */ "setlist ::= setlist COMMA nm EQ expr",
|
|
+ /* 153 */ "setlist ::= setlist COMMA LP idlist RP EQ expr",
|
|
+ /* 154 */ "setlist ::= nm EQ expr",
|
|
+ /* 155 */ "setlist ::= LP idlist RP EQ expr",
|
|
+ /* 156 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert",
|
|
+ /* 157 */ "cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES",
|
|
+ /* 158 */ "upsert ::=",
|
|
+ /* 159 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt",
|
|
+ /* 160 */ "upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING",
|
|
+ /* 161 */ "upsert ::= ON CONFLICT DO NOTHING",
|
|
+ /* 162 */ "insert_cmd ::= INSERT orconf",
|
|
+ /* 163 */ "insert_cmd ::= REPLACE",
|
|
+ /* 164 */ "idlist_opt ::=",
|
|
+ /* 165 */ "idlist_opt ::= LP idlist RP",
|
|
+ /* 166 */ "idlist ::= idlist COMMA nm",
|
|
+ /* 167 */ "idlist ::= nm",
|
|
+ /* 168 */ "expr ::= LP expr RP",
|
|
+ /* 169 */ "expr ::= ID|INDEXED",
|
|
+ /* 170 */ "expr ::= JOIN_KW",
|
|
+ /* 171 */ "expr ::= nm DOT nm",
|
|
+ /* 172 */ "expr ::= nm DOT nm DOT nm",
|
|
+ /* 173 */ "term ::= NULL|FLOAT|BLOB",
|
|
+ /* 174 */ "term ::= STRING",
|
|
+ /* 175 */ "term ::= INTEGER",
|
|
+ /* 176 */ "expr ::= VARIABLE",
|
|
+ /* 177 */ "expr ::= expr COLLATE ID|STRING",
|
|
+ /* 178 */ "expr ::= CAST LP expr AS typetoken RP",
|
|
+ /* 179 */ "expr ::= ID|INDEXED LP distinct exprlist RP",
|
|
+ /* 180 */ "expr ::= ID|INDEXED LP STAR RP",
|
|
+ /* 181 */ "expr ::= ID|INDEXED LP distinct exprlist RP filter_over",
|
|
+ /* 182 */ "expr ::= ID|INDEXED LP STAR RP filter_over",
|
|
+ /* 183 */ "term ::= CTIME_KW",
|
|
+ /* 184 */ "expr ::= LP nexprlist COMMA expr RP",
|
|
+ /* 185 */ "expr ::= expr AND expr",
|
|
+ /* 186 */ "expr ::= expr OR expr",
|
|
+ /* 187 */ "expr ::= expr LT|GT|GE|LE expr",
|
|
+ /* 188 */ "expr ::= expr EQ|NE expr",
|
|
+ /* 189 */ "expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr",
|
|
+ /* 190 */ "expr ::= expr PLUS|MINUS expr",
|
|
+ /* 191 */ "expr ::= expr STAR|SLASH|REM expr",
|
|
+ /* 192 */ "expr ::= expr CONCAT expr",
|
|
+ /* 193 */ "likeop ::= NOT LIKE_KW|MATCH",
|
|
+ /* 194 */ "expr ::= expr likeop expr",
|
|
+ /* 195 */ "expr ::= expr likeop expr ESCAPE expr",
|
|
+ /* 196 */ "expr ::= expr ISNULL|NOTNULL",
|
|
+ /* 197 */ "expr ::= expr NOT NULL",
|
|
+ /* 198 */ "expr ::= expr IS expr",
|
|
+ /* 199 */ "expr ::= expr IS NOT expr",
|
|
+ /* 200 */ "expr ::= NOT expr",
|
|
+ /* 201 */ "expr ::= BITNOT expr",
|
|
+ /* 202 */ "expr ::= PLUS|MINUS expr",
|
|
+ /* 203 */ "between_op ::= BETWEEN",
|
|
+ /* 204 */ "between_op ::= NOT BETWEEN",
|
|
+ /* 205 */ "expr ::= expr between_op expr AND expr",
|
|
+ /* 206 */ "in_op ::= IN",
|
|
+ /* 207 */ "in_op ::= NOT IN",
|
|
+ /* 208 */ "expr ::= expr in_op LP exprlist RP",
|
|
+ /* 209 */ "expr ::= LP select RP",
|
|
+ /* 210 */ "expr ::= expr in_op LP select RP",
|
|
+ /* 211 */ "expr ::= expr in_op nm dbnm paren_exprlist",
|
|
+ /* 212 */ "expr ::= EXISTS LP select RP",
|
|
+ /* 213 */ "expr ::= CASE case_operand case_exprlist case_else END",
|
|
+ /* 214 */ "case_exprlist ::= case_exprlist WHEN expr THEN expr",
|
|
+ /* 215 */ "case_exprlist ::= WHEN expr THEN expr",
|
|
+ /* 216 */ "case_else ::= ELSE expr",
|
|
+ /* 217 */ "case_else ::=",
|
|
+ /* 218 */ "case_operand ::= expr",
|
|
+ /* 219 */ "case_operand ::=",
|
|
+ /* 220 */ "exprlist ::=",
|
|
+ /* 221 */ "nexprlist ::= nexprlist COMMA expr",
|
|
+ /* 222 */ "nexprlist ::= expr",
|
|
+ /* 223 */ "paren_exprlist ::=",
|
|
+ /* 224 */ "paren_exprlist ::= LP exprlist RP",
|
|
+ /* 225 */ "cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt",
|
|
+ /* 226 */ "uniqueflag ::= UNIQUE",
|
|
+ /* 227 */ "uniqueflag ::=",
|
|
+ /* 228 */ "eidlist_opt ::=",
|
|
+ /* 229 */ "eidlist_opt ::= LP eidlist RP",
|
|
+ /* 230 */ "eidlist ::= eidlist COMMA nm collate sortorder",
|
|
+ /* 231 */ "eidlist ::= nm collate sortorder",
|
|
+ /* 232 */ "collate ::=",
|
|
+ /* 233 */ "collate ::= COLLATE ID|STRING",
|
|
+ /* 234 */ "cmd ::= DROP INDEX ifexists fullname",
|
|
+ /* 235 */ "cmd ::= VACUUM vinto",
|
|
+ /* 236 */ "cmd ::= VACUUM nm vinto",
|
|
+ /* 237 */ "vinto ::= INTO expr",
|
|
+ /* 238 */ "vinto ::=",
|
|
+ /* 239 */ "cmd ::= PRAGMA nm dbnm",
|
|
+ /* 240 */ "cmd ::= PRAGMA nm dbnm EQ nmnum",
|
|
+ /* 241 */ "cmd ::= PRAGMA nm dbnm LP nmnum RP",
|
|
+ /* 242 */ "cmd ::= PRAGMA nm dbnm EQ minus_num",
|
|
+ /* 243 */ "cmd ::= PRAGMA nm dbnm LP minus_num RP",
|
|
+ /* 244 */ "plus_num ::= PLUS INTEGER|FLOAT",
|
|
+ /* 245 */ "minus_num ::= MINUS INTEGER|FLOAT",
|
|
+ /* 246 */ "cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END",
|
|
+ /* 247 */ "trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause",
|
|
+ /* 248 */ "trigger_time ::= BEFORE|AFTER",
|
|
+ /* 249 */ "trigger_time ::= INSTEAD OF",
|
|
+ /* 250 */ "trigger_time ::=",
|
|
+ /* 251 */ "trigger_event ::= DELETE|INSERT",
|
|
+ /* 252 */ "trigger_event ::= UPDATE",
|
|
+ /* 253 */ "trigger_event ::= UPDATE OF idlist",
|
|
+ /* 254 */ "when_clause ::=",
|
|
+ /* 255 */ "when_clause ::= WHEN expr",
|
|
+ /* 256 */ "trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI",
|
|
+ /* 257 */ "trigger_cmd_list ::= trigger_cmd SEMI",
|
|
+ /* 258 */ "trnm ::= nm DOT nm",
|
|
+ /* 259 */ "tridxby ::= INDEXED BY nm",
|
|
+ /* 260 */ "tridxby ::= NOT INDEXED",
|
|
+ /* 261 */ "trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt",
|
|
+ /* 262 */ "trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt",
|
|
+ /* 263 */ "trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt",
|
|
+ /* 264 */ "trigger_cmd ::= scanpt select scanpt",
|
|
+ /* 265 */ "expr ::= RAISE LP IGNORE RP",
|
|
+ /* 266 */ "expr ::= RAISE LP raisetype COMMA nm RP",
|
|
+ /* 267 */ "raisetype ::= ROLLBACK",
|
|
+ /* 268 */ "raisetype ::= ABORT",
|
|
+ /* 269 */ "raisetype ::= FAIL",
|
|
+ /* 270 */ "cmd ::= DROP TRIGGER ifexists fullname",
|
|
+ /* 271 */ "cmd ::= ATTACH database_kw_opt expr AS expr key_opt",
|
|
+ /* 272 */ "cmd ::= DETACH database_kw_opt expr",
|
|
+ /* 273 */ "key_opt ::=",
|
|
+ /* 274 */ "key_opt ::= KEY expr",
|
|
+ /* 275 */ "cmd ::= REINDEX",
|
|
+ /* 276 */ "cmd ::= REINDEX nm dbnm",
|
|
+ /* 277 */ "cmd ::= ANALYZE",
|
|
+ /* 278 */ "cmd ::= ANALYZE nm dbnm",
|
|
+ /* 279 */ "cmd ::= ALTER TABLE fullname RENAME TO nm",
|
|
+ /* 280 */ "cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist",
|
|
+ /* 281 */ "add_column_fullname ::= fullname",
|
|
+ /* 282 */ "cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm",
|
|
+ /* 283 */ "cmd ::= create_vtab",
|
|
+ /* 284 */ "cmd ::= create_vtab LP vtabarglist RP",
|
|
+ /* 285 */ "create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm",
|
|
+ /* 286 */ "vtabarg ::=",
|
|
+ /* 287 */ "vtabargtoken ::= ANY",
|
|
+ /* 288 */ "vtabargtoken ::= lp anylist RP",
|
|
+ /* 289 */ "lp ::= LP",
|
|
+ /* 290 */ "with ::= WITH wqlist",
|
|
+ /* 291 */ "with ::= WITH RECURSIVE wqlist",
|
|
+ /* 292 */ "wqlist ::= nm eidlist_opt AS LP select RP",
|
|
+ /* 293 */ "wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP",
|
|
+ /* 294 */ "windowdefn_list ::= windowdefn",
|
|
+ /* 295 */ "windowdefn_list ::= windowdefn_list COMMA windowdefn",
|
|
+ /* 296 */ "windowdefn ::= nm AS LP window RP",
|
|
+ /* 297 */ "window ::= PARTITION BY nexprlist orderby_opt frame_opt",
|
|
+ /* 298 */ "window ::= nm PARTITION BY nexprlist orderby_opt frame_opt",
|
|
+ /* 299 */ "window ::= ORDER BY sortlist frame_opt",
|
|
+ /* 300 */ "window ::= nm ORDER BY sortlist frame_opt",
|
|
+ /* 301 */ "window ::= frame_opt",
|
|
+ /* 302 */ "window ::= nm frame_opt",
|
|
+ /* 303 */ "frame_opt ::=",
|
|
+ /* 304 */ "frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt",
|
|
+ /* 305 */ "frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt",
|
|
+ /* 306 */ "range_or_rows ::= RANGE|ROWS|GROUPS",
|
|
+ /* 307 */ "frame_bound_s ::= frame_bound",
|
|
+ /* 308 */ "frame_bound_s ::= UNBOUNDED PRECEDING",
|
|
+ /* 309 */ "frame_bound_e ::= frame_bound",
|
|
+ /* 310 */ "frame_bound_e ::= UNBOUNDED FOLLOWING",
|
|
+ /* 311 */ "frame_bound ::= expr PRECEDING|FOLLOWING",
|
|
+ /* 312 */ "frame_bound ::= CURRENT ROW",
|
|
+ /* 313 */ "frame_exclude_opt ::=",
|
|
+ /* 314 */ "frame_exclude_opt ::= EXCLUDE frame_exclude",
|
|
+ /* 315 */ "frame_exclude ::= NO OTHERS",
|
|
+ /* 316 */ "frame_exclude ::= CURRENT ROW",
|
|
+ /* 317 */ "frame_exclude ::= GROUP|TIES",
|
|
+ /* 318 */ "window_clause ::= WINDOW windowdefn_list",
|
|
+ /* 319 */ "filter_over ::= filter_clause over_clause",
|
|
+ /* 320 */ "filter_over ::= over_clause",
|
|
+ /* 321 */ "filter_over ::= filter_clause",
|
|
+ /* 322 */ "over_clause ::= OVER LP window RP",
|
|
+ /* 323 */ "over_clause ::= OVER nm",
|
|
+ /* 324 */ "filter_clause ::= FILTER LP WHERE expr RP",
|
|
+ /* 325 */ "input ::= cmdlist",
|
|
+ /* 326 */ "cmdlist ::= cmdlist ecmd",
|
|
+ /* 327 */ "cmdlist ::= ecmd",
|
|
+ /* 328 */ "ecmd ::= SEMI",
|
|
+ /* 329 */ "ecmd ::= cmdx SEMI",
|
|
+ /* 330 */ "ecmd ::= explain cmdx SEMI",
|
|
+ /* 331 */ "trans_opt ::=",
|
|
+ /* 332 */ "trans_opt ::= TRANSACTION",
|
|
+ /* 333 */ "trans_opt ::= TRANSACTION nm",
|
|
+ /* 334 */ "savepoint_opt ::= SAVEPOINT",
|
|
+ /* 335 */ "savepoint_opt ::=",
|
|
+ /* 336 */ "cmd ::= create_table create_table_args",
|
|
+ /* 337 */ "columnlist ::= columnlist COMMA columnname carglist",
|
|
+ /* 338 */ "columnlist ::= columnname carglist",
|
|
+ /* 339 */ "nm ::= ID|INDEXED",
|
|
+ /* 340 */ "nm ::= STRING",
|
|
+ /* 341 */ "nm ::= JOIN_KW",
|
|
+ /* 342 */ "typetoken ::= typename",
|
|
+ /* 343 */ "typename ::= ID|STRING",
|
|
+ /* 344 */ "signed ::= plus_num",
|
|
+ /* 345 */ "signed ::= minus_num",
|
|
+ /* 346 */ "carglist ::= carglist ccons",
|
|
+ /* 347 */ "carglist ::=",
|
|
+ /* 348 */ "ccons ::= NULL onconf",
|
|
+ /* 349 */ "ccons ::= GENERATED ALWAYS AS generated",
|
|
+ /* 350 */ "ccons ::= AS generated",
|
|
+ /* 351 */ "conslist_opt ::= COMMA conslist",
|
|
+ /* 352 */ "conslist ::= conslist tconscomma tcons",
|
|
+ /* 353 */ "conslist ::= tcons",
|
|
+ /* 354 */ "tconscomma ::=",
|
|
+ /* 355 */ "defer_subclause_opt ::= defer_subclause",
|
|
+ /* 356 */ "resolvetype ::= raisetype",
|
|
+ /* 357 */ "selectnowith ::= oneselect",
|
|
+ /* 358 */ "oneselect ::= values",
|
|
+ /* 359 */ "sclp ::= selcollist COMMA",
|
|
+ /* 360 */ "as ::= ID|STRING",
|
|
+ /* 361 */ "expr ::= term",
|
|
+ /* 362 */ "likeop ::= LIKE_KW|MATCH",
|
|
+ /* 363 */ "exprlist ::= nexprlist",
|
|
+ /* 364 */ "nmnum ::= plus_num",
|
|
+ /* 365 */ "nmnum ::= nm",
|
|
+ /* 366 */ "nmnum ::= ON",
|
|
+ /* 367 */ "nmnum ::= DELETE",
|
|
+ /* 368 */ "nmnum ::= DEFAULT",
|
|
+ /* 369 */ "plus_num ::= INTEGER|FLOAT",
|
|
+ /* 370 */ "foreach_clause ::=",
|
|
+ /* 371 */ "foreach_clause ::= FOR EACH ROW",
|
|
+ /* 372 */ "trnm ::= nm",
|
|
+ /* 373 */ "tridxby ::=",
|
|
+ /* 374 */ "database_kw_opt ::= DATABASE",
|
|
+ /* 375 */ "database_kw_opt ::=",
|
|
+ /* 376 */ "kwcolumn_opt ::=",
|
|
+ /* 377 */ "kwcolumn_opt ::= COLUMNKW",
|
|
+ /* 378 */ "vtabarglist ::= vtabarg",
|
|
+ /* 379 */ "vtabarglist ::= vtabarglist COMMA vtabarg",
|
|
+ /* 380 */ "vtabarg ::= vtabarg vtabargtoken",
|
|
+ /* 381 */ "anylist ::=",
|
|
+ /* 382 */ "anylist ::= anylist LP anylist RP",
|
|
+ /* 383 */ "anylist ::= anylist ANY",
|
|
+ /* 384 */ "with ::=",
|
|
};
|
|
#endif /* NDEBUG */
|
|
|
|
@@ -150661,97 +155456,98 @@
|
|
** inside the C code.
|
|
*/
|
|
/********* Begin destructor definitions ***************************************/
|
|
- case 195: /* select */
|
|
- case 228: /* selectnowith */
|
|
- case 229: /* oneselect */
|
|
- case 241: /* values */
|
|
+ case 200: /* select */
|
|
+ case 234: /* selectnowith */
|
|
+ case 235: /* oneselect */
|
|
+ case 247: /* values */
|
|
{
|
|
-sqlite3SelectDelete(pParse->db, (yypminor->yy391));
|
|
+sqlite3SelectDelete(pParse->db, (yypminor->yy539));
|
|
}
|
|
break;
|
|
- case 206: /* term */
|
|
- case 207: /* expr */
|
|
- case 235: /* where_opt */
|
|
- case 237: /* having_opt */
|
|
- case 249: /* on_opt */
|
|
- case 264: /* case_operand */
|
|
- case 266: /* case_else */
|
|
- case 269: /* vinto */
|
|
- case 276: /* when_clause */
|
|
- case 281: /* key_opt */
|
|
- case 295: /* filter_opt */
|
|
+ case 211: /* term */
|
|
+ case 212: /* expr */
|
|
+ case 241: /* where_opt */
|
|
+ case 243: /* having_opt */
|
|
+ case 255: /* on_opt */
|
|
+ case 271: /* case_operand */
|
|
+ case 273: /* case_else */
|
|
+ case 276: /* vinto */
|
|
+ case 283: /* when_clause */
|
|
+ case 288: /* key_opt */
|
|
+ case 302: /* filter_clause */
|
|
{
|
|
-sqlite3ExprDelete(pParse->db, (yypminor->yy102));
|
|
+sqlite3ExprDelete(pParse->db, (yypminor->yy202));
|
|
}
|
|
break;
|
|
- case 211: /* eidlist_opt */
|
|
- case 220: /* sortlist */
|
|
- case 221: /* eidlist */
|
|
- case 233: /* selcollist */
|
|
- case 236: /* groupby_opt */
|
|
- case 238: /* orderby_opt */
|
|
- case 242: /* nexprlist */
|
|
- case 243: /* sclp */
|
|
- case 251: /* exprlist */
|
|
- case 255: /* setlist */
|
|
- case 263: /* paren_exprlist */
|
|
- case 265: /* case_exprlist */
|
|
- case 294: /* part_opt */
|
|
+ case 216: /* eidlist_opt */
|
|
+ case 226: /* sortlist */
|
|
+ case 227: /* eidlist */
|
|
+ case 239: /* selcollist */
|
|
+ case 242: /* groupby_opt */
|
|
+ case 244: /* orderby_opt */
|
|
+ case 248: /* nexprlist */
|
|
+ case 249: /* sclp */
|
|
+ case 257: /* exprlist */
|
|
+ case 262: /* setlist */
|
|
+ case 270: /* paren_exprlist */
|
|
+ case 272: /* case_exprlist */
|
|
+ case 301: /* part_opt */
|
|
{
|
|
-sqlite3ExprListDelete(pParse->db, (yypminor->yy94));
|
|
+sqlite3ExprListDelete(pParse->db, (yypminor->yy242));
|
|
}
|
|
break;
|
|
- case 227: /* fullname */
|
|
- case 234: /* from */
|
|
- case 245: /* seltablist */
|
|
- case 246: /* stl_prefix */
|
|
- case 252: /* xfullname */
|
|
+ case 233: /* fullname */
|
|
+ case 240: /* from */
|
|
+ case 251: /* seltablist */
|
|
+ case 252: /* stl_prefix */
|
|
+ case 258: /* xfullname */
|
|
{
|
|
-sqlite3SrcListDelete(pParse->db, (yypminor->yy407));
|
|
+sqlite3SrcListDelete(pParse->db, (yypminor->yy47));
|
|
}
|
|
break;
|
|
- case 230: /* wqlist */
|
|
+ case 236: /* wqlist */
|
|
{
|
|
-sqlite3WithDelete(pParse->db, (yypminor->yy243));
|
|
+sqlite3WithDelete(pParse->db, (yypminor->yy131));
|
|
}
|
|
break;
|
|
- case 240: /* window_clause */
|
|
- case 290: /* windowdefn_list */
|
|
+ case 246: /* window_clause */
|
|
+ case 297: /* windowdefn_list */
|
|
{
|
|
-sqlite3WindowListDelete(pParse->db, (yypminor->yy379));
|
|
+sqlite3WindowListDelete(pParse->db, (yypminor->yy303));
|
|
}
|
|
break;
|
|
- case 250: /* using_opt */
|
|
- case 253: /* idlist */
|
|
- case 257: /* idlist_opt */
|
|
+ case 256: /* using_opt */
|
|
+ case 259: /* idlist */
|
|
+ case 264: /* idlist_opt */
|
|
{
|
|
-sqlite3IdListDelete(pParse->db, (yypminor->yy76));
|
|
+sqlite3IdListDelete(pParse->db, (yypminor->yy600));
|
|
}
|
|
break;
|
|
- case 259: /* over_clause */
|
|
- case 291: /* windowdefn */
|
|
- case 292: /* window */
|
|
- case 293: /* frame_opt */
|
|
+ case 266: /* filter_over */
|
|
+ case 298: /* windowdefn */
|
|
+ case 299: /* window */
|
|
+ case 300: /* frame_opt */
|
|
+ case 303: /* over_clause */
|
|
{
|
|
-sqlite3WindowDelete(pParse->db, (yypminor->yy379));
|
|
+sqlite3WindowDelete(pParse->db, (yypminor->yy303));
|
|
}
|
|
break;
|
|
- case 272: /* trigger_cmd_list */
|
|
- case 277: /* trigger_cmd */
|
|
+ case 279: /* trigger_cmd_list */
|
|
+ case 284: /* trigger_cmd */
|
|
{
|
|
-sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy11));
|
|
+sqlite3DeleteTriggerStep(pParse->db, (yypminor->yy447));
|
|
}
|
|
break;
|
|
- case 274: /* trigger_event */
|
|
+ case 281: /* trigger_event */
|
|
{
|
|
-sqlite3IdListDelete(pParse->db, (yypminor->yy298).b);
|
|
+sqlite3IdListDelete(pParse->db, (yypminor->yy230).b);
|
|
}
|
|
break;
|
|
- case 297: /* frame_bound */
|
|
- case 298: /* frame_bound_s */
|
|
- case 299: /* frame_bound_e */
|
|
+ case 305: /* frame_bound */
|
|
+ case 306: /* frame_bound_s */
|
|
+ case 307: /* frame_bound_e */
|
|
{
|
|
-sqlite3ExprDelete(pParse->db, (yypminor->yy389).pExpr);
|
|
+sqlite3ExprDelete(pParse->db, (yypminor->yy77).pExpr);
|
|
}
|
|
break;
|
|
/********* End destructor definitions *****************************************/
|
|
@@ -150877,15 +155673,18 @@
|
|
do{
|
|
i = yy_shift_ofst[stateno];
|
|
assert( i>=0 );
|
|
- /* assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD ); */
|
|
+ assert( i<=YY_ACTTAB_COUNT );
|
|
+ assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD );
|
|
assert( iLookAhead!=YYNOCODE );
|
|
assert( iLookAhead < YYNTOKEN );
|
|
i += iLookAhead;
|
|
- if( i>=YY_NLOOKAHEAD || yy_lookahead[i]!=iLookAhead ){
|
|
+ assert( i<(int)YY_NLOOKAHEAD );
|
|
+ if( yy_lookahead[i]!=iLookAhead ){
|
|
#ifdef YYFALLBACK
|
|
YYCODETYPE iFallback; /* Fallback token */
|
|
- if( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0])
|
|
- && (iFallback = yyFallback[iLookAhead])!=0 ){
|
|
+ assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) );
|
|
+ iFallback = yyFallback[iLookAhead];
|
|
+ if( iFallback!=0 ){
|
|
#ifndef NDEBUG
|
|
if( yyTraceFILE ){
|
|
fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
|
|
@@ -150900,16 +155699,8 @@
|
|
#ifdef YYWILDCARD
|
|
{
|
|
int j = i - iLookAhead + YYWILDCARD;
|
|
- if(
|
|
-#if YY_SHIFT_MIN+YYWILDCARD<0
|
|
- j>=0 &&
|
|
-#endif
|
|
-#if YY_SHIFT_MAX+YYWILDCARD>=YY_ACTTAB_COUNT
|
|
- j<YY_ACTTAB_COUNT &&
|
|
-#endif
|
|
- j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) &&
|
|
- yy_lookahead[j]==YYWILDCARD && iLookAhead>0
|
|
- ){
|
|
+ assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) );
|
|
+ if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){
|
|
#ifndef NDEBUG
|
|
if( yyTraceFILE ){
|
|
fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
|
|
@@ -150923,6 +155714,7 @@
|
|
#endif /* YYWILDCARD */
|
|
return yy_default[stateno];
|
|
}else{
|
|
+ assert( i>=0 && i<sizeof(yy_action)/sizeof(yy_action[0]) );
|
|
return yy_action[i];
|
|
}
|
|
}while(1);
|
|
@@ -151046,382 +155838,391 @@
|
|
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
|
|
** of that rule */
|
|
static const YYCODETYPE yyRuleInfoLhs[] = {
|
|
- 180, /* (0) explain ::= EXPLAIN */
|
|
- 180, /* (1) explain ::= EXPLAIN QUERY PLAN */
|
|
- 179, /* (2) cmdx ::= cmd */
|
|
- 181, /* (3) cmd ::= BEGIN transtype trans_opt */
|
|
- 182, /* (4) transtype ::= */
|
|
- 182, /* (5) transtype ::= DEFERRED */
|
|
- 182, /* (6) transtype ::= IMMEDIATE */
|
|
- 182, /* (7) transtype ::= EXCLUSIVE */
|
|
- 181, /* (8) cmd ::= COMMIT|END trans_opt */
|
|
- 181, /* (9) cmd ::= ROLLBACK trans_opt */
|
|
- 181, /* (10) cmd ::= SAVEPOINT nm */
|
|
- 181, /* (11) cmd ::= RELEASE savepoint_opt nm */
|
|
- 181, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
|
|
- 186, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
|
|
- 188, /* (14) createkw ::= CREATE */
|
|
- 190, /* (15) ifnotexists ::= */
|
|
- 190, /* (16) ifnotexists ::= IF NOT EXISTS */
|
|
- 189, /* (17) temp ::= TEMP */
|
|
- 189, /* (18) temp ::= */
|
|
- 187, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
|
|
- 187, /* (20) create_table_args ::= AS select */
|
|
- 194, /* (21) table_options ::= */
|
|
- 194, /* (22) table_options ::= WITHOUT nm */
|
|
- 196, /* (23) columnname ::= nm typetoken */
|
|
- 198, /* (24) typetoken ::= */
|
|
- 198, /* (25) typetoken ::= typename LP signed RP */
|
|
- 198, /* (26) typetoken ::= typename LP signed COMMA signed RP */
|
|
- 199, /* (27) typename ::= typename ID|STRING */
|
|
- 203, /* (28) scanpt ::= */
|
|
- 204, /* (29) scantok ::= */
|
|
- 205, /* (30) ccons ::= CONSTRAINT nm */
|
|
- 205, /* (31) ccons ::= DEFAULT scantok term */
|
|
- 205, /* (32) ccons ::= DEFAULT LP expr RP */
|
|
- 205, /* (33) ccons ::= DEFAULT PLUS scantok term */
|
|
- 205, /* (34) ccons ::= DEFAULT MINUS scantok term */
|
|
- 205, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
|
|
- 205, /* (36) ccons ::= NOT NULL onconf */
|
|
- 205, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
|
|
- 205, /* (38) ccons ::= UNIQUE onconf */
|
|
- 205, /* (39) ccons ::= CHECK LP expr RP */
|
|
- 205, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
|
|
- 205, /* (41) ccons ::= defer_subclause */
|
|
- 205, /* (42) ccons ::= COLLATE ID|STRING */
|
|
- 210, /* (43) autoinc ::= */
|
|
- 210, /* (44) autoinc ::= AUTOINCR */
|
|
- 212, /* (45) refargs ::= */
|
|
- 212, /* (46) refargs ::= refargs refarg */
|
|
- 214, /* (47) refarg ::= MATCH nm */
|
|
- 214, /* (48) refarg ::= ON INSERT refact */
|
|
- 214, /* (49) refarg ::= ON DELETE refact */
|
|
- 214, /* (50) refarg ::= ON UPDATE refact */
|
|
- 215, /* (51) refact ::= SET NULL */
|
|
- 215, /* (52) refact ::= SET DEFAULT */
|
|
- 215, /* (53) refact ::= CASCADE */
|
|
- 215, /* (54) refact ::= RESTRICT */
|
|
- 215, /* (55) refact ::= NO ACTION */
|
|
- 213, /* (56) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
|
|
- 213, /* (57) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
|
|
- 216, /* (58) init_deferred_pred_opt ::= */
|
|
- 216, /* (59) init_deferred_pred_opt ::= INITIALLY DEFERRED */
|
|
- 216, /* (60) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
|
|
- 193, /* (61) conslist_opt ::= */
|
|
- 218, /* (62) tconscomma ::= COMMA */
|
|
- 219, /* (63) tcons ::= CONSTRAINT nm */
|
|
- 219, /* (64) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
|
|
- 219, /* (65) tcons ::= UNIQUE LP sortlist RP onconf */
|
|
- 219, /* (66) tcons ::= CHECK LP expr RP onconf */
|
|
- 219, /* (67) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
|
|
- 222, /* (68) defer_subclause_opt ::= */
|
|
- 208, /* (69) onconf ::= */
|
|
- 208, /* (70) onconf ::= ON CONFLICT resolvetype */
|
|
- 223, /* (71) orconf ::= */
|
|
- 223, /* (72) orconf ::= OR resolvetype */
|
|
- 224, /* (73) resolvetype ::= IGNORE */
|
|
- 224, /* (74) resolvetype ::= REPLACE */
|
|
- 181, /* (75) cmd ::= DROP TABLE ifexists fullname */
|
|
- 226, /* (76) ifexists ::= IF EXISTS */
|
|
- 226, /* (77) ifexists ::= */
|
|
- 181, /* (78) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
|
|
- 181, /* (79) cmd ::= DROP VIEW ifexists fullname */
|
|
- 181, /* (80) cmd ::= select */
|
|
- 195, /* (81) select ::= WITH wqlist selectnowith */
|
|
- 195, /* (82) select ::= WITH RECURSIVE wqlist selectnowith */
|
|
- 195, /* (83) select ::= selectnowith */
|
|
- 228, /* (84) selectnowith ::= selectnowith multiselect_op oneselect */
|
|
- 231, /* (85) multiselect_op ::= UNION */
|
|
- 231, /* (86) multiselect_op ::= UNION ALL */
|
|
- 231, /* (87) multiselect_op ::= EXCEPT|INTERSECT */
|
|
- 229, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
|
|
- 229, /* (89) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
|
|
- 241, /* (90) values ::= VALUES LP nexprlist RP */
|
|
- 241, /* (91) values ::= values COMMA LP nexprlist RP */
|
|
- 232, /* (92) distinct ::= DISTINCT */
|
|
- 232, /* (93) distinct ::= ALL */
|
|
- 232, /* (94) distinct ::= */
|
|
- 243, /* (95) sclp ::= */
|
|
- 233, /* (96) selcollist ::= sclp scanpt expr scanpt as */
|
|
- 233, /* (97) selcollist ::= sclp scanpt STAR */
|
|
- 233, /* (98) selcollist ::= sclp scanpt nm DOT STAR */
|
|
- 244, /* (99) as ::= AS nm */
|
|
- 244, /* (100) as ::= */
|
|
- 234, /* (101) from ::= */
|
|
- 234, /* (102) from ::= FROM seltablist */
|
|
- 246, /* (103) stl_prefix ::= seltablist joinop */
|
|
- 246, /* (104) stl_prefix ::= */
|
|
- 245, /* (105) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
|
|
- 245, /* (106) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
|
|
- 245, /* (107) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
|
|
- 245, /* (108) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
|
|
- 191, /* (109) dbnm ::= */
|
|
- 191, /* (110) dbnm ::= DOT nm */
|
|
- 227, /* (111) fullname ::= nm */
|
|
- 227, /* (112) fullname ::= nm DOT nm */
|
|
- 252, /* (113) xfullname ::= nm */
|
|
- 252, /* (114) xfullname ::= nm DOT nm */
|
|
- 252, /* (115) xfullname ::= nm DOT nm AS nm */
|
|
- 252, /* (116) xfullname ::= nm AS nm */
|
|
- 247, /* (117) joinop ::= COMMA|JOIN */
|
|
- 247, /* (118) joinop ::= JOIN_KW JOIN */
|
|
- 247, /* (119) joinop ::= JOIN_KW nm JOIN */
|
|
- 247, /* (120) joinop ::= JOIN_KW nm nm JOIN */
|
|
- 249, /* (121) on_opt ::= ON expr */
|
|
- 249, /* (122) on_opt ::= */
|
|
- 248, /* (123) indexed_opt ::= */
|
|
- 248, /* (124) indexed_opt ::= INDEXED BY nm */
|
|
- 248, /* (125) indexed_opt ::= NOT INDEXED */
|
|
- 250, /* (126) using_opt ::= USING LP idlist RP */
|
|
- 250, /* (127) using_opt ::= */
|
|
- 238, /* (128) orderby_opt ::= */
|
|
- 238, /* (129) orderby_opt ::= ORDER BY sortlist */
|
|
- 220, /* (130) sortlist ::= sortlist COMMA expr sortorder */
|
|
- 220, /* (131) sortlist ::= expr sortorder */
|
|
- 209, /* (132) sortorder ::= ASC */
|
|
- 209, /* (133) sortorder ::= DESC */
|
|
- 209, /* (134) sortorder ::= */
|
|
- 236, /* (135) groupby_opt ::= */
|
|
- 236, /* (136) groupby_opt ::= GROUP BY nexprlist */
|
|
- 237, /* (137) having_opt ::= */
|
|
- 237, /* (138) having_opt ::= HAVING expr */
|
|
- 239, /* (139) limit_opt ::= */
|
|
- 239, /* (140) limit_opt ::= LIMIT expr */
|
|
- 239, /* (141) limit_opt ::= LIMIT expr OFFSET expr */
|
|
- 239, /* (142) limit_opt ::= LIMIT expr COMMA expr */
|
|
- 181, /* (143) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
|
|
- 235, /* (144) where_opt ::= */
|
|
- 235, /* (145) where_opt ::= WHERE expr */
|
|
- 181, /* (146) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
|
|
- 255, /* (147) setlist ::= setlist COMMA nm EQ expr */
|
|
- 255, /* (148) setlist ::= setlist COMMA LP idlist RP EQ expr */
|
|
- 255, /* (149) setlist ::= nm EQ expr */
|
|
- 255, /* (150) setlist ::= LP idlist RP EQ expr */
|
|
- 181, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
|
|
- 181, /* (152) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
|
|
- 258, /* (153) upsert ::= */
|
|
- 258, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
|
|
- 258, /* (155) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
|
|
- 258, /* (156) upsert ::= ON CONFLICT DO NOTHING */
|
|
- 256, /* (157) insert_cmd ::= INSERT orconf */
|
|
- 256, /* (158) insert_cmd ::= REPLACE */
|
|
- 257, /* (159) idlist_opt ::= */
|
|
- 257, /* (160) idlist_opt ::= LP idlist RP */
|
|
- 253, /* (161) idlist ::= idlist COMMA nm */
|
|
- 253, /* (162) idlist ::= nm */
|
|
- 207, /* (163) expr ::= LP expr RP */
|
|
- 207, /* (164) expr ::= ID|INDEXED */
|
|
- 207, /* (165) expr ::= JOIN_KW */
|
|
- 207, /* (166) expr ::= nm DOT nm */
|
|
- 207, /* (167) expr ::= nm DOT nm DOT nm */
|
|
- 206, /* (168) term ::= NULL|FLOAT|BLOB */
|
|
- 206, /* (169) term ::= STRING */
|
|
- 206, /* (170) term ::= INTEGER */
|
|
- 207, /* (171) expr ::= VARIABLE */
|
|
- 207, /* (172) expr ::= expr COLLATE ID|STRING */
|
|
- 207, /* (173) expr ::= CAST LP expr AS typetoken RP */
|
|
- 207, /* (174) expr ::= ID|INDEXED LP distinct exprlist RP */
|
|
- 207, /* (175) expr ::= ID|INDEXED LP STAR RP */
|
|
- 207, /* (176) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */
|
|
- 207, /* (177) expr ::= ID|INDEXED LP STAR RP over_clause */
|
|
- 206, /* (178) term ::= CTIME_KW */
|
|
- 207, /* (179) expr ::= LP nexprlist COMMA expr RP */
|
|
- 207, /* (180) expr ::= expr AND expr */
|
|
- 207, /* (181) expr ::= expr OR expr */
|
|
- 207, /* (182) expr ::= expr LT|GT|GE|LE expr */
|
|
- 207, /* (183) expr ::= expr EQ|NE expr */
|
|
- 207, /* (184) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
|
|
- 207, /* (185) expr ::= expr PLUS|MINUS expr */
|
|
- 207, /* (186) expr ::= expr STAR|SLASH|REM expr */
|
|
- 207, /* (187) expr ::= expr CONCAT expr */
|
|
- 260, /* (188) likeop ::= NOT LIKE_KW|MATCH */
|
|
- 207, /* (189) expr ::= expr likeop expr */
|
|
- 207, /* (190) expr ::= expr likeop expr ESCAPE expr */
|
|
- 207, /* (191) expr ::= expr ISNULL|NOTNULL */
|
|
- 207, /* (192) expr ::= expr NOT NULL */
|
|
- 207, /* (193) expr ::= expr IS expr */
|
|
- 207, /* (194) expr ::= expr IS NOT expr */
|
|
- 207, /* (195) expr ::= NOT expr */
|
|
- 207, /* (196) expr ::= BITNOT expr */
|
|
- 207, /* (197) expr ::= PLUS|MINUS expr */
|
|
- 261, /* (198) between_op ::= BETWEEN */
|
|
- 261, /* (199) between_op ::= NOT BETWEEN */
|
|
- 207, /* (200) expr ::= expr between_op expr AND expr */
|
|
- 262, /* (201) in_op ::= IN */
|
|
- 262, /* (202) in_op ::= NOT IN */
|
|
- 207, /* (203) expr ::= expr in_op LP exprlist RP */
|
|
- 207, /* (204) expr ::= LP select RP */
|
|
- 207, /* (205) expr ::= expr in_op LP select RP */
|
|
- 207, /* (206) expr ::= expr in_op nm dbnm paren_exprlist */
|
|
- 207, /* (207) expr ::= EXISTS LP select RP */
|
|
- 207, /* (208) expr ::= CASE case_operand case_exprlist case_else END */
|
|
- 265, /* (209) case_exprlist ::= case_exprlist WHEN expr THEN expr */
|
|
- 265, /* (210) case_exprlist ::= WHEN expr THEN expr */
|
|
- 266, /* (211) case_else ::= ELSE expr */
|
|
- 266, /* (212) case_else ::= */
|
|
- 264, /* (213) case_operand ::= expr */
|
|
- 264, /* (214) case_operand ::= */
|
|
- 251, /* (215) exprlist ::= */
|
|
- 242, /* (216) nexprlist ::= nexprlist COMMA expr */
|
|
- 242, /* (217) nexprlist ::= expr */
|
|
- 263, /* (218) paren_exprlist ::= */
|
|
- 263, /* (219) paren_exprlist ::= LP exprlist RP */
|
|
- 181, /* (220) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
|
|
- 267, /* (221) uniqueflag ::= UNIQUE */
|
|
- 267, /* (222) uniqueflag ::= */
|
|
- 211, /* (223) eidlist_opt ::= */
|
|
- 211, /* (224) eidlist_opt ::= LP eidlist RP */
|
|
- 221, /* (225) eidlist ::= eidlist COMMA nm collate sortorder */
|
|
- 221, /* (226) eidlist ::= nm collate sortorder */
|
|
- 268, /* (227) collate ::= */
|
|
- 268, /* (228) collate ::= COLLATE ID|STRING */
|
|
- 181, /* (229) cmd ::= DROP INDEX ifexists fullname */
|
|
- 181, /* (230) cmd ::= VACUUM vinto */
|
|
- 181, /* (231) cmd ::= VACUUM nm vinto */
|
|
- 269, /* (232) vinto ::= INTO expr */
|
|
- 269, /* (233) vinto ::= */
|
|
- 181, /* (234) cmd ::= PRAGMA nm dbnm */
|
|
- 181, /* (235) cmd ::= PRAGMA nm dbnm EQ nmnum */
|
|
- 181, /* (236) cmd ::= PRAGMA nm dbnm LP nmnum RP */
|
|
- 181, /* (237) cmd ::= PRAGMA nm dbnm EQ minus_num */
|
|
- 181, /* (238) cmd ::= PRAGMA nm dbnm LP minus_num RP */
|
|
- 201, /* (239) plus_num ::= PLUS INTEGER|FLOAT */
|
|
- 202, /* (240) minus_num ::= MINUS INTEGER|FLOAT */
|
|
- 181, /* (241) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
|
|
- 271, /* (242) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
|
|
- 273, /* (243) trigger_time ::= BEFORE|AFTER */
|
|
- 273, /* (244) trigger_time ::= INSTEAD OF */
|
|
- 273, /* (245) trigger_time ::= */
|
|
- 274, /* (246) trigger_event ::= DELETE|INSERT */
|
|
- 274, /* (247) trigger_event ::= UPDATE */
|
|
- 274, /* (248) trigger_event ::= UPDATE OF idlist */
|
|
- 276, /* (249) when_clause ::= */
|
|
- 276, /* (250) when_clause ::= WHEN expr */
|
|
- 272, /* (251) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
|
|
- 272, /* (252) trigger_cmd_list ::= trigger_cmd SEMI */
|
|
- 278, /* (253) trnm ::= nm DOT nm */
|
|
- 279, /* (254) tridxby ::= INDEXED BY nm */
|
|
- 279, /* (255) tridxby ::= NOT INDEXED */
|
|
- 277, /* (256) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
|
|
- 277, /* (257) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
|
|
- 277, /* (258) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
|
|
- 277, /* (259) trigger_cmd ::= scanpt select scanpt */
|
|
- 207, /* (260) expr ::= RAISE LP IGNORE RP */
|
|
- 207, /* (261) expr ::= RAISE LP raisetype COMMA nm RP */
|
|
- 225, /* (262) raisetype ::= ROLLBACK */
|
|
- 225, /* (263) raisetype ::= ABORT */
|
|
- 225, /* (264) raisetype ::= FAIL */
|
|
- 181, /* (265) cmd ::= DROP TRIGGER ifexists fullname */
|
|
- 181, /* (266) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
|
|
- 181, /* (267) cmd ::= DETACH database_kw_opt expr */
|
|
- 281, /* (268) key_opt ::= */
|
|
- 281, /* (269) key_opt ::= KEY expr */
|
|
- 181, /* (270) cmd ::= REINDEX */
|
|
- 181, /* (271) cmd ::= REINDEX nm dbnm */
|
|
- 181, /* (272) cmd ::= ANALYZE */
|
|
- 181, /* (273) cmd ::= ANALYZE nm dbnm */
|
|
- 181, /* (274) cmd ::= ALTER TABLE fullname RENAME TO nm */
|
|
- 181, /* (275) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
|
|
- 282, /* (276) add_column_fullname ::= fullname */
|
|
- 181, /* (277) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
|
|
- 181, /* (278) cmd ::= create_vtab */
|
|
- 181, /* (279) cmd ::= create_vtab LP vtabarglist RP */
|
|
- 284, /* (280) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
|
|
- 286, /* (281) vtabarg ::= */
|
|
- 287, /* (282) vtabargtoken ::= ANY */
|
|
- 287, /* (283) vtabargtoken ::= lp anylist RP */
|
|
- 288, /* (284) lp ::= LP */
|
|
- 254, /* (285) with ::= WITH wqlist */
|
|
- 254, /* (286) with ::= WITH RECURSIVE wqlist */
|
|
- 230, /* (287) wqlist ::= nm eidlist_opt AS LP select RP */
|
|
- 230, /* (288) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
|
|
- 290, /* (289) windowdefn_list ::= windowdefn */
|
|
- 290, /* (290) windowdefn_list ::= windowdefn_list COMMA windowdefn */
|
|
- 291, /* (291) windowdefn ::= nm AS LP window RP */
|
|
- 292, /* (292) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
|
|
- 292, /* (293) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
|
|
- 292, /* (294) window ::= ORDER BY sortlist frame_opt */
|
|
- 292, /* (295) window ::= nm ORDER BY sortlist frame_opt */
|
|
- 292, /* (296) window ::= frame_opt */
|
|
- 292, /* (297) window ::= nm frame_opt */
|
|
- 293, /* (298) frame_opt ::= */
|
|
- 293, /* (299) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
|
|
- 293, /* (300) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
|
|
- 296, /* (301) range_or_rows ::= RANGE|ROWS|GROUPS */
|
|
- 298, /* (302) frame_bound_s ::= frame_bound */
|
|
- 298, /* (303) frame_bound_s ::= UNBOUNDED PRECEDING */
|
|
- 299, /* (304) frame_bound_e ::= frame_bound */
|
|
- 299, /* (305) frame_bound_e ::= UNBOUNDED FOLLOWING */
|
|
- 297, /* (306) frame_bound ::= expr PRECEDING|FOLLOWING */
|
|
- 297, /* (307) frame_bound ::= CURRENT ROW */
|
|
- 300, /* (308) frame_exclude_opt ::= */
|
|
- 300, /* (309) frame_exclude_opt ::= EXCLUDE frame_exclude */
|
|
- 301, /* (310) frame_exclude ::= NO OTHERS */
|
|
- 301, /* (311) frame_exclude ::= CURRENT ROW */
|
|
- 301, /* (312) frame_exclude ::= GROUP|TIES */
|
|
- 240, /* (313) window_clause ::= WINDOW windowdefn_list */
|
|
- 259, /* (314) over_clause ::= filter_opt OVER LP window RP */
|
|
- 259, /* (315) over_clause ::= filter_opt OVER nm */
|
|
- 295, /* (316) filter_opt ::= */
|
|
- 295, /* (317) filter_opt ::= FILTER LP WHERE expr RP */
|
|
- 176, /* (318) input ::= cmdlist */
|
|
- 177, /* (319) cmdlist ::= cmdlist ecmd */
|
|
- 177, /* (320) cmdlist ::= ecmd */
|
|
- 178, /* (321) ecmd ::= SEMI */
|
|
- 178, /* (322) ecmd ::= cmdx SEMI */
|
|
- 178, /* (323) ecmd ::= explain cmdx */
|
|
- 183, /* (324) trans_opt ::= */
|
|
- 183, /* (325) trans_opt ::= TRANSACTION */
|
|
- 183, /* (326) trans_opt ::= TRANSACTION nm */
|
|
- 185, /* (327) savepoint_opt ::= SAVEPOINT */
|
|
- 185, /* (328) savepoint_opt ::= */
|
|
- 181, /* (329) cmd ::= create_table create_table_args */
|
|
- 192, /* (330) columnlist ::= columnlist COMMA columnname carglist */
|
|
- 192, /* (331) columnlist ::= columnname carglist */
|
|
- 184, /* (332) nm ::= ID|INDEXED */
|
|
- 184, /* (333) nm ::= STRING */
|
|
- 184, /* (334) nm ::= JOIN_KW */
|
|
- 198, /* (335) typetoken ::= typename */
|
|
- 199, /* (336) typename ::= ID|STRING */
|
|
- 200, /* (337) signed ::= plus_num */
|
|
- 200, /* (338) signed ::= minus_num */
|
|
- 197, /* (339) carglist ::= carglist ccons */
|
|
- 197, /* (340) carglist ::= */
|
|
- 205, /* (341) ccons ::= NULL onconf */
|
|
- 193, /* (342) conslist_opt ::= COMMA conslist */
|
|
- 217, /* (343) conslist ::= conslist tconscomma tcons */
|
|
- 217, /* (344) conslist ::= tcons */
|
|
- 218, /* (345) tconscomma ::= */
|
|
- 222, /* (346) defer_subclause_opt ::= defer_subclause */
|
|
- 224, /* (347) resolvetype ::= raisetype */
|
|
- 228, /* (348) selectnowith ::= oneselect */
|
|
- 229, /* (349) oneselect ::= values */
|
|
- 243, /* (350) sclp ::= selcollist COMMA */
|
|
- 244, /* (351) as ::= ID|STRING */
|
|
- 207, /* (352) expr ::= term */
|
|
- 260, /* (353) likeop ::= LIKE_KW|MATCH */
|
|
- 251, /* (354) exprlist ::= nexprlist */
|
|
- 270, /* (355) nmnum ::= plus_num */
|
|
- 270, /* (356) nmnum ::= nm */
|
|
- 270, /* (357) nmnum ::= ON */
|
|
- 270, /* (358) nmnum ::= DELETE */
|
|
- 270, /* (359) nmnum ::= DEFAULT */
|
|
- 201, /* (360) plus_num ::= INTEGER|FLOAT */
|
|
- 275, /* (361) foreach_clause ::= */
|
|
- 275, /* (362) foreach_clause ::= FOR EACH ROW */
|
|
- 278, /* (363) trnm ::= nm */
|
|
- 279, /* (364) tridxby ::= */
|
|
- 280, /* (365) database_kw_opt ::= DATABASE */
|
|
- 280, /* (366) database_kw_opt ::= */
|
|
- 283, /* (367) kwcolumn_opt ::= */
|
|
- 283, /* (368) kwcolumn_opt ::= COLUMNKW */
|
|
- 285, /* (369) vtabarglist ::= vtabarg */
|
|
- 285, /* (370) vtabarglist ::= vtabarglist COMMA vtabarg */
|
|
- 286, /* (371) vtabarg ::= vtabarg vtabargtoken */
|
|
- 289, /* (372) anylist ::= */
|
|
- 289, /* (373) anylist ::= anylist LP anylist RP */
|
|
- 289, /* (374) anylist ::= anylist ANY */
|
|
- 254, /* (375) with ::= */
|
|
+ 185, /* (0) explain ::= EXPLAIN */
|
|
+ 185, /* (1) explain ::= EXPLAIN QUERY PLAN */
|
|
+ 184, /* (2) cmdx ::= cmd */
|
|
+ 186, /* (3) cmd ::= BEGIN transtype trans_opt */
|
|
+ 187, /* (4) transtype ::= */
|
|
+ 187, /* (5) transtype ::= DEFERRED */
|
|
+ 187, /* (6) transtype ::= IMMEDIATE */
|
|
+ 187, /* (7) transtype ::= EXCLUSIVE */
|
|
+ 186, /* (8) cmd ::= COMMIT|END trans_opt */
|
|
+ 186, /* (9) cmd ::= ROLLBACK trans_opt */
|
|
+ 186, /* (10) cmd ::= SAVEPOINT nm */
|
|
+ 186, /* (11) cmd ::= RELEASE savepoint_opt nm */
|
|
+ 186, /* (12) cmd ::= ROLLBACK trans_opt TO savepoint_opt nm */
|
|
+ 191, /* (13) create_table ::= createkw temp TABLE ifnotexists nm dbnm */
|
|
+ 193, /* (14) createkw ::= CREATE */
|
|
+ 195, /* (15) ifnotexists ::= */
|
|
+ 195, /* (16) ifnotexists ::= IF NOT EXISTS */
|
|
+ 194, /* (17) temp ::= TEMP */
|
|
+ 194, /* (18) temp ::= */
|
|
+ 192, /* (19) create_table_args ::= LP columnlist conslist_opt RP table_options */
|
|
+ 192, /* (20) create_table_args ::= AS select */
|
|
+ 199, /* (21) table_options ::= */
|
|
+ 199, /* (22) table_options ::= WITHOUT nm */
|
|
+ 201, /* (23) columnname ::= nm typetoken */
|
|
+ 203, /* (24) typetoken ::= */
|
|
+ 203, /* (25) typetoken ::= typename LP signed RP */
|
|
+ 203, /* (26) typetoken ::= typename LP signed COMMA signed RP */
|
|
+ 204, /* (27) typename ::= typename ID|STRING */
|
|
+ 208, /* (28) scanpt ::= */
|
|
+ 209, /* (29) scantok ::= */
|
|
+ 210, /* (30) ccons ::= CONSTRAINT nm */
|
|
+ 210, /* (31) ccons ::= DEFAULT scantok term */
|
|
+ 210, /* (32) ccons ::= DEFAULT LP expr RP */
|
|
+ 210, /* (33) ccons ::= DEFAULT PLUS scantok term */
|
|
+ 210, /* (34) ccons ::= DEFAULT MINUS scantok term */
|
|
+ 210, /* (35) ccons ::= DEFAULT scantok ID|INDEXED */
|
|
+ 210, /* (36) ccons ::= NOT NULL onconf */
|
|
+ 210, /* (37) ccons ::= PRIMARY KEY sortorder onconf autoinc */
|
|
+ 210, /* (38) ccons ::= UNIQUE onconf */
|
|
+ 210, /* (39) ccons ::= CHECK LP expr RP */
|
|
+ 210, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
|
|
+ 210, /* (41) ccons ::= defer_subclause */
|
|
+ 210, /* (42) ccons ::= COLLATE ID|STRING */
|
|
+ 219, /* (43) generated ::= LP expr RP */
|
|
+ 219, /* (44) generated ::= LP expr RP ID */
|
|
+ 215, /* (45) autoinc ::= */
|
|
+ 215, /* (46) autoinc ::= AUTOINCR */
|
|
+ 217, /* (47) refargs ::= */
|
|
+ 217, /* (48) refargs ::= refargs refarg */
|
|
+ 220, /* (49) refarg ::= MATCH nm */
|
|
+ 220, /* (50) refarg ::= ON INSERT refact */
|
|
+ 220, /* (51) refarg ::= ON DELETE refact */
|
|
+ 220, /* (52) refarg ::= ON UPDATE refact */
|
|
+ 221, /* (53) refact ::= SET NULL */
|
|
+ 221, /* (54) refact ::= SET DEFAULT */
|
|
+ 221, /* (55) refact ::= CASCADE */
|
|
+ 221, /* (56) refact ::= RESTRICT */
|
|
+ 221, /* (57) refact ::= NO ACTION */
|
|
+ 218, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
|
|
+ 218, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
|
|
+ 222, /* (60) init_deferred_pred_opt ::= */
|
|
+ 222, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
|
|
+ 222, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
|
|
+ 198, /* (63) conslist_opt ::= */
|
|
+ 224, /* (64) tconscomma ::= COMMA */
|
|
+ 225, /* (65) tcons ::= CONSTRAINT nm */
|
|
+ 225, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
|
|
+ 225, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
|
|
+ 225, /* (68) tcons ::= CHECK LP expr RP onconf */
|
|
+ 225, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
|
|
+ 228, /* (70) defer_subclause_opt ::= */
|
|
+ 213, /* (71) onconf ::= */
|
|
+ 213, /* (72) onconf ::= ON CONFLICT resolvetype */
|
|
+ 229, /* (73) orconf ::= */
|
|
+ 229, /* (74) orconf ::= OR resolvetype */
|
|
+ 230, /* (75) resolvetype ::= IGNORE */
|
|
+ 230, /* (76) resolvetype ::= REPLACE */
|
|
+ 186, /* (77) cmd ::= DROP TABLE ifexists fullname */
|
|
+ 232, /* (78) ifexists ::= IF EXISTS */
|
|
+ 232, /* (79) ifexists ::= */
|
|
+ 186, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
|
|
+ 186, /* (81) cmd ::= DROP VIEW ifexists fullname */
|
|
+ 186, /* (82) cmd ::= select */
|
|
+ 200, /* (83) select ::= WITH wqlist selectnowith */
|
|
+ 200, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
|
|
+ 200, /* (85) select ::= selectnowith */
|
|
+ 234, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
|
|
+ 237, /* (87) multiselect_op ::= UNION */
|
|
+ 237, /* (88) multiselect_op ::= UNION ALL */
|
|
+ 237, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
|
|
+ 235, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
|
|
+ 235, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
|
|
+ 247, /* (92) values ::= VALUES LP nexprlist RP */
|
|
+ 247, /* (93) values ::= values COMMA LP nexprlist RP */
|
|
+ 238, /* (94) distinct ::= DISTINCT */
|
|
+ 238, /* (95) distinct ::= ALL */
|
|
+ 238, /* (96) distinct ::= */
|
|
+ 249, /* (97) sclp ::= */
|
|
+ 239, /* (98) selcollist ::= sclp scanpt expr scanpt as */
|
|
+ 239, /* (99) selcollist ::= sclp scanpt STAR */
|
|
+ 239, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
|
|
+ 250, /* (101) as ::= AS nm */
|
|
+ 250, /* (102) as ::= */
|
|
+ 240, /* (103) from ::= */
|
|
+ 240, /* (104) from ::= FROM seltablist */
|
|
+ 252, /* (105) stl_prefix ::= seltablist joinop */
|
|
+ 252, /* (106) stl_prefix ::= */
|
|
+ 251, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
|
|
+ 251, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
|
|
+ 251, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
|
|
+ 251, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
|
|
+ 196, /* (111) dbnm ::= */
|
|
+ 196, /* (112) dbnm ::= DOT nm */
|
|
+ 233, /* (113) fullname ::= nm */
|
|
+ 233, /* (114) fullname ::= nm DOT nm */
|
|
+ 258, /* (115) xfullname ::= nm */
|
|
+ 258, /* (116) xfullname ::= nm DOT nm */
|
|
+ 258, /* (117) xfullname ::= nm DOT nm AS nm */
|
|
+ 258, /* (118) xfullname ::= nm AS nm */
|
|
+ 253, /* (119) joinop ::= COMMA|JOIN */
|
|
+ 253, /* (120) joinop ::= JOIN_KW JOIN */
|
|
+ 253, /* (121) joinop ::= JOIN_KW nm JOIN */
|
|
+ 253, /* (122) joinop ::= JOIN_KW nm nm JOIN */
|
|
+ 255, /* (123) on_opt ::= ON expr */
|
|
+ 255, /* (124) on_opt ::= */
|
|
+ 254, /* (125) indexed_opt ::= */
|
|
+ 254, /* (126) indexed_opt ::= INDEXED BY nm */
|
|
+ 254, /* (127) indexed_opt ::= NOT INDEXED */
|
|
+ 256, /* (128) using_opt ::= USING LP idlist RP */
|
|
+ 256, /* (129) using_opt ::= */
|
|
+ 244, /* (130) orderby_opt ::= */
|
|
+ 244, /* (131) orderby_opt ::= ORDER BY sortlist */
|
|
+ 226, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
|
|
+ 226, /* (133) sortlist ::= expr sortorder nulls */
|
|
+ 214, /* (134) sortorder ::= ASC */
|
|
+ 214, /* (135) sortorder ::= DESC */
|
|
+ 214, /* (136) sortorder ::= */
|
|
+ 260, /* (137) nulls ::= NULLS FIRST */
|
|
+ 260, /* (138) nulls ::= NULLS LAST */
|
|
+ 260, /* (139) nulls ::= */
|
|
+ 242, /* (140) groupby_opt ::= */
|
|
+ 242, /* (141) groupby_opt ::= GROUP BY nexprlist */
|
|
+ 243, /* (142) having_opt ::= */
|
|
+ 243, /* (143) having_opt ::= HAVING expr */
|
|
+ 245, /* (144) limit_opt ::= */
|
|
+ 245, /* (145) limit_opt ::= LIMIT expr */
|
|
+ 245, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
|
|
+ 245, /* (147) limit_opt ::= LIMIT expr COMMA expr */
|
|
+ 186, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
|
|
+ 241, /* (149) where_opt ::= */
|
|
+ 241, /* (150) where_opt ::= WHERE expr */
|
|
+ 186, /* (151) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
|
|
+ 262, /* (152) setlist ::= setlist COMMA nm EQ expr */
|
|
+ 262, /* (153) setlist ::= setlist COMMA LP idlist RP EQ expr */
|
|
+ 262, /* (154) setlist ::= nm EQ expr */
|
|
+ 262, /* (155) setlist ::= LP idlist RP EQ expr */
|
|
+ 186, /* (156) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
|
|
+ 186, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
|
|
+ 265, /* (158) upsert ::= */
|
|
+ 265, /* (159) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
|
|
+ 265, /* (160) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
|
|
+ 265, /* (161) upsert ::= ON CONFLICT DO NOTHING */
|
|
+ 263, /* (162) insert_cmd ::= INSERT orconf */
|
|
+ 263, /* (163) insert_cmd ::= REPLACE */
|
|
+ 264, /* (164) idlist_opt ::= */
|
|
+ 264, /* (165) idlist_opt ::= LP idlist RP */
|
|
+ 259, /* (166) idlist ::= idlist COMMA nm */
|
|
+ 259, /* (167) idlist ::= nm */
|
|
+ 212, /* (168) expr ::= LP expr RP */
|
|
+ 212, /* (169) expr ::= ID|INDEXED */
|
|
+ 212, /* (170) expr ::= JOIN_KW */
|
|
+ 212, /* (171) expr ::= nm DOT nm */
|
|
+ 212, /* (172) expr ::= nm DOT nm DOT nm */
|
|
+ 211, /* (173) term ::= NULL|FLOAT|BLOB */
|
|
+ 211, /* (174) term ::= STRING */
|
|
+ 211, /* (175) term ::= INTEGER */
|
|
+ 212, /* (176) expr ::= VARIABLE */
|
|
+ 212, /* (177) expr ::= expr COLLATE ID|STRING */
|
|
+ 212, /* (178) expr ::= CAST LP expr AS typetoken RP */
|
|
+ 212, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP */
|
|
+ 212, /* (180) expr ::= ID|INDEXED LP STAR RP */
|
|
+ 212, /* (181) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
|
|
+ 212, /* (182) expr ::= ID|INDEXED LP STAR RP filter_over */
|
|
+ 211, /* (183) term ::= CTIME_KW */
|
|
+ 212, /* (184) expr ::= LP nexprlist COMMA expr RP */
|
|
+ 212, /* (185) expr ::= expr AND expr */
|
|
+ 212, /* (186) expr ::= expr OR expr */
|
|
+ 212, /* (187) expr ::= expr LT|GT|GE|LE expr */
|
|
+ 212, /* (188) expr ::= expr EQ|NE expr */
|
|
+ 212, /* (189) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
|
|
+ 212, /* (190) expr ::= expr PLUS|MINUS expr */
|
|
+ 212, /* (191) expr ::= expr STAR|SLASH|REM expr */
|
|
+ 212, /* (192) expr ::= expr CONCAT expr */
|
|
+ 267, /* (193) likeop ::= NOT LIKE_KW|MATCH */
|
|
+ 212, /* (194) expr ::= expr likeop expr */
|
|
+ 212, /* (195) expr ::= expr likeop expr ESCAPE expr */
|
|
+ 212, /* (196) expr ::= expr ISNULL|NOTNULL */
|
|
+ 212, /* (197) expr ::= expr NOT NULL */
|
|
+ 212, /* (198) expr ::= expr IS expr */
|
|
+ 212, /* (199) expr ::= expr IS NOT expr */
|
|
+ 212, /* (200) expr ::= NOT expr */
|
|
+ 212, /* (201) expr ::= BITNOT expr */
|
|
+ 212, /* (202) expr ::= PLUS|MINUS expr */
|
|
+ 268, /* (203) between_op ::= BETWEEN */
|
|
+ 268, /* (204) between_op ::= NOT BETWEEN */
|
|
+ 212, /* (205) expr ::= expr between_op expr AND expr */
|
|
+ 269, /* (206) in_op ::= IN */
|
|
+ 269, /* (207) in_op ::= NOT IN */
|
|
+ 212, /* (208) expr ::= expr in_op LP exprlist RP */
|
|
+ 212, /* (209) expr ::= LP select RP */
|
|
+ 212, /* (210) expr ::= expr in_op LP select RP */
|
|
+ 212, /* (211) expr ::= expr in_op nm dbnm paren_exprlist */
|
|
+ 212, /* (212) expr ::= EXISTS LP select RP */
|
|
+ 212, /* (213) expr ::= CASE case_operand case_exprlist case_else END */
|
|
+ 272, /* (214) case_exprlist ::= case_exprlist WHEN expr THEN expr */
|
|
+ 272, /* (215) case_exprlist ::= WHEN expr THEN expr */
|
|
+ 273, /* (216) case_else ::= ELSE expr */
|
|
+ 273, /* (217) case_else ::= */
|
|
+ 271, /* (218) case_operand ::= expr */
|
|
+ 271, /* (219) case_operand ::= */
|
|
+ 257, /* (220) exprlist ::= */
|
|
+ 248, /* (221) nexprlist ::= nexprlist COMMA expr */
|
|
+ 248, /* (222) nexprlist ::= expr */
|
|
+ 270, /* (223) paren_exprlist ::= */
|
|
+ 270, /* (224) paren_exprlist ::= LP exprlist RP */
|
|
+ 186, /* (225) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
|
|
+ 274, /* (226) uniqueflag ::= UNIQUE */
|
|
+ 274, /* (227) uniqueflag ::= */
|
|
+ 216, /* (228) eidlist_opt ::= */
|
|
+ 216, /* (229) eidlist_opt ::= LP eidlist RP */
|
|
+ 227, /* (230) eidlist ::= eidlist COMMA nm collate sortorder */
|
|
+ 227, /* (231) eidlist ::= nm collate sortorder */
|
|
+ 275, /* (232) collate ::= */
|
|
+ 275, /* (233) collate ::= COLLATE ID|STRING */
|
|
+ 186, /* (234) cmd ::= DROP INDEX ifexists fullname */
|
|
+ 186, /* (235) cmd ::= VACUUM vinto */
|
|
+ 186, /* (236) cmd ::= VACUUM nm vinto */
|
|
+ 276, /* (237) vinto ::= INTO expr */
|
|
+ 276, /* (238) vinto ::= */
|
|
+ 186, /* (239) cmd ::= PRAGMA nm dbnm */
|
|
+ 186, /* (240) cmd ::= PRAGMA nm dbnm EQ nmnum */
|
|
+ 186, /* (241) cmd ::= PRAGMA nm dbnm LP nmnum RP */
|
|
+ 186, /* (242) cmd ::= PRAGMA nm dbnm EQ minus_num */
|
|
+ 186, /* (243) cmd ::= PRAGMA nm dbnm LP minus_num RP */
|
|
+ 206, /* (244) plus_num ::= PLUS INTEGER|FLOAT */
|
|
+ 207, /* (245) minus_num ::= MINUS INTEGER|FLOAT */
|
|
+ 186, /* (246) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
|
|
+ 278, /* (247) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
|
|
+ 280, /* (248) trigger_time ::= BEFORE|AFTER */
|
|
+ 280, /* (249) trigger_time ::= INSTEAD OF */
|
|
+ 280, /* (250) trigger_time ::= */
|
|
+ 281, /* (251) trigger_event ::= DELETE|INSERT */
|
|
+ 281, /* (252) trigger_event ::= UPDATE */
|
|
+ 281, /* (253) trigger_event ::= UPDATE OF idlist */
|
|
+ 283, /* (254) when_clause ::= */
|
|
+ 283, /* (255) when_clause ::= WHEN expr */
|
|
+ 279, /* (256) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
|
|
+ 279, /* (257) trigger_cmd_list ::= trigger_cmd SEMI */
|
|
+ 285, /* (258) trnm ::= nm DOT nm */
|
|
+ 286, /* (259) tridxby ::= INDEXED BY nm */
|
|
+ 286, /* (260) tridxby ::= NOT INDEXED */
|
|
+ 284, /* (261) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
|
|
+ 284, /* (262) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
|
|
+ 284, /* (263) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
|
|
+ 284, /* (264) trigger_cmd ::= scanpt select scanpt */
|
|
+ 212, /* (265) expr ::= RAISE LP IGNORE RP */
|
|
+ 212, /* (266) expr ::= RAISE LP raisetype COMMA nm RP */
|
|
+ 231, /* (267) raisetype ::= ROLLBACK */
|
|
+ 231, /* (268) raisetype ::= ABORT */
|
|
+ 231, /* (269) raisetype ::= FAIL */
|
|
+ 186, /* (270) cmd ::= DROP TRIGGER ifexists fullname */
|
|
+ 186, /* (271) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
|
|
+ 186, /* (272) cmd ::= DETACH database_kw_opt expr */
|
|
+ 288, /* (273) key_opt ::= */
|
|
+ 288, /* (274) key_opt ::= KEY expr */
|
|
+ 186, /* (275) cmd ::= REINDEX */
|
|
+ 186, /* (276) cmd ::= REINDEX nm dbnm */
|
|
+ 186, /* (277) cmd ::= ANALYZE */
|
|
+ 186, /* (278) cmd ::= ANALYZE nm dbnm */
|
|
+ 186, /* (279) cmd ::= ALTER TABLE fullname RENAME TO nm */
|
|
+ 186, /* (280) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
|
|
+ 289, /* (281) add_column_fullname ::= fullname */
|
|
+ 186, /* (282) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
|
|
+ 186, /* (283) cmd ::= create_vtab */
|
|
+ 186, /* (284) cmd ::= create_vtab LP vtabarglist RP */
|
|
+ 291, /* (285) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
|
|
+ 293, /* (286) vtabarg ::= */
|
|
+ 294, /* (287) vtabargtoken ::= ANY */
|
|
+ 294, /* (288) vtabargtoken ::= lp anylist RP */
|
|
+ 295, /* (289) lp ::= LP */
|
|
+ 261, /* (290) with ::= WITH wqlist */
|
|
+ 261, /* (291) with ::= WITH RECURSIVE wqlist */
|
|
+ 236, /* (292) wqlist ::= nm eidlist_opt AS LP select RP */
|
|
+ 236, /* (293) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
|
|
+ 297, /* (294) windowdefn_list ::= windowdefn */
|
|
+ 297, /* (295) windowdefn_list ::= windowdefn_list COMMA windowdefn */
|
|
+ 298, /* (296) windowdefn ::= nm AS LP window RP */
|
|
+ 299, /* (297) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
|
|
+ 299, /* (298) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
|
|
+ 299, /* (299) window ::= ORDER BY sortlist frame_opt */
|
|
+ 299, /* (300) window ::= nm ORDER BY sortlist frame_opt */
|
|
+ 299, /* (301) window ::= frame_opt */
|
|
+ 299, /* (302) window ::= nm frame_opt */
|
|
+ 300, /* (303) frame_opt ::= */
|
|
+ 300, /* (304) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
|
|
+ 300, /* (305) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
|
|
+ 304, /* (306) range_or_rows ::= RANGE|ROWS|GROUPS */
|
|
+ 306, /* (307) frame_bound_s ::= frame_bound */
|
|
+ 306, /* (308) frame_bound_s ::= UNBOUNDED PRECEDING */
|
|
+ 307, /* (309) frame_bound_e ::= frame_bound */
|
|
+ 307, /* (310) frame_bound_e ::= UNBOUNDED FOLLOWING */
|
|
+ 305, /* (311) frame_bound ::= expr PRECEDING|FOLLOWING */
|
|
+ 305, /* (312) frame_bound ::= CURRENT ROW */
|
|
+ 308, /* (313) frame_exclude_opt ::= */
|
|
+ 308, /* (314) frame_exclude_opt ::= EXCLUDE frame_exclude */
|
|
+ 309, /* (315) frame_exclude ::= NO OTHERS */
|
|
+ 309, /* (316) frame_exclude ::= CURRENT ROW */
|
|
+ 309, /* (317) frame_exclude ::= GROUP|TIES */
|
|
+ 246, /* (318) window_clause ::= WINDOW windowdefn_list */
|
|
+ 266, /* (319) filter_over ::= filter_clause over_clause */
|
|
+ 266, /* (320) filter_over ::= over_clause */
|
|
+ 266, /* (321) filter_over ::= filter_clause */
|
|
+ 303, /* (322) over_clause ::= OVER LP window RP */
|
|
+ 303, /* (323) over_clause ::= OVER nm */
|
|
+ 302, /* (324) filter_clause ::= FILTER LP WHERE expr RP */
|
|
+ 181, /* (325) input ::= cmdlist */
|
|
+ 182, /* (326) cmdlist ::= cmdlist ecmd */
|
|
+ 182, /* (327) cmdlist ::= ecmd */
|
|
+ 183, /* (328) ecmd ::= SEMI */
|
|
+ 183, /* (329) ecmd ::= cmdx SEMI */
|
|
+ 183, /* (330) ecmd ::= explain cmdx SEMI */
|
|
+ 188, /* (331) trans_opt ::= */
|
|
+ 188, /* (332) trans_opt ::= TRANSACTION */
|
|
+ 188, /* (333) trans_opt ::= TRANSACTION nm */
|
|
+ 190, /* (334) savepoint_opt ::= SAVEPOINT */
|
|
+ 190, /* (335) savepoint_opt ::= */
|
|
+ 186, /* (336) cmd ::= create_table create_table_args */
|
|
+ 197, /* (337) columnlist ::= columnlist COMMA columnname carglist */
|
|
+ 197, /* (338) columnlist ::= columnname carglist */
|
|
+ 189, /* (339) nm ::= ID|INDEXED */
|
|
+ 189, /* (340) nm ::= STRING */
|
|
+ 189, /* (341) nm ::= JOIN_KW */
|
|
+ 203, /* (342) typetoken ::= typename */
|
|
+ 204, /* (343) typename ::= ID|STRING */
|
|
+ 205, /* (344) signed ::= plus_num */
|
|
+ 205, /* (345) signed ::= minus_num */
|
|
+ 202, /* (346) carglist ::= carglist ccons */
|
|
+ 202, /* (347) carglist ::= */
|
|
+ 210, /* (348) ccons ::= NULL onconf */
|
|
+ 210, /* (349) ccons ::= GENERATED ALWAYS AS generated */
|
|
+ 210, /* (350) ccons ::= AS generated */
|
|
+ 198, /* (351) conslist_opt ::= COMMA conslist */
|
|
+ 223, /* (352) conslist ::= conslist tconscomma tcons */
|
|
+ 223, /* (353) conslist ::= tcons */
|
|
+ 224, /* (354) tconscomma ::= */
|
|
+ 228, /* (355) defer_subclause_opt ::= defer_subclause */
|
|
+ 230, /* (356) resolvetype ::= raisetype */
|
|
+ 234, /* (357) selectnowith ::= oneselect */
|
|
+ 235, /* (358) oneselect ::= values */
|
|
+ 249, /* (359) sclp ::= selcollist COMMA */
|
|
+ 250, /* (360) as ::= ID|STRING */
|
|
+ 212, /* (361) expr ::= term */
|
|
+ 267, /* (362) likeop ::= LIKE_KW|MATCH */
|
|
+ 257, /* (363) exprlist ::= nexprlist */
|
|
+ 277, /* (364) nmnum ::= plus_num */
|
|
+ 277, /* (365) nmnum ::= nm */
|
|
+ 277, /* (366) nmnum ::= ON */
|
|
+ 277, /* (367) nmnum ::= DELETE */
|
|
+ 277, /* (368) nmnum ::= DEFAULT */
|
|
+ 206, /* (369) plus_num ::= INTEGER|FLOAT */
|
|
+ 282, /* (370) foreach_clause ::= */
|
|
+ 282, /* (371) foreach_clause ::= FOR EACH ROW */
|
|
+ 285, /* (372) trnm ::= nm */
|
|
+ 286, /* (373) tridxby ::= */
|
|
+ 287, /* (374) database_kw_opt ::= DATABASE */
|
|
+ 287, /* (375) database_kw_opt ::= */
|
|
+ 290, /* (376) kwcolumn_opt ::= */
|
|
+ 290, /* (377) kwcolumn_opt ::= COLUMNKW */
|
|
+ 292, /* (378) vtabarglist ::= vtabarg */
|
|
+ 292, /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */
|
|
+ 293, /* (380) vtabarg ::= vtabarg vtabargtoken */
|
|
+ 296, /* (381) anylist ::= */
|
|
+ 296, /* (382) anylist ::= anylist LP anylist RP */
|
|
+ 296, /* (383) anylist ::= anylist ANY */
|
|
+ 261, /* (384) with ::= */
|
|
};
|
|
|
|
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
|
|
@@ -151470,339 +156271,348 @@
|
|
-4, /* (40) ccons ::= REFERENCES nm eidlist_opt refargs */
|
|
-1, /* (41) ccons ::= defer_subclause */
|
|
-2, /* (42) ccons ::= COLLATE ID|STRING */
|
|
- 0, /* (43) autoinc ::= */
|
|
- -1, /* (44) autoinc ::= AUTOINCR */
|
|
- 0, /* (45) refargs ::= */
|
|
- -2, /* (46) refargs ::= refargs refarg */
|
|
- -2, /* (47) refarg ::= MATCH nm */
|
|
- -3, /* (48) refarg ::= ON INSERT refact */
|
|
- -3, /* (49) refarg ::= ON DELETE refact */
|
|
- -3, /* (50) refarg ::= ON UPDATE refact */
|
|
- -2, /* (51) refact ::= SET NULL */
|
|
- -2, /* (52) refact ::= SET DEFAULT */
|
|
- -1, /* (53) refact ::= CASCADE */
|
|
- -1, /* (54) refact ::= RESTRICT */
|
|
- -2, /* (55) refact ::= NO ACTION */
|
|
- -3, /* (56) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
|
|
- -2, /* (57) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
|
|
- 0, /* (58) init_deferred_pred_opt ::= */
|
|
- -2, /* (59) init_deferred_pred_opt ::= INITIALLY DEFERRED */
|
|
- -2, /* (60) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
|
|
- 0, /* (61) conslist_opt ::= */
|
|
- -1, /* (62) tconscomma ::= COMMA */
|
|
- -2, /* (63) tcons ::= CONSTRAINT nm */
|
|
- -7, /* (64) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
|
|
- -5, /* (65) tcons ::= UNIQUE LP sortlist RP onconf */
|
|
- -5, /* (66) tcons ::= CHECK LP expr RP onconf */
|
|
- -10, /* (67) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
|
|
- 0, /* (68) defer_subclause_opt ::= */
|
|
- 0, /* (69) onconf ::= */
|
|
- -3, /* (70) onconf ::= ON CONFLICT resolvetype */
|
|
- 0, /* (71) orconf ::= */
|
|
- -2, /* (72) orconf ::= OR resolvetype */
|
|
- -1, /* (73) resolvetype ::= IGNORE */
|
|
- -1, /* (74) resolvetype ::= REPLACE */
|
|
- -4, /* (75) cmd ::= DROP TABLE ifexists fullname */
|
|
- -2, /* (76) ifexists ::= IF EXISTS */
|
|
- 0, /* (77) ifexists ::= */
|
|
- -9, /* (78) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
|
|
- -4, /* (79) cmd ::= DROP VIEW ifexists fullname */
|
|
- -1, /* (80) cmd ::= select */
|
|
- -3, /* (81) select ::= WITH wqlist selectnowith */
|
|
- -4, /* (82) select ::= WITH RECURSIVE wqlist selectnowith */
|
|
- -1, /* (83) select ::= selectnowith */
|
|
- -3, /* (84) selectnowith ::= selectnowith multiselect_op oneselect */
|
|
- -1, /* (85) multiselect_op ::= UNION */
|
|
- -2, /* (86) multiselect_op ::= UNION ALL */
|
|
- -1, /* (87) multiselect_op ::= EXCEPT|INTERSECT */
|
|
- -9, /* (88) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
|
|
- -10, /* (89) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
|
|
- -4, /* (90) values ::= VALUES LP nexprlist RP */
|
|
- -5, /* (91) values ::= values COMMA LP nexprlist RP */
|
|
- -1, /* (92) distinct ::= DISTINCT */
|
|
- -1, /* (93) distinct ::= ALL */
|
|
- 0, /* (94) distinct ::= */
|
|
- 0, /* (95) sclp ::= */
|
|
- -5, /* (96) selcollist ::= sclp scanpt expr scanpt as */
|
|
- -3, /* (97) selcollist ::= sclp scanpt STAR */
|
|
- -5, /* (98) selcollist ::= sclp scanpt nm DOT STAR */
|
|
- -2, /* (99) as ::= AS nm */
|
|
- 0, /* (100) as ::= */
|
|
- 0, /* (101) from ::= */
|
|
- -2, /* (102) from ::= FROM seltablist */
|
|
- -2, /* (103) stl_prefix ::= seltablist joinop */
|
|
- 0, /* (104) stl_prefix ::= */
|
|
- -7, /* (105) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
|
|
- -9, /* (106) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
|
|
- -7, /* (107) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
|
|
- -7, /* (108) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
|
|
- 0, /* (109) dbnm ::= */
|
|
- -2, /* (110) dbnm ::= DOT nm */
|
|
- -1, /* (111) fullname ::= nm */
|
|
- -3, /* (112) fullname ::= nm DOT nm */
|
|
- -1, /* (113) xfullname ::= nm */
|
|
- -3, /* (114) xfullname ::= nm DOT nm */
|
|
- -5, /* (115) xfullname ::= nm DOT nm AS nm */
|
|
- -3, /* (116) xfullname ::= nm AS nm */
|
|
- -1, /* (117) joinop ::= COMMA|JOIN */
|
|
- -2, /* (118) joinop ::= JOIN_KW JOIN */
|
|
- -3, /* (119) joinop ::= JOIN_KW nm JOIN */
|
|
- -4, /* (120) joinop ::= JOIN_KW nm nm JOIN */
|
|
- -2, /* (121) on_opt ::= ON expr */
|
|
- 0, /* (122) on_opt ::= */
|
|
- 0, /* (123) indexed_opt ::= */
|
|
- -3, /* (124) indexed_opt ::= INDEXED BY nm */
|
|
- -2, /* (125) indexed_opt ::= NOT INDEXED */
|
|
- -4, /* (126) using_opt ::= USING LP idlist RP */
|
|
- 0, /* (127) using_opt ::= */
|
|
- 0, /* (128) orderby_opt ::= */
|
|
- -3, /* (129) orderby_opt ::= ORDER BY sortlist */
|
|
- -4, /* (130) sortlist ::= sortlist COMMA expr sortorder */
|
|
- -2, /* (131) sortlist ::= expr sortorder */
|
|
- -1, /* (132) sortorder ::= ASC */
|
|
- -1, /* (133) sortorder ::= DESC */
|
|
- 0, /* (134) sortorder ::= */
|
|
- 0, /* (135) groupby_opt ::= */
|
|
- -3, /* (136) groupby_opt ::= GROUP BY nexprlist */
|
|
- 0, /* (137) having_opt ::= */
|
|
- -2, /* (138) having_opt ::= HAVING expr */
|
|
- 0, /* (139) limit_opt ::= */
|
|
- -2, /* (140) limit_opt ::= LIMIT expr */
|
|
- -4, /* (141) limit_opt ::= LIMIT expr OFFSET expr */
|
|
- -4, /* (142) limit_opt ::= LIMIT expr COMMA expr */
|
|
- -6, /* (143) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
|
|
- 0, /* (144) where_opt ::= */
|
|
- -2, /* (145) where_opt ::= WHERE expr */
|
|
- -8, /* (146) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
|
|
- -5, /* (147) setlist ::= setlist COMMA nm EQ expr */
|
|
- -7, /* (148) setlist ::= setlist COMMA LP idlist RP EQ expr */
|
|
- -3, /* (149) setlist ::= nm EQ expr */
|
|
- -5, /* (150) setlist ::= LP idlist RP EQ expr */
|
|
- -7, /* (151) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
|
|
- -7, /* (152) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
|
|
- 0, /* (153) upsert ::= */
|
|
- -11, /* (154) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
|
|
- -8, /* (155) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
|
|
- -4, /* (156) upsert ::= ON CONFLICT DO NOTHING */
|
|
- -2, /* (157) insert_cmd ::= INSERT orconf */
|
|
- -1, /* (158) insert_cmd ::= REPLACE */
|
|
- 0, /* (159) idlist_opt ::= */
|
|
- -3, /* (160) idlist_opt ::= LP idlist RP */
|
|
- -3, /* (161) idlist ::= idlist COMMA nm */
|
|
- -1, /* (162) idlist ::= nm */
|
|
- -3, /* (163) expr ::= LP expr RP */
|
|
- -1, /* (164) expr ::= ID|INDEXED */
|
|
- -1, /* (165) expr ::= JOIN_KW */
|
|
- -3, /* (166) expr ::= nm DOT nm */
|
|
- -5, /* (167) expr ::= nm DOT nm DOT nm */
|
|
- -1, /* (168) term ::= NULL|FLOAT|BLOB */
|
|
- -1, /* (169) term ::= STRING */
|
|
- -1, /* (170) term ::= INTEGER */
|
|
- -1, /* (171) expr ::= VARIABLE */
|
|
- -3, /* (172) expr ::= expr COLLATE ID|STRING */
|
|
- -6, /* (173) expr ::= CAST LP expr AS typetoken RP */
|
|
- -5, /* (174) expr ::= ID|INDEXED LP distinct exprlist RP */
|
|
- -4, /* (175) expr ::= ID|INDEXED LP STAR RP */
|
|
- -6, /* (176) expr ::= ID|INDEXED LP distinct exprlist RP over_clause */
|
|
- -5, /* (177) expr ::= ID|INDEXED LP STAR RP over_clause */
|
|
- -1, /* (178) term ::= CTIME_KW */
|
|
- -5, /* (179) expr ::= LP nexprlist COMMA expr RP */
|
|
- -3, /* (180) expr ::= expr AND expr */
|
|
- -3, /* (181) expr ::= expr OR expr */
|
|
- -3, /* (182) expr ::= expr LT|GT|GE|LE expr */
|
|
- -3, /* (183) expr ::= expr EQ|NE expr */
|
|
- -3, /* (184) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
|
|
- -3, /* (185) expr ::= expr PLUS|MINUS expr */
|
|
- -3, /* (186) expr ::= expr STAR|SLASH|REM expr */
|
|
- -3, /* (187) expr ::= expr CONCAT expr */
|
|
- -2, /* (188) likeop ::= NOT LIKE_KW|MATCH */
|
|
- -3, /* (189) expr ::= expr likeop expr */
|
|
- -5, /* (190) expr ::= expr likeop expr ESCAPE expr */
|
|
- -2, /* (191) expr ::= expr ISNULL|NOTNULL */
|
|
- -3, /* (192) expr ::= expr NOT NULL */
|
|
- -3, /* (193) expr ::= expr IS expr */
|
|
- -4, /* (194) expr ::= expr IS NOT expr */
|
|
- -2, /* (195) expr ::= NOT expr */
|
|
- -2, /* (196) expr ::= BITNOT expr */
|
|
- -2, /* (197) expr ::= PLUS|MINUS expr */
|
|
- -1, /* (198) between_op ::= BETWEEN */
|
|
- -2, /* (199) between_op ::= NOT BETWEEN */
|
|
- -5, /* (200) expr ::= expr between_op expr AND expr */
|
|
- -1, /* (201) in_op ::= IN */
|
|
- -2, /* (202) in_op ::= NOT IN */
|
|
- -5, /* (203) expr ::= expr in_op LP exprlist RP */
|
|
- -3, /* (204) expr ::= LP select RP */
|
|
- -5, /* (205) expr ::= expr in_op LP select RP */
|
|
- -5, /* (206) expr ::= expr in_op nm dbnm paren_exprlist */
|
|
- -4, /* (207) expr ::= EXISTS LP select RP */
|
|
- -5, /* (208) expr ::= CASE case_operand case_exprlist case_else END */
|
|
- -5, /* (209) case_exprlist ::= case_exprlist WHEN expr THEN expr */
|
|
- -4, /* (210) case_exprlist ::= WHEN expr THEN expr */
|
|
- -2, /* (211) case_else ::= ELSE expr */
|
|
- 0, /* (212) case_else ::= */
|
|
- -1, /* (213) case_operand ::= expr */
|
|
- 0, /* (214) case_operand ::= */
|
|
- 0, /* (215) exprlist ::= */
|
|
- -3, /* (216) nexprlist ::= nexprlist COMMA expr */
|
|
- -1, /* (217) nexprlist ::= expr */
|
|
- 0, /* (218) paren_exprlist ::= */
|
|
- -3, /* (219) paren_exprlist ::= LP exprlist RP */
|
|
- -12, /* (220) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
|
|
- -1, /* (221) uniqueflag ::= UNIQUE */
|
|
- 0, /* (222) uniqueflag ::= */
|
|
- 0, /* (223) eidlist_opt ::= */
|
|
- -3, /* (224) eidlist_opt ::= LP eidlist RP */
|
|
- -5, /* (225) eidlist ::= eidlist COMMA nm collate sortorder */
|
|
- -3, /* (226) eidlist ::= nm collate sortorder */
|
|
- 0, /* (227) collate ::= */
|
|
- -2, /* (228) collate ::= COLLATE ID|STRING */
|
|
- -4, /* (229) cmd ::= DROP INDEX ifexists fullname */
|
|
- -2, /* (230) cmd ::= VACUUM vinto */
|
|
- -3, /* (231) cmd ::= VACUUM nm vinto */
|
|
- -2, /* (232) vinto ::= INTO expr */
|
|
- 0, /* (233) vinto ::= */
|
|
- -3, /* (234) cmd ::= PRAGMA nm dbnm */
|
|
- -5, /* (235) cmd ::= PRAGMA nm dbnm EQ nmnum */
|
|
- -6, /* (236) cmd ::= PRAGMA nm dbnm LP nmnum RP */
|
|
- -5, /* (237) cmd ::= PRAGMA nm dbnm EQ minus_num */
|
|
- -6, /* (238) cmd ::= PRAGMA nm dbnm LP minus_num RP */
|
|
- -2, /* (239) plus_num ::= PLUS INTEGER|FLOAT */
|
|
- -2, /* (240) minus_num ::= MINUS INTEGER|FLOAT */
|
|
- -5, /* (241) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
|
|
- -11, /* (242) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
|
|
- -1, /* (243) trigger_time ::= BEFORE|AFTER */
|
|
- -2, /* (244) trigger_time ::= INSTEAD OF */
|
|
- 0, /* (245) trigger_time ::= */
|
|
- -1, /* (246) trigger_event ::= DELETE|INSERT */
|
|
- -1, /* (247) trigger_event ::= UPDATE */
|
|
- -3, /* (248) trigger_event ::= UPDATE OF idlist */
|
|
- 0, /* (249) when_clause ::= */
|
|
- -2, /* (250) when_clause ::= WHEN expr */
|
|
- -3, /* (251) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
|
|
- -2, /* (252) trigger_cmd_list ::= trigger_cmd SEMI */
|
|
- -3, /* (253) trnm ::= nm DOT nm */
|
|
- -3, /* (254) tridxby ::= INDEXED BY nm */
|
|
- -2, /* (255) tridxby ::= NOT INDEXED */
|
|
- -8, /* (256) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
|
|
- -8, /* (257) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
|
|
- -6, /* (258) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
|
|
- -3, /* (259) trigger_cmd ::= scanpt select scanpt */
|
|
- -4, /* (260) expr ::= RAISE LP IGNORE RP */
|
|
- -6, /* (261) expr ::= RAISE LP raisetype COMMA nm RP */
|
|
- -1, /* (262) raisetype ::= ROLLBACK */
|
|
- -1, /* (263) raisetype ::= ABORT */
|
|
- -1, /* (264) raisetype ::= FAIL */
|
|
- -4, /* (265) cmd ::= DROP TRIGGER ifexists fullname */
|
|
- -6, /* (266) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
|
|
- -3, /* (267) cmd ::= DETACH database_kw_opt expr */
|
|
- 0, /* (268) key_opt ::= */
|
|
- -2, /* (269) key_opt ::= KEY expr */
|
|
- -1, /* (270) cmd ::= REINDEX */
|
|
- -3, /* (271) cmd ::= REINDEX nm dbnm */
|
|
- -1, /* (272) cmd ::= ANALYZE */
|
|
- -3, /* (273) cmd ::= ANALYZE nm dbnm */
|
|
- -6, /* (274) cmd ::= ALTER TABLE fullname RENAME TO nm */
|
|
- -7, /* (275) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
|
|
- -1, /* (276) add_column_fullname ::= fullname */
|
|
- -8, /* (277) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
|
|
- -1, /* (278) cmd ::= create_vtab */
|
|
- -4, /* (279) cmd ::= create_vtab LP vtabarglist RP */
|
|
- -8, /* (280) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
|
|
- 0, /* (281) vtabarg ::= */
|
|
- -1, /* (282) vtabargtoken ::= ANY */
|
|
- -3, /* (283) vtabargtoken ::= lp anylist RP */
|
|
- -1, /* (284) lp ::= LP */
|
|
- -2, /* (285) with ::= WITH wqlist */
|
|
- -3, /* (286) with ::= WITH RECURSIVE wqlist */
|
|
- -6, /* (287) wqlist ::= nm eidlist_opt AS LP select RP */
|
|
- -8, /* (288) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
|
|
- -1, /* (289) windowdefn_list ::= windowdefn */
|
|
- -3, /* (290) windowdefn_list ::= windowdefn_list COMMA windowdefn */
|
|
- -5, /* (291) windowdefn ::= nm AS LP window RP */
|
|
- -5, /* (292) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
|
|
- -6, /* (293) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
|
|
- -4, /* (294) window ::= ORDER BY sortlist frame_opt */
|
|
- -5, /* (295) window ::= nm ORDER BY sortlist frame_opt */
|
|
- -1, /* (296) window ::= frame_opt */
|
|
- -2, /* (297) window ::= nm frame_opt */
|
|
- 0, /* (298) frame_opt ::= */
|
|
- -3, /* (299) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
|
|
- -6, /* (300) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
|
|
- -1, /* (301) range_or_rows ::= RANGE|ROWS|GROUPS */
|
|
- -1, /* (302) frame_bound_s ::= frame_bound */
|
|
- -2, /* (303) frame_bound_s ::= UNBOUNDED PRECEDING */
|
|
- -1, /* (304) frame_bound_e ::= frame_bound */
|
|
- -2, /* (305) frame_bound_e ::= UNBOUNDED FOLLOWING */
|
|
- -2, /* (306) frame_bound ::= expr PRECEDING|FOLLOWING */
|
|
- -2, /* (307) frame_bound ::= CURRENT ROW */
|
|
- 0, /* (308) frame_exclude_opt ::= */
|
|
- -2, /* (309) frame_exclude_opt ::= EXCLUDE frame_exclude */
|
|
- -2, /* (310) frame_exclude ::= NO OTHERS */
|
|
- -2, /* (311) frame_exclude ::= CURRENT ROW */
|
|
- -1, /* (312) frame_exclude ::= GROUP|TIES */
|
|
- -2, /* (313) window_clause ::= WINDOW windowdefn_list */
|
|
- -5, /* (314) over_clause ::= filter_opt OVER LP window RP */
|
|
- -3, /* (315) over_clause ::= filter_opt OVER nm */
|
|
- 0, /* (316) filter_opt ::= */
|
|
- -5, /* (317) filter_opt ::= FILTER LP WHERE expr RP */
|
|
- -1, /* (318) input ::= cmdlist */
|
|
- -2, /* (319) cmdlist ::= cmdlist ecmd */
|
|
- -1, /* (320) cmdlist ::= ecmd */
|
|
- -1, /* (321) ecmd ::= SEMI */
|
|
- -2, /* (322) ecmd ::= cmdx SEMI */
|
|
- -2, /* (323) ecmd ::= explain cmdx */
|
|
- 0, /* (324) trans_opt ::= */
|
|
- -1, /* (325) trans_opt ::= TRANSACTION */
|
|
- -2, /* (326) trans_opt ::= TRANSACTION nm */
|
|
- -1, /* (327) savepoint_opt ::= SAVEPOINT */
|
|
- 0, /* (328) savepoint_opt ::= */
|
|
- -2, /* (329) cmd ::= create_table create_table_args */
|
|
- -4, /* (330) columnlist ::= columnlist COMMA columnname carglist */
|
|
- -2, /* (331) columnlist ::= columnname carglist */
|
|
- -1, /* (332) nm ::= ID|INDEXED */
|
|
- -1, /* (333) nm ::= STRING */
|
|
- -1, /* (334) nm ::= JOIN_KW */
|
|
- -1, /* (335) typetoken ::= typename */
|
|
- -1, /* (336) typename ::= ID|STRING */
|
|
- -1, /* (337) signed ::= plus_num */
|
|
- -1, /* (338) signed ::= minus_num */
|
|
- -2, /* (339) carglist ::= carglist ccons */
|
|
- 0, /* (340) carglist ::= */
|
|
- -2, /* (341) ccons ::= NULL onconf */
|
|
- -2, /* (342) conslist_opt ::= COMMA conslist */
|
|
- -3, /* (343) conslist ::= conslist tconscomma tcons */
|
|
- -1, /* (344) conslist ::= tcons */
|
|
- 0, /* (345) tconscomma ::= */
|
|
- -1, /* (346) defer_subclause_opt ::= defer_subclause */
|
|
- -1, /* (347) resolvetype ::= raisetype */
|
|
- -1, /* (348) selectnowith ::= oneselect */
|
|
- -1, /* (349) oneselect ::= values */
|
|
- -2, /* (350) sclp ::= selcollist COMMA */
|
|
- -1, /* (351) as ::= ID|STRING */
|
|
- -1, /* (352) expr ::= term */
|
|
- -1, /* (353) likeop ::= LIKE_KW|MATCH */
|
|
- -1, /* (354) exprlist ::= nexprlist */
|
|
- -1, /* (355) nmnum ::= plus_num */
|
|
- -1, /* (356) nmnum ::= nm */
|
|
- -1, /* (357) nmnum ::= ON */
|
|
- -1, /* (358) nmnum ::= DELETE */
|
|
- -1, /* (359) nmnum ::= DEFAULT */
|
|
- -1, /* (360) plus_num ::= INTEGER|FLOAT */
|
|
- 0, /* (361) foreach_clause ::= */
|
|
- -3, /* (362) foreach_clause ::= FOR EACH ROW */
|
|
- -1, /* (363) trnm ::= nm */
|
|
- 0, /* (364) tridxby ::= */
|
|
- -1, /* (365) database_kw_opt ::= DATABASE */
|
|
- 0, /* (366) database_kw_opt ::= */
|
|
- 0, /* (367) kwcolumn_opt ::= */
|
|
- -1, /* (368) kwcolumn_opt ::= COLUMNKW */
|
|
- -1, /* (369) vtabarglist ::= vtabarg */
|
|
- -3, /* (370) vtabarglist ::= vtabarglist COMMA vtabarg */
|
|
- -2, /* (371) vtabarg ::= vtabarg vtabargtoken */
|
|
- 0, /* (372) anylist ::= */
|
|
- -4, /* (373) anylist ::= anylist LP anylist RP */
|
|
- -2, /* (374) anylist ::= anylist ANY */
|
|
- 0, /* (375) with ::= */
|
|
+ -3, /* (43) generated ::= LP expr RP */
|
|
+ -4, /* (44) generated ::= LP expr RP ID */
|
|
+ 0, /* (45) autoinc ::= */
|
|
+ -1, /* (46) autoinc ::= AUTOINCR */
|
|
+ 0, /* (47) refargs ::= */
|
|
+ -2, /* (48) refargs ::= refargs refarg */
|
|
+ -2, /* (49) refarg ::= MATCH nm */
|
|
+ -3, /* (50) refarg ::= ON INSERT refact */
|
|
+ -3, /* (51) refarg ::= ON DELETE refact */
|
|
+ -3, /* (52) refarg ::= ON UPDATE refact */
|
|
+ -2, /* (53) refact ::= SET NULL */
|
|
+ -2, /* (54) refact ::= SET DEFAULT */
|
|
+ -1, /* (55) refact ::= CASCADE */
|
|
+ -1, /* (56) refact ::= RESTRICT */
|
|
+ -2, /* (57) refact ::= NO ACTION */
|
|
+ -3, /* (58) defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
|
|
+ -2, /* (59) defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
|
|
+ 0, /* (60) init_deferred_pred_opt ::= */
|
|
+ -2, /* (61) init_deferred_pred_opt ::= INITIALLY DEFERRED */
|
|
+ -2, /* (62) init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
|
|
+ 0, /* (63) conslist_opt ::= */
|
|
+ -1, /* (64) tconscomma ::= COMMA */
|
|
+ -2, /* (65) tcons ::= CONSTRAINT nm */
|
|
+ -7, /* (66) tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
|
|
+ -5, /* (67) tcons ::= UNIQUE LP sortlist RP onconf */
|
|
+ -5, /* (68) tcons ::= CHECK LP expr RP onconf */
|
|
+ -10, /* (69) tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
|
|
+ 0, /* (70) defer_subclause_opt ::= */
|
|
+ 0, /* (71) onconf ::= */
|
|
+ -3, /* (72) onconf ::= ON CONFLICT resolvetype */
|
|
+ 0, /* (73) orconf ::= */
|
|
+ -2, /* (74) orconf ::= OR resolvetype */
|
|
+ -1, /* (75) resolvetype ::= IGNORE */
|
|
+ -1, /* (76) resolvetype ::= REPLACE */
|
|
+ -4, /* (77) cmd ::= DROP TABLE ifexists fullname */
|
|
+ -2, /* (78) ifexists ::= IF EXISTS */
|
|
+ 0, /* (79) ifexists ::= */
|
|
+ -9, /* (80) cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
|
|
+ -4, /* (81) cmd ::= DROP VIEW ifexists fullname */
|
|
+ -1, /* (82) cmd ::= select */
|
|
+ -3, /* (83) select ::= WITH wqlist selectnowith */
|
|
+ -4, /* (84) select ::= WITH RECURSIVE wqlist selectnowith */
|
|
+ -1, /* (85) select ::= selectnowith */
|
|
+ -3, /* (86) selectnowith ::= selectnowith multiselect_op oneselect */
|
|
+ -1, /* (87) multiselect_op ::= UNION */
|
|
+ -2, /* (88) multiselect_op ::= UNION ALL */
|
|
+ -1, /* (89) multiselect_op ::= EXCEPT|INTERSECT */
|
|
+ -9, /* (90) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
|
|
+ -10, /* (91) oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
|
|
+ -4, /* (92) values ::= VALUES LP nexprlist RP */
|
|
+ -5, /* (93) values ::= values COMMA LP nexprlist RP */
|
|
+ -1, /* (94) distinct ::= DISTINCT */
|
|
+ -1, /* (95) distinct ::= ALL */
|
|
+ 0, /* (96) distinct ::= */
|
|
+ 0, /* (97) sclp ::= */
|
|
+ -5, /* (98) selcollist ::= sclp scanpt expr scanpt as */
|
|
+ -3, /* (99) selcollist ::= sclp scanpt STAR */
|
|
+ -5, /* (100) selcollist ::= sclp scanpt nm DOT STAR */
|
|
+ -2, /* (101) as ::= AS nm */
|
|
+ 0, /* (102) as ::= */
|
|
+ 0, /* (103) from ::= */
|
|
+ -2, /* (104) from ::= FROM seltablist */
|
|
+ -2, /* (105) stl_prefix ::= seltablist joinop */
|
|
+ 0, /* (106) stl_prefix ::= */
|
|
+ -7, /* (107) seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
|
|
+ -9, /* (108) seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
|
|
+ -7, /* (109) seltablist ::= stl_prefix LP select RP as on_opt using_opt */
|
|
+ -7, /* (110) seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
|
|
+ 0, /* (111) dbnm ::= */
|
|
+ -2, /* (112) dbnm ::= DOT nm */
|
|
+ -1, /* (113) fullname ::= nm */
|
|
+ -3, /* (114) fullname ::= nm DOT nm */
|
|
+ -1, /* (115) xfullname ::= nm */
|
|
+ -3, /* (116) xfullname ::= nm DOT nm */
|
|
+ -5, /* (117) xfullname ::= nm DOT nm AS nm */
|
|
+ -3, /* (118) xfullname ::= nm AS nm */
|
|
+ -1, /* (119) joinop ::= COMMA|JOIN */
|
|
+ -2, /* (120) joinop ::= JOIN_KW JOIN */
|
|
+ -3, /* (121) joinop ::= JOIN_KW nm JOIN */
|
|
+ -4, /* (122) joinop ::= JOIN_KW nm nm JOIN */
|
|
+ -2, /* (123) on_opt ::= ON expr */
|
|
+ 0, /* (124) on_opt ::= */
|
|
+ 0, /* (125) indexed_opt ::= */
|
|
+ -3, /* (126) indexed_opt ::= INDEXED BY nm */
|
|
+ -2, /* (127) indexed_opt ::= NOT INDEXED */
|
|
+ -4, /* (128) using_opt ::= USING LP idlist RP */
|
|
+ 0, /* (129) using_opt ::= */
|
|
+ 0, /* (130) orderby_opt ::= */
|
|
+ -3, /* (131) orderby_opt ::= ORDER BY sortlist */
|
|
+ -5, /* (132) sortlist ::= sortlist COMMA expr sortorder nulls */
|
|
+ -3, /* (133) sortlist ::= expr sortorder nulls */
|
|
+ -1, /* (134) sortorder ::= ASC */
|
|
+ -1, /* (135) sortorder ::= DESC */
|
|
+ 0, /* (136) sortorder ::= */
|
|
+ -2, /* (137) nulls ::= NULLS FIRST */
|
|
+ -2, /* (138) nulls ::= NULLS LAST */
|
|
+ 0, /* (139) nulls ::= */
|
|
+ 0, /* (140) groupby_opt ::= */
|
|
+ -3, /* (141) groupby_opt ::= GROUP BY nexprlist */
|
|
+ 0, /* (142) having_opt ::= */
|
|
+ -2, /* (143) having_opt ::= HAVING expr */
|
|
+ 0, /* (144) limit_opt ::= */
|
|
+ -2, /* (145) limit_opt ::= LIMIT expr */
|
|
+ -4, /* (146) limit_opt ::= LIMIT expr OFFSET expr */
|
|
+ -4, /* (147) limit_opt ::= LIMIT expr COMMA expr */
|
|
+ -6, /* (148) cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
|
|
+ 0, /* (149) where_opt ::= */
|
|
+ -2, /* (150) where_opt ::= WHERE expr */
|
|
+ -8, /* (151) cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
|
|
+ -5, /* (152) setlist ::= setlist COMMA nm EQ expr */
|
|
+ -7, /* (153) setlist ::= setlist COMMA LP idlist RP EQ expr */
|
|
+ -3, /* (154) setlist ::= nm EQ expr */
|
|
+ -5, /* (155) setlist ::= LP idlist RP EQ expr */
|
|
+ -7, /* (156) cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
|
|
+ -7, /* (157) cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
|
|
+ 0, /* (158) upsert ::= */
|
|
+ -11, /* (159) upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
|
|
+ -8, /* (160) upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
|
|
+ -4, /* (161) upsert ::= ON CONFLICT DO NOTHING */
|
|
+ -2, /* (162) insert_cmd ::= INSERT orconf */
|
|
+ -1, /* (163) insert_cmd ::= REPLACE */
|
|
+ 0, /* (164) idlist_opt ::= */
|
|
+ -3, /* (165) idlist_opt ::= LP idlist RP */
|
|
+ -3, /* (166) idlist ::= idlist COMMA nm */
|
|
+ -1, /* (167) idlist ::= nm */
|
|
+ -3, /* (168) expr ::= LP expr RP */
|
|
+ -1, /* (169) expr ::= ID|INDEXED */
|
|
+ -1, /* (170) expr ::= JOIN_KW */
|
|
+ -3, /* (171) expr ::= nm DOT nm */
|
|
+ -5, /* (172) expr ::= nm DOT nm DOT nm */
|
|
+ -1, /* (173) term ::= NULL|FLOAT|BLOB */
|
|
+ -1, /* (174) term ::= STRING */
|
|
+ -1, /* (175) term ::= INTEGER */
|
|
+ -1, /* (176) expr ::= VARIABLE */
|
|
+ -3, /* (177) expr ::= expr COLLATE ID|STRING */
|
|
+ -6, /* (178) expr ::= CAST LP expr AS typetoken RP */
|
|
+ -5, /* (179) expr ::= ID|INDEXED LP distinct exprlist RP */
|
|
+ -4, /* (180) expr ::= ID|INDEXED LP STAR RP */
|
|
+ -6, /* (181) expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
|
|
+ -5, /* (182) expr ::= ID|INDEXED LP STAR RP filter_over */
|
|
+ -1, /* (183) term ::= CTIME_KW */
|
|
+ -5, /* (184) expr ::= LP nexprlist COMMA expr RP */
|
|
+ -3, /* (185) expr ::= expr AND expr */
|
|
+ -3, /* (186) expr ::= expr OR expr */
|
|
+ -3, /* (187) expr ::= expr LT|GT|GE|LE expr */
|
|
+ -3, /* (188) expr ::= expr EQ|NE expr */
|
|
+ -3, /* (189) expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */
|
|
+ -3, /* (190) expr ::= expr PLUS|MINUS expr */
|
|
+ -3, /* (191) expr ::= expr STAR|SLASH|REM expr */
|
|
+ -3, /* (192) expr ::= expr CONCAT expr */
|
|
+ -2, /* (193) likeop ::= NOT LIKE_KW|MATCH */
|
|
+ -3, /* (194) expr ::= expr likeop expr */
|
|
+ -5, /* (195) expr ::= expr likeop expr ESCAPE expr */
|
|
+ -2, /* (196) expr ::= expr ISNULL|NOTNULL */
|
|
+ -3, /* (197) expr ::= expr NOT NULL */
|
|
+ -3, /* (198) expr ::= expr IS expr */
|
|
+ -4, /* (199) expr ::= expr IS NOT expr */
|
|
+ -2, /* (200) expr ::= NOT expr */
|
|
+ -2, /* (201) expr ::= BITNOT expr */
|
|
+ -2, /* (202) expr ::= PLUS|MINUS expr */
|
|
+ -1, /* (203) between_op ::= BETWEEN */
|
|
+ -2, /* (204) between_op ::= NOT BETWEEN */
|
|
+ -5, /* (205) expr ::= expr between_op expr AND expr */
|
|
+ -1, /* (206) in_op ::= IN */
|
|
+ -2, /* (207) in_op ::= NOT IN */
|
|
+ -5, /* (208) expr ::= expr in_op LP exprlist RP */
|
|
+ -3, /* (209) expr ::= LP select RP */
|
|
+ -5, /* (210) expr ::= expr in_op LP select RP */
|
|
+ -5, /* (211) expr ::= expr in_op nm dbnm paren_exprlist */
|
|
+ -4, /* (212) expr ::= EXISTS LP select RP */
|
|
+ -5, /* (213) expr ::= CASE case_operand case_exprlist case_else END */
|
|
+ -5, /* (214) case_exprlist ::= case_exprlist WHEN expr THEN expr */
|
|
+ -4, /* (215) case_exprlist ::= WHEN expr THEN expr */
|
|
+ -2, /* (216) case_else ::= ELSE expr */
|
|
+ 0, /* (217) case_else ::= */
|
|
+ -1, /* (218) case_operand ::= expr */
|
|
+ 0, /* (219) case_operand ::= */
|
|
+ 0, /* (220) exprlist ::= */
|
|
+ -3, /* (221) nexprlist ::= nexprlist COMMA expr */
|
|
+ -1, /* (222) nexprlist ::= expr */
|
|
+ 0, /* (223) paren_exprlist ::= */
|
|
+ -3, /* (224) paren_exprlist ::= LP exprlist RP */
|
|
+ -12, /* (225) cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
|
|
+ -1, /* (226) uniqueflag ::= UNIQUE */
|
|
+ 0, /* (227) uniqueflag ::= */
|
|
+ 0, /* (228) eidlist_opt ::= */
|
|
+ -3, /* (229) eidlist_opt ::= LP eidlist RP */
|
|
+ -5, /* (230) eidlist ::= eidlist COMMA nm collate sortorder */
|
|
+ -3, /* (231) eidlist ::= nm collate sortorder */
|
|
+ 0, /* (232) collate ::= */
|
|
+ -2, /* (233) collate ::= COLLATE ID|STRING */
|
|
+ -4, /* (234) cmd ::= DROP INDEX ifexists fullname */
|
|
+ -2, /* (235) cmd ::= VACUUM vinto */
|
|
+ -3, /* (236) cmd ::= VACUUM nm vinto */
|
|
+ -2, /* (237) vinto ::= INTO expr */
|
|
+ 0, /* (238) vinto ::= */
|
|
+ -3, /* (239) cmd ::= PRAGMA nm dbnm */
|
|
+ -5, /* (240) cmd ::= PRAGMA nm dbnm EQ nmnum */
|
|
+ -6, /* (241) cmd ::= PRAGMA nm dbnm LP nmnum RP */
|
|
+ -5, /* (242) cmd ::= PRAGMA nm dbnm EQ minus_num */
|
|
+ -6, /* (243) cmd ::= PRAGMA nm dbnm LP minus_num RP */
|
|
+ -2, /* (244) plus_num ::= PLUS INTEGER|FLOAT */
|
|
+ -2, /* (245) minus_num ::= MINUS INTEGER|FLOAT */
|
|
+ -5, /* (246) cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
|
|
+ -11, /* (247) trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
|
|
+ -1, /* (248) trigger_time ::= BEFORE|AFTER */
|
|
+ -2, /* (249) trigger_time ::= INSTEAD OF */
|
|
+ 0, /* (250) trigger_time ::= */
|
|
+ -1, /* (251) trigger_event ::= DELETE|INSERT */
|
|
+ -1, /* (252) trigger_event ::= UPDATE */
|
|
+ -3, /* (253) trigger_event ::= UPDATE OF idlist */
|
|
+ 0, /* (254) when_clause ::= */
|
|
+ -2, /* (255) when_clause ::= WHEN expr */
|
|
+ -3, /* (256) trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
|
|
+ -2, /* (257) trigger_cmd_list ::= trigger_cmd SEMI */
|
|
+ -3, /* (258) trnm ::= nm DOT nm */
|
|
+ -3, /* (259) tridxby ::= INDEXED BY nm */
|
|
+ -2, /* (260) tridxby ::= NOT INDEXED */
|
|
+ -8, /* (261) trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
|
|
+ -8, /* (262) trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
|
|
+ -6, /* (263) trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
|
|
+ -3, /* (264) trigger_cmd ::= scanpt select scanpt */
|
|
+ -4, /* (265) expr ::= RAISE LP IGNORE RP */
|
|
+ -6, /* (266) expr ::= RAISE LP raisetype COMMA nm RP */
|
|
+ -1, /* (267) raisetype ::= ROLLBACK */
|
|
+ -1, /* (268) raisetype ::= ABORT */
|
|
+ -1, /* (269) raisetype ::= FAIL */
|
|
+ -4, /* (270) cmd ::= DROP TRIGGER ifexists fullname */
|
|
+ -6, /* (271) cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
|
|
+ -3, /* (272) cmd ::= DETACH database_kw_opt expr */
|
|
+ 0, /* (273) key_opt ::= */
|
|
+ -2, /* (274) key_opt ::= KEY expr */
|
|
+ -1, /* (275) cmd ::= REINDEX */
|
|
+ -3, /* (276) cmd ::= REINDEX nm dbnm */
|
|
+ -1, /* (277) cmd ::= ANALYZE */
|
|
+ -3, /* (278) cmd ::= ANALYZE nm dbnm */
|
|
+ -6, /* (279) cmd ::= ALTER TABLE fullname RENAME TO nm */
|
|
+ -7, /* (280) cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
|
|
+ -1, /* (281) add_column_fullname ::= fullname */
|
|
+ -8, /* (282) cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
|
|
+ -1, /* (283) cmd ::= create_vtab */
|
|
+ -4, /* (284) cmd ::= create_vtab LP vtabarglist RP */
|
|
+ -8, /* (285) create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
|
|
+ 0, /* (286) vtabarg ::= */
|
|
+ -1, /* (287) vtabargtoken ::= ANY */
|
|
+ -3, /* (288) vtabargtoken ::= lp anylist RP */
|
|
+ -1, /* (289) lp ::= LP */
|
|
+ -2, /* (290) with ::= WITH wqlist */
|
|
+ -3, /* (291) with ::= WITH RECURSIVE wqlist */
|
|
+ -6, /* (292) wqlist ::= nm eidlist_opt AS LP select RP */
|
|
+ -8, /* (293) wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
|
|
+ -1, /* (294) windowdefn_list ::= windowdefn */
|
|
+ -3, /* (295) windowdefn_list ::= windowdefn_list COMMA windowdefn */
|
|
+ -5, /* (296) windowdefn ::= nm AS LP window RP */
|
|
+ -5, /* (297) window ::= PARTITION BY nexprlist orderby_opt frame_opt */
|
|
+ -6, /* (298) window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
|
|
+ -4, /* (299) window ::= ORDER BY sortlist frame_opt */
|
|
+ -5, /* (300) window ::= nm ORDER BY sortlist frame_opt */
|
|
+ -1, /* (301) window ::= frame_opt */
|
|
+ -2, /* (302) window ::= nm frame_opt */
|
|
+ 0, /* (303) frame_opt ::= */
|
|
+ -3, /* (304) frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
|
|
+ -6, /* (305) frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
|
|
+ -1, /* (306) range_or_rows ::= RANGE|ROWS|GROUPS */
|
|
+ -1, /* (307) frame_bound_s ::= frame_bound */
|
|
+ -2, /* (308) frame_bound_s ::= UNBOUNDED PRECEDING */
|
|
+ -1, /* (309) frame_bound_e ::= frame_bound */
|
|
+ -2, /* (310) frame_bound_e ::= UNBOUNDED FOLLOWING */
|
|
+ -2, /* (311) frame_bound ::= expr PRECEDING|FOLLOWING */
|
|
+ -2, /* (312) frame_bound ::= CURRENT ROW */
|
|
+ 0, /* (313) frame_exclude_opt ::= */
|
|
+ -2, /* (314) frame_exclude_opt ::= EXCLUDE frame_exclude */
|
|
+ -2, /* (315) frame_exclude ::= NO OTHERS */
|
|
+ -2, /* (316) frame_exclude ::= CURRENT ROW */
|
|
+ -1, /* (317) frame_exclude ::= GROUP|TIES */
|
|
+ -2, /* (318) window_clause ::= WINDOW windowdefn_list */
|
|
+ -2, /* (319) filter_over ::= filter_clause over_clause */
|
|
+ -1, /* (320) filter_over ::= over_clause */
|
|
+ -1, /* (321) filter_over ::= filter_clause */
|
|
+ -4, /* (322) over_clause ::= OVER LP window RP */
|
|
+ -2, /* (323) over_clause ::= OVER nm */
|
|
+ -5, /* (324) filter_clause ::= FILTER LP WHERE expr RP */
|
|
+ -1, /* (325) input ::= cmdlist */
|
|
+ -2, /* (326) cmdlist ::= cmdlist ecmd */
|
|
+ -1, /* (327) cmdlist ::= ecmd */
|
|
+ -1, /* (328) ecmd ::= SEMI */
|
|
+ -2, /* (329) ecmd ::= cmdx SEMI */
|
|
+ -3, /* (330) ecmd ::= explain cmdx SEMI */
|
|
+ 0, /* (331) trans_opt ::= */
|
|
+ -1, /* (332) trans_opt ::= TRANSACTION */
|
|
+ -2, /* (333) trans_opt ::= TRANSACTION nm */
|
|
+ -1, /* (334) savepoint_opt ::= SAVEPOINT */
|
|
+ 0, /* (335) savepoint_opt ::= */
|
|
+ -2, /* (336) cmd ::= create_table create_table_args */
|
|
+ -4, /* (337) columnlist ::= columnlist COMMA columnname carglist */
|
|
+ -2, /* (338) columnlist ::= columnname carglist */
|
|
+ -1, /* (339) nm ::= ID|INDEXED */
|
|
+ -1, /* (340) nm ::= STRING */
|
|
+ -1, /* (341) nm ::= JOIN_KW */
|
|
+ -1, /* (342) typetoken ::= typename */
|
|
+ -1, /* (343) typename ::= ID|STRING */
|
|
+ -1, /* (344) signed ::= plus_num */
|
|
+ -1, /* (345) signed ::= minus_num */
|
|
+ -2, /* (346) carglist ::= carglist ccons */
|
|
+ 0, /* (347) carglist ::= */
|
|
+ -2, /* (348) ccons ::= NULL onconf */
|
|
+ -4, /* (349) ccons ::= GENERATED ALWAYS AS generated */
|
|
+ -2, /* (350) ccons ::= AS generated */
|
|
+ -2, /* (351) conslist_opt ::= COMMA conslist */
|
|
+ -3, /* (352) conslist ::= conslist tconscomma tcons */
|
|
+ -1, /* (353) conslist ::= tcons */
|
|
+ 0, /* (354) tconscomma ::= */
|
|
+ -1, /* (355) defer_subclause_opt ::= defer_subclause */
|
|
+ -1, /* (356) resolvetype ::= raisetype */
|
|
+ -1, /* (357) selectnowith ::= oneselect */
|
|
+ -1, /* (358) oneselect ::= values */
|
|
+ -2, /* (359) sclp ::= selcollist COMMA */
|
|
+ -1, /* (360) as ::= ID|STRING */
|
|
+ -1, /* (361) expr ::= term */
|
|
+ -1, /* (362) likeop ::= LIKE_KW|MATCH */
|
|
+ -1, /* (363) exprlist ::= nexprlist */
|
|
+ -1, /* (364) nmnum ::= plus_num */
|
|
+ -1, /* (365) nmnum ::= nm */
|
|
+ -1, /* (366) nmnum ::= ON */
|
|
+ -1, /* (367) nmnum ::= DELETE */
|
|
+ -1, /* (368) nmnum ::= DEFAULT */
|
|
+ -1, /* (369) plus_num ::= INTEGER|FLOAT */
|
|
+ 0, /* (370) foreach_clause ::= */
|
|
+ -3, /* (371) foreach_clause ::= FOR EACH ROW */
|
|
+ -1, /* (372) trnm ::= nm */
|
|
+ 0, /* (373) tridxby ::= */
|
|
+ -1, /* (374) database_kw_opt ::= DATABASE */
|
|
+ 0, /* (375) database_kw_opt ::= */
|
|
+ 0, /* (376) kwcolumn_opt ::= */
|
|
+ -1, /* (377) kwcolumn_opt ::= COLUMNKW */
|
|
+ -1, /* (378) vtabarglist ::= vtabarg */
|
|
+ -3, /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */
|
|
+ -2, /* (380) vtabarg ::= vtabarg vtabargtoken */
|
|
+ 0, /* (381) anylist ::= */
|
|
+ -4, /* (382) anylist ::= anylist LP anylist RP */
|
|
+ -2, /* (383) anylist ::= anylist ANY */
|
|
+ 0, /* (384) with ::= */
|
|
};
|
|
|
|
static void yy_accept(yyParser*); /* Forward Declaration */
|
|
@@ -151836,12 +156646,15 @@
|
|
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
|
|
yysize = yyRuleInfoNRhs[yyruleno];
|
|
if( yysize ){
|
|
- fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
|
|
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
|
|
yyTracePrompt,
|
|
- yyruleno, yyRuleName[yyruleno], yymsp[yysize].stateno);
|
|
+ yyruleno, yyRuleName[yyruleno],
|
|
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
|
|
+ yymsp[yysize].stateno);
|
|
}else{
|
|
- fprintf(yyTraceFILE, "%sReduce %d [%s].\n",
|
|
- yyTracePrompt, yyruleno, yyRuleName[yyruleno]);
|
|
+ fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
|
|
+ yyTracePrompt, yyruleno, yyRuleName[yyruleno],
|
|
+ yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
|
|
}
|
|
}
|
|
#endif /* NDEBUG */
|
|
@@ -151899,16 +156712,16 @@
|
|
{ sqlite3FinishCoding(pParse); }
|
|
break;
|
|
case 3: /* cmd ::= BEGIN transtype trans_opt */
|
|
-{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy100);}
|
|
+{sqlite3BeginTransaction(pParse, yymsp[-1].minor.yy192);}
|
|
break;
|
|
case 4: /* transtype ::= */
|
|
-{yymsp[1].minor.yy100 = TK_DEFERRED;}
|
|
+{yymsp[1].minor.yy192 = TK_DEFERRED;}
|
|
break;
|
|
case 5: /* transtype ::= DEFERRED */
|
|
case 6: /* transtype ::= IMMEDIATE */ yytestcase(yyruleno==6);
|
|
case 7: /* transtype ::= EXCLUSIVE */ yytestcase(yyruleno==7);
|
|
- case 301: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==301);
|
|
-{yymsp[0].minor.yy100 = yymsp[0].major; /*A-overwrites-X*/}
|
|
+ case 306: /* range_or_rows ::= RANGE|ROWS|GROUPS */ yytestcase(yyruleno==306);
|
|
+{yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-X*/}
|
|
break;
|
|
case 8: /* cmd ::= COMMIT|END trans_opt */
|
|
case 9: /* cmd ::= ROLLBACK trans_opt */ yytestcase(yyruleno==9);
|
|
@@ -151931,7 +156744,7 @@
|
|
break;
|
|
case 13: /* create_table ::= createkw temp TABLE ifnotexists nm dbnm */
|
|
{
|
|
- sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy100,0,0,yymsp[-2].minor.yy100);
|
|
+ sqlite3StartTable(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,yymsp[-4].minor.yy192,0,0,yymsp[-2].minor.yy192);
|
|
}
|
|
break;
|
|
case 14: /* createkw ::= CREATE */
|
|
@@ -151940,38 +156753,38 @@
|
|
case 15: /* ifnotexists ::= */
|
|
case 18: /* temp ::= */ yytestcase(yyruleno==18);
|
|
case 21: /* table_options ::= */ yytestcase(yyruleno==21);
|
|
- case 43: /* autoinc ::= */ yytestcase(yyruleno==43);
|
|
- case 58: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==58);
|
|
- case 68: /* defer_subclause_opt ::= */ yytestcase(yyruleno==68);
|
|
- case 77: /* ifexists ::= */ yytestcase(yyruleno==77);
|
|
- case 94: /* distinct ::= */ yytestcase(yyruleno==94);
|
|
- case 227: /* collate ::= */ yytestcase(yyruleno==227);
|
|
-{yymsp[1].minor.yy100 = 0;}
|
|
+ case 45: /* autoinc ::= */ yytestcase(yyruleno==45);
|
|
+ case 60: /* init_deferred_pred_opt ::= */ yytestcase(yyruleno==60);
|
|
+ case 70: /* defer_subclause_opt ::= */ yytestcase(yyruleno==70);
|
|
+ case 79: /* ifexists ::= */ yytestcase(yyruleno==79);
|
|
+ case 96: /* distinct ::= */ yytestcase(yyruleno==96);
|
|
+ case 232: /* collate ::= */ yytestcase(yyruleno==232);
|
|
+{yymsp[1].minor.yy192 = 0;}
|
|
break;
|
|
case 16: /* ifnotexists ::= IF NOT EXISTS */
|
|
-{yymsp[-2].minor.yy100 = 1;}
|
|
+{yymsp[-2].minor.yy192 = 1;}
|
|
break;
|
|
case 17: /* temp ::= TEMP */
|
|
- case 44: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==44);
|
|
-{yymsp[0].minor.yy100 = 1;}
|
|
+ case 46: /* autoinc ::= AUTOINCR */ yytestcase(yyruleno==46);
|
|
+{yymsp[0].minor.yy192 = 1;}
|
|
break;
|
|
case 19: /* create_table_args ::= LP columnlist conslist_opt RP table_options */
|
|
{
|
|
- sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy100,0);
|
|
+ sqlite3EndTable(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,yymsp[0].minor.yy192,0);
|
|
}
|
|
break;
|
|
case 20: /* create_table_args ::= AS select */
|
|
{
|
|
- sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy391);
|
|
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy391);
|
|
+ sqlite3EndTable(pParse,0,0,0,yymsp[0].minor.yy539);
|
|
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy539);
|
|
}
|
|
break;
|
|
case 22: /* table_options ::= WITHOUT nm */
|
|
{
|
|
if( yymsp[0].minor.yy0.n==5 && sqlite3_strnicmp(yymsp[0].minor.yy0.z,"rowid",5)==0 ){
|
|
- yymsp[-1].minor.yy100 = TF_WithoutRowid | TF_NoVisibleRowid;
|
|
+ yymsp[-1].minor.yy192 = TF_WithoutRowid | TF_NoVisibleRowid;
|
|
}else{
|
|
- yymsp[-1].minor.yy100 = 0;
|
|
+ yymsp[-1].minor.yy192 = 0;
|
|
sqlite3ErrorMsg(pParse, "unknown table option: %.*s", yymsp[0].minor.yy0.n, yymsp[0].minor.yy0.z);
|
|
}
|
|
}
|
|
@@ -151980,8 +156793,8 @@
|
|
{sqlite3AddColumn(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
|
|
break;
|
|
case 24: /* typetoken ::= */
|
|
- case 61: /* conslist_opt ::= */ yytestcase(yyruleno==61);
|
|
- case 100: /* as ::= */ yytestcase(yyruleno==100);
|
|
+ case 63: /* conslist_opt ::= */ yytestcase(yyruleno==63);
|
|
+ case 102: /* as ::= */ yytestcase(yyruleno==102);
|
|
{yymsp[1].minor.yy0.n = 0; yymsp[1].minor.yy0.z = 0;}
|
|
break;
|
|
case 25: /* typetoken ::= typename LP signed RP */
|
|
@@ -152000,7 +156813,7 @@
|
|
case 28: /* scanpt ::= */
|
|
{
|
|
assert( yyLookahead!=YYNOCODE );
|
|
- yymsp[1].minor.yy528 = yyLookaheadToken.z;
|
|
+ yymsp[1].minor.yy436 = yyLookaheadToken.z;
|
|
}
|
|
break;
|
|
case 29: /* scantok ::= */
|
|
@@ -152010,21 +156823,21 @@
|
|
}
|
|
break;
|
|
case 30: /* ccons ::= CONSTRAINT nm */
|
|
- case 63: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==63);
|
|
+ case 65: /* tcons ::= CONSTRAINT nm */ yytestcase(yyruleno==65);
|
|
{pParse->constraintName = yymsp[0].minor.yy0;}
|
|
break;
|
|
case 31: /* ccons ::= DEFAULT scantok term */
|
|
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy102,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
|
|
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy202,yymsp[-1].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
|
|
break;
|
|
case 32: /* ccons ::= DEFAULT LP expr RP */
|
|
-{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy102,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
|
|
+{sqlite3AddDefaultValue(pParse,yymsp[-1].minor.yy202,yymsp[-2].minor.yy0.z+1,yymsp[0].minor.yy0.z);}
|
|
break;
|
|
case 33: /* ccons ::= DEFAULT PLUS scantok term */
|
|
-{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy102,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
|
|
+{sqlite3AddDefaultValue(pParse,yymsp[0].minor.yy202,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);}
|
|
break;
|
|
case 34: /* ccons ::= DEFAULT MINUS scantok term */
|
|
{
|
|
- Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy102, 0);
|
|
+ Expr *p = sqlite3PExpr(pParse, TK_UMINUS, yymsp[0].minor.yy202, 0);
|
|
sqlite3AddDefaultValue(pParse,p,yymsp[-2].minor.yy0.z,&yymsp[-1].minor.yy0.z[yymsp[-1].minor.yy0.n]);
|
|
}
|
|
break;
|
|
@@ -152039,170 +156852,176 @@
|
|
}
|
|
break;
|
|
case 36: /* ccons ::= NOT NULL onconf */
|
|
-{sqlite3AddNotNull(pParse, yymsp[0].minor.yy100);}
|
|
+{sqlite3AddNotNull(pParse, yymsp[0].minor.yy192);}
|
|
break;
|
|
case 37: /* ccons ::= PRIMARY KEY sortorder onconf autoinc */
|
|
-{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy100,yymsp[0].minor.yy100,yymsp[-2].minor.yy100);}
|
|
+{sqlite3AddPrimaryKey(pParse,0,yymsp[-1].minor.yy192,yymsp[0].minor.yy192,yymsp[-2].minor.yy192);}
|
|
break;
|
|
case 38: /* ccons ::= UNIQUE onconf */
|
|
-{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy100,0,0,0,0,
|
|
+{sqlite3CreateIndex(pParse,0,0,0,0,yymsp[0].minor.yy192,0,0,0,0,
|
|
SQLITE_IDXTYPE_UNIQUE);}
|
|
break;
|
|
case 39: /* ccons ::= CHECK LP expr RP */
|
|
-{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy102);}
|
|
+{sqlite3AddCheckConstraint(pParse,yymsp[-1].minor.yy202);}
|
|
break;
|
|
case 40: /* ccons ::= REFERENCES nm eidlist_opt refargs */
|
|
-{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy94,yymsp[0].minor.yy100);}
|
|
+{sqlite3CreateForeignKey(pParse,0,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy242,yymsp[0].minor.yy192);}
|
|
break;
|
|
case 41: /* ccons ::= defer_subclause */
|
|
-{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy100);}
|
|
+{sqlite3DeferForeignKey(pParse,yymsp[0].minor.yy192);}
|
|
break;
|
|
case 42: /* ccons ::= COLLATE ID|STRING */
|
|
{sqlite3AddCollateType(pParse, &yymsp[0].minor.yy0);}
|
|
break;
|
|
- case 45: /* refargs ::= */
|
|
-{ yymsp[1].minor.yy100 = OE_None*0x0101; /* EV: R-19803-45884 */}
|
|
+ case 43: /* generated ::= LP expr RP */
|
|
+{sqlite3AddGenerated(pParse,yymsp[-1].minor.yy202,0);}
|
|
+ break;
|
|
+ case 44: /* generated ::= LP expr RP ID */
|
|
+{sqlite3AddGenerated(pParse,yymsp[-2].minor.yy202,&yymsp[0].minor.yy0);}
|
|
+ break;
|
|
+ case 47: /* refargs ::= */
|
|
+{ yymsp[1].minor.yy192 = OE_None*0x0101; /* EV: R-19803-45884 */}
|
|
break;
|
|
- case 46: /* refargs ::= refargs refarg */
|
|
-{ yymsp[-1].minor.yy100 = (yymsp[-1].minor.yy100 & ~yymsp[0].minor.yy199.mask) | yymsp[0].minor.yy199.value; }
|
|
+ case 48: /* refargs ::= refargs refarg */
|
|
+{ yymsp[-1].minor.yy192 = (yymsp[-1].minor.yy192 & ~yymsp[0].minor.yy207.mask) | yymsp[0].minor.yy207.value; }
|
|
break;
|
|
- case 47: /* refarg ::= MATCH nm */
|
|
-{ yymsp[-1].minor.yy199.value = 0; yymsp[-1].minor.yy199.mask = 0x000000; }
|
|
+ case 49: /* refarg ::= MATCH nm */
|
|
+{ yymsp[-1].minor.yy207.value = 0; yymsp[-1].minor.yy207.mask = 0x000000; }
|
|
break;
|
|
- case 48: /* refarg ::= ON INSERT refact */
|
|
-{ yymsp[-2].minor.yy199.value = 0; yymsp[-2].minor.yy199.mask = 0x000000; }
|
|
+ case 50: /* refarg ::= ON INSERT refact */
|
|
+{ yymsp[-2].minor.yy207.value = 0; yymsp[-2].minor.yy207.mask = 0x000000; }
|
|
break;
|
|
- case 49: /* refarg ::= ON DELETE refact */
|
|
-{ yymsp[-2].minor.yy199.value = yymsp[0].minor.yy100; yymsp[-2].minor.yy199.mask = 0x0000ff; }
|
|
+ case 51: /* refarg ::= ON DELETE refact */
|
|
+{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy192; yymsp[-2].minor.yy207.mask = 0x0000ff; }
|
|
break;
|
|
- case 50: /* refarg ::= ON UPDATE refact */
|
|
-{ yymsp[-2].minor.yy199.value = yymsp[0].minor.yy100<<8; yymsp[-2].minor.yy199.mask = 0x00ff00; }
|
|
+ case 52: /* refarg ::= ON UPDATE refact */
|
|
+{ yymsp[-2].minor.yy207.value = yymsp[0].minor.yy192<<8; yymsp[-2].minor.yy207.mask = 0x00ff00; }
|
|
break;
|
|
- case 51: /* refact ::= SET NULL */
|
|
-{ yymsp[-1].minor.yy100 = OE_SetNull; /* EV: R-33326-45252 */}
|
|
+ case 53: /* refact ::= SET NULL */
|
|
+{ yymsp[-1].minor.yy192 = OE_SetNull; /* EV: R-33326-45252 */}
|
|
break;
|
|
- case 52: /* refact ::= SET DEFAULT */
|
|
-{ yymsp[-1].minor.yy100 = OE_SetDflt; /* EV: R-33326-45252 */}
|
|
+ case 54: /* refact ::= SET DEFAULT */
|
|
+{ yymsp[-1].minor.yy192 = OE_SetDflt; /* EV: R-33326-45252 */}
|
|
break;
|
|
- case 53: /* refact ::= CASCADE */
|
|
-{ yymsp[0].minor.yy100 = OE_Cascade; /* EV: R-33326-45252 */}
|
|
+ case 55: /* refact ::= CASCADE */
|
|
+{ yymsp[0].minor.yy192 = OE_Cascade; /* EV: R-33326-45252 */}
|
|
break;
|
|
- case 54: /* refact ::= RESTRICT */
|
|
-{ yymsp[0].minor.yy100 = OE_Restrict; /* EV: R-33326-45252 */}
|
|
+ case 56: /* refact ::= RESTRICT */
|
|
+{ yymsp[0].minor.yy192 = OE_Restrict; /* EV: R-33326-45252 */}
|
|
break;
|
|
- case 55: /* refact ::= NO ACTION */
|
|
-{ yymsp[-1].minor.yy100 = OE_None; /* EV: R-33326-45252 */}
|
|
+ case 57: /* refact ::= NO ACTION */
|
|
+{ yymsp[-1].minor.yy192 = OE_None; /* EV: R-33326-45252 */}
|
|
break;
|
|
- case 56: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
|
|
-{yymsp[-2].minor.yy100 = 0;}
|
|
+ case 58: /* defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt */
|
|
+{yymsp[-2].minor.yy192 = 0;}
|
|
break;
|
|
- case 57: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
|
|
- case 72: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==72);
|
|
- case 157: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==157);
|
|
-{yymsp[-1].minor.yy100 = yymsp[0].minor.yy100;}
|
|
+ case 59: /* defer_subclause ::= DEFERRABLE init_deferred_pred_opt */
|
|
+ case 74: /* orconf ::= OR resolvetype */ yytestcase(yyruleno==74);
|
|
+ case 162: /* insert_cmd ::= INSERT orconf */ yytestcase(yyruleno==162);
|
|
+{yymsp[-1].minor.yy192 = yymsp[0].minor.yy192;}
|
|
break;
|
|
- case 59: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
|
|
- case 76: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==76);
|
|
- case 199: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==199);
|
|
- case 202: /* in_op ::= NOT IN */ yytestcase(yyruleno==202);
|
|
- case 228: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==228);
|
|
-{yymsp[-1].minor.yy100 = 1;}
|
|
+ case 61: /* init_deferred_pred_opt ::= INITIALLY DEFERRED */
|
|
+ case 78: /* ifexists ::= IF EXISTS */ yytestcase(yyruleno==78);
|
|
+ case 204: /* between_op ::= NOT BETWEEN */ yytestcase(yyruleno==204);
|
|
+ case 207: /* in_op ::= NOT IN */ yytestcase(yyruleno==207);
|
|
+ case 233: /* collate ::= COLLATE ID|STRING */ yytestcase(yyruleno==233);
|
|
+{yymsp[-1].minor.yy192 = 1;}
|
|
break;
|
|
- case 60: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
|
|
-{yymsp[-1].minor.yy100 = 0;}
|
|
+ case 62: /* init_deferred_pred_opt ::= INITIALLY IMMEDIATE */
|
|
+{yymsp[-1].minor.yy192 = 0;}
|
|
break;
|
|
- case 62: /* tconscomma ::= COMMA */
|
|
+ case 64: /* tconscomma ::= COMMA */
|
|
{pParse->constraintName.n = 0;}
|
|
break;
|
|
- case 64: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
|
|
-{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy94,yymsp[0].minor.yy100,yymsp[-2].minor.yy100,0);}
|
|
+ case 66: /* tcons ::= PRIMARY KEY LP sortlist autoinc RP onconf */
|
|
+{sqlite3AddPrimaryKey(pParse,yymsp[-3].minor.yy242,yymsp[0].minor.yy192,yymsp[-2].minor.yy192,0);}
|
|
break;
|
|
- case 65: /* tcons ::= UNIQUE LP sortlist RP onconf */
|
|
-{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy94,yymsp[0].minor.yy100,0,0,0,0,
|
|
+ case 67: /* tcons ::= UNIQUE LP sortlist RP onconf */
|
|
+{sqlite3CreateIndex(pParse,0,0,0,yymsp[-2].minor.yy242,yymsp[0].minor.yy192,0,0,0,0,
|
|
SQLITE_IDXTYPE_UNIQUE);}
|
|
break;
|
|
- case 66: /* tcons ::= CHECK LP expr RP onconf */
|
|
-{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy102);}
|
|
+ case 68: /* tcons ::= CHECK LP expr RP onconf */
|
|
+{sqlite3AddCheckConstraint(pParse,yymsp[-2].minor.yy202);}
|
|
break;
|
|
- case 67: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
|
|
+ case 69: /* tcons ::= FOREIGN KEY LP eidlist RP REFERENCES nm eidlist_opt refargs defer_subclause_opt */
|
|
{
|
|
- sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy94, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy94, yymsp[-1].minor.yy100);
|
|
- sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy100);
|
|
+ sqlite3CreateForeignKey(pParse, yymsp[-6].minor.yy242, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy192);
|
|
+ sqlite3DeferForeignKey(pParse, yymsp[0].minor.yy192);
|
|
}
|
|
break;
|
|
- case 69: /* onconf ::= */
|
|
- case 71: /* orconf ::= */ yytestcase(yyruleno==71);
|
|
-{yymsp[1].minor.yy100 = OE_Default;}
|
|
+ case 71: /* onconf ::= */
|
|
+ case 73: /* orconf ::= */ yytestcase(yyruleno==73);
|
|
+{yymsp[1].minor.yy192 = OE_Default;}
|
|
break;
|
|
- case 70: /* onconf ::= ON CONFLICT resolvetype */
|
|
-{yymsp[-2].minor.yy100 = yymsp[0].minor.yy100;}
|
|
+ case 72: /* onconf ::= ON CONFLICT resolvetype */
|
|
+{yymsp[-2].minor.yy192 = yymsp[0].minor.yy192;}
|
|
break;
|
|
- case 73: /* resolvetype ::= IGNORE */
|
|
-{yymsp[0].minor.yy100 = OE_Ignore;}
|
|
+ case 75: /* resolvetype ::= IGNORE */
|
|
+{yymsp[0].minor.yy192 = OE_Ignore;}
|
|
break;
|
|
- case 74: /* resolvetype ::= REPLACE */
|
|
- case 158: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==158);
|
|
-{yymsp[0].minor.yy100 = OE_Replace;}
|
|
+ case 76: /* resolvetype ::= REPLACE */
|
|
+ case 163: /* insert_cmd ::= REPLACE */ yytestcase(yyruleno==163);
|
|
+{yymsp[0].minor.yy192 = OE_Replace;}
|
|
break;
|
|
- case 75: /* cmd ::= DROP TABLE ifexists fullname */
|
|
+ case 77: /* cmd ::= DROP TABLE ifexists fullname */
|
|
{
|
|
- sqlite3DropTable(pParse, yymsp[0].minor.yy407, 0, yymsp[-1].minor.yy100);
|
|
+ sqlite3DropTable(pParse, yymsp[0].minor.yy47, 0, yymsp[-1].minor.yy192);
|
|
}
|
|
break;
|
|
- case 78: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
|
|
+ case 80: /* cmd ::= createkw temp VIEW ifnotexists nm dbnm eidlist_opt AS select */
|
|
{
|
|
- sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy94, yymsp[0].minor.yy391, yymsp[-7].minor.yy100, yymsp[-5].minor.yy100);
|
|
+ sqlite3CreateView(pParse, &yymsp[-8].minor.yy0, &yymsp[-4].minor.yy0, &yymsp[-3].minor.yy0, yymsp[-2].minor.yy242, yymsp[0].minor.yy539, yymsp[-7].minor.yy192, yymsp[-5].minor.yy192);
|
|
}
|
|
break;
|
|
- case 79: /* cmd ::= DROP VIEW ifexists fullname */
|
|
+ case 81: /* cmd ::= DROP VIEW ifexists fullname */
|
|
{
|
|
- sqlite3DropTable(pParse, yymsp[0].minor.yy407, 1, yymsp[-1].minor.yy100);
|
|
+ sqlite3DropTable(pParse, yymsp[0].minor.yy47, 1, yymsp[-1].minor.yy192);
|
|
}
|
|
break;
|
|
- case 80: /* cmd ::= select */
|
|
+ case 82: /* cmd ::= select */
|
|
{
|
|
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
|
|
- sqlite3Select(pParse, yymsp[0].minor.yy391, &dest);
|
|
- sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy391);
|
|
+ sqlite3Select(pParse, yymsp[0].minor.yy539, &dest);
|
|
+ sqlite3SelectDelete(pParse->db, yymsp[0].minor.yy539);
|
|
}
|
|
break;
|
|
- case 81: /* select ::= WITH wqlist selectnowith */
|
|
+ case 83: /* select ::= WITH wqlist selectnowith */
|
|
{
|
|
- Select *p = yymsp[0].minor.yy391;
|
|
+ Select *p = yymsp[0].minor.yy539;
|
|
if( p ){
|
|
- p->pWith = yymsp[-1].minor.yy243;
|
|
+ p->pWith = yymsp[-1].minor.yy131;
|
|
parserDoubleLinkSelect(pParse, p);
|
|
}else{
|
|
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy243);
|
|
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy131);
|
|
}
|
|
- yymsp[-2].minor.yy391 = p;
|
|
+ yymsp[-2].minor.yy539 = p;
|
|
}
|
|
break;
|
|
- case 82: /* select ::= WITH RECURSIVE wqlist selectnowith */
|
|
+ case 84: /* select ::= WITH RECURSIVE wqlist selectnowith */
|
|
{
|
|
- Select *p = yymsp[0].minor.yy391;
|
|
+ Select *p = yymsp[0].minor.yy539;
|
|
if( p ){
|
|
- p->pWith = yymsp[-1].minor.yy243;
|
|
+ p->pWith = yymsp[-1].minor.yy131;
|
|
parserDoubleLinkSelect(pParse, p);
|
|
}else{
|
|
- sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy243);
|
|
+ sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy131);
|
|
}
|
|
- yymsp[-3].minor.yy391 = p;
|
|
+ yymsp[-3].minor.yy539 = p;
|
|
}
|
|
break;
|
|
- case 83: /* select ::= selectnowith */
|
|
+ case 85: /* select ::= selectnowith */
|
|
{
|
|
- Select *p = yymsp[0].minor.yy391;
|
|
+ Select *p = yymsp[0].minor.yy539;
|
|
if( p ){
|
|
parserDoubleLinkSelect(pParse, p);
|
|
}
|
|
- yymsp[0].minor.yy391 = p; /*A-overwrites-X*/
|
|
+ yymsp[0].minor.yy539 = p; /*A-overwrites-X*/
|
|
}
|
|
break;
|
|
- case 84: /* selectnowith ::= selectnowith multiselect_op oneselect */
|
|
+ case 86: /* selectnowith ::= selectnowith multiselect_op oneselect */
|
|
{
|
|
- Select *pRhs = yymsp[0].minor.yy391;
|
|
- Select *pLhs = yymsp[-2].minor.yy391;
|
|
+ Select *pRhs = yymsp[0].minor.yy539;
|
|
+ Select *pLhs = yymsp[-2].minor.yy539;
|
|
if( pRhs && pRhs->pPrior ){
|
|
SrcList *pFrom;
|
|
Token x;
|
|
@@ -152212,142 +157031,142 @@
|
|
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0);
|
|
}
|
|
if( pRhs ){
|
|
- pRhs->op = (u8)yymsp[-1].minor.yy100;
|
|
+ pRhs->op = (u8)yymsp[-1].minor.yy192;
|
|
pRhs->pPrior = pLhs;
|
|
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
|
|
pRhs->selFlags &= ~SF_MultiValue;
|
|
- if( yymsp[-1].minor.yy100!=TK_ALL ) pParse->hasCompound = 1;
|
|
+ if( yymsp[-1].minor.yy192!=TK_ALL ) pParse->hasCompound = 1;
|
|
}else{
|
|
sqlite3SelectDelete(pParse->db, pLhs);
|
|
}
|
|
- yymsp[-2].minor.yy391 = pRhs;
|
|
+ yymsp[-2].minor.yy539 = pRhs;
|
|
}
|
|
break;
|
|
- case 85: /* multiselect_op ::= UNION */
|
|
- case 87: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==87);
|
|
-{yymsp[0].minor.yy100 = yymsp[0].major; /*A-overwrites-OP*/}
|
|
+ case 87: /* multiselect_op ::= UNION */
|
|
+ case 89: /* multiselect_op ::= EXCEPT|INTERSECT */ yytestcase(yyruleno==89);
|
|
+{yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-OP*/}
|
|
break;
|
|
- case 86: /* multiselect_op ::= UNION ALL */
|
|
-{yymsp[-1].minor.yy100 = TK_ALL;}
|
|
+ case 88: /* multiselect_op ::= UNION ALL */
|
|
+{yymsp[-1].minor.yy192 = TK_ALL;}
|
|
break;
|
|
- case 88: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
|
|
+ case 90: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt orderby_opt limit_opt */
|
|
{
|
|
- yymsp[-8].minor.yy391 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy94,yymsp[-5].minor.yy407,yymsp[-4].minor.yy102,yymsp[-3].minor.yy94,yymsp[-2].minor.yy102,yymsp[-1].minor.yy94,yymsp[-7].minor.yy100,yymsp[0].minor.yy102);
|
|
+ yymsp[-8].minor.yy539 = sqlite3SelectNew(pParse,yymsp[-6].minor.yy242,yymsp[-5].minor.yy47,yymsp[-4].minor.yy202,yymsp[-3].minor.yy242,yymsp[-2].minor.yy202,yymsp[-1].minor.yy242,yymsp[-7].minor.yy192,yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 89: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
|
|
+ case 91: /* oneselect ::= SELECT distinct selcollist from where_opt groupby_opt having_opt window_clause orderby_opt limit_opt */
|
|
{
|
|
- yymsp[-9].minor.yy391 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy94,yymsp[-6].minor.yy407,yymsp[-5].minor.yy102,yymsp[-4].minor.yy94,yymsp[-3].minor.yy102,yymsp[-1].minor.yy94,yymsp[-8].minor.yy100,yymsp[0].minor.yy102);
|
|
- if( yymsp[-9].minor.yy391 ){
|
|
- yymsp[-9].minor.yy391->pWinDefn = yymsp[-2].minor.yy379;
|
|
+ yymsp[-9].minor.yy539 = sqlite3SelectNew(pParse,yymsp[-7].minor.yy242,yymsp[-6].minor.yy47,yymsp[-5].minor.yy202,yymsp[-4].minor.yy242,yymsp[-3].minor.yy202,yymsp[-1].minor.yy242,yymsp[-8].minor.yy192,yymsp[0].minor.yy202);
|
|
+ if( yymsp[-9].minor.yy539 ){
|
|
+ yymsp[-9].minor.yy539->pWinDefn = yymsp[-2].minor.yy303;
|
|
}else{
|
|
- sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy379);
|
|
+ sqlite3WindowListDelete(pParse->db, yymsp[-2].minor.yy303);
|
|
}
|
|
}
|
|
break;
|
|
- case 90: /* values ::= VALUES LP nexprlist RP */
|
|
+ case 92: /* values ::= VALUES LP nexprlist RP */
|
|
{
|
|
- yymsp[-3].minor.yy391 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy94,0,0,0,0,0,SF_Values,0);
|
|
+ yymsp[-3].minor.yy539 = sqlite3SelectNew(pParse,yymsp[-1].minor.yy242,0,0,0,0,0,SF_Values,0);
|
|
}
|
|
break;
|
|
- case 91: /* values ::= values COMMA LP nexprlist RP */
|
|
+ case 93: /* values ::= values COMMA LP nexprlist RP */
|
|
{
|
|
- Select *pRight, *pLeft = yymsp[-4].minor.yy391;
|
|
- pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy94,0,0,0,0,0,SF_Values|SF_MultiValue,0);
|
|
+ Select *pRight, *pLeft = yymsp[-4].minor.yy539;
|
|
+ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy242,0,0,0,0,0,SF_Values|SF_MultiValue,0);
|
|
if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
|
|
if( pRight ){
|
|
pRight->op = TK_ALL;
|
|
pRight->pPrior = pLeft;
|
|
- yymsp[-4].minor.yy391 = pRight;
|
|
+ yymsp[-4].minor.yy539 = pRight;
|
|
}else{
|
|
- yymsp[-4].minor.yy391 = pLeft;
|
|
+ yymsp[-4].minor.yy539 = pLeft;
|
|
}
|
|
}
|
|
break;
|
|
- case 92: /* distinct ::= DISTINCT */
|
|
-{yymsp[0].minor.yy100 = SF_Distinct;}
|
|
+ case 94: /* distinct ::= DISTINCT */
|
|
+{yymsp[0].minor.yy192 = SF_Distinct;}
|
|
break;
|
|
- case 93: /* distinct ::= ALL */
|
|
-{yymsp[0].minor.yy100 = SF_All;}
|
|
+ case 95: /* distinct ::= ALL */
|
|
+{yymsp[0].minor.yy192 = SF_All;}
|
|
break;
|
|
- case 95: /* sclp ::= */
|
|
- case 128: /* orderby_opt ::= */ yytestcase(yyruleno==128);
|
|
- case 135: /* groupby_opt ::= */ yytestcase(yyruleno==135);
|
|
- case 215: /* exprlist ::= */ yytestcase(yyruleno==215);
|
|
- case 218: /* paren_exprlist ::= */ yytestcase(yyruleno==218);
|
|
- case 223: /* eidlist_opt ::= */ yytestcase(yyruleno==223);
|
|
-{yymsp[1].minor.yy94 = 0;}
|
|
+ case 97: /* sclp ::= */
|
|
+ case 130: /* orderby_opt ::= */ yytestcase(yyruleno==130);
|
|
+ case 140: /* groupby_opt ::= */ yytestcase(yyruleno==140);
|
|
+ case 220: /* exprlist ::= */ yytestcase(yyruleno==220);
|
|
+ case 223: /* paren_exprlist ::= */ yytestcase(yyruleno==223);
|
|
+ case 228: /* eidlist_opt ::= */ yytestcase(yyruleno==228);
|
|
+{yymsp[1].minor.yy242 = 0;}
|
|
break;
|
|
- case 96: /* selcollist ::= sclp scanpt expr scanpt as */
|
|
+ case 98: /* selcollist ::= sclp scanpt expr scanpt as */
|
|
{
|
|
- yymsp[-4].minor.yy94 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy94, yymsp[-2].minor.yy102);
|
|
- if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy94, &yymsp[0].minor.yy0, 1);
|
|
- sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy94,yymsp[-3].minor.yy528,yymsp[-1].minor.yy528);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy242, yymsp[-2].minor.yy202);
|
|
+ if( yymsp[0].minor.yy0.n>0 ) sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy242, &yymsp[0].minor.yy0, 1);
|
|
+ sqlite3ExprListSetSpan(pParse,yymsp[-4].minor.yy242,yymsp[-3].minor.yy436,yymsp[-1].minor.yy436);
|
|
}
|
|
break;
|
|
- case 97: /* selcollist ::= sclp scanpt STAR */
|
|
+ case 99: /* selcollist ::= sclp scanpt STAR */
|
|
{
|
|
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
|
|
- yymsp[-2].minor.yy94 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy94, p);
|
|
+ yymsp[-2].minor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-2].minor.yy242, p);
|
|
}
|
|
break;
|
|
- case 98: /* selcollist ::= sclp scanpt nm DOT STAR */
|
|
+ case 100: /* selcollist ::= sclp scanpt nm DOT STAR */
|
|
{
|
|
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0);
|
|
Expr *pLeft = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
|
|
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight);
|
|
- yymsp[-4].minor.yy94 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy94, pDot);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, pDot);
|
|
}
|
|
break;
|
|
- case 99: /* as ::= AS nm */
|
|
- case 110: /* dbnm ::= DOT nm */ yytestcase(yyruleno==110);
|
|
- case 239: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==239);
|
|
- case 240: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==240);
|
|
+ case 101: /* as ::= AS nm */
|
|
+ case 112: /* dbnm ::= DOT nm */ yytestcase(yyruleno==112);
|
|
+ case 244: /* plus_num ::= PLUS INTEGER|FLOAT */ yytestcase(yyruleno==244);
|
|
+ case 245: /* minus_num ::= MINUS INTEGER|FLOAT */ yytestcase(yyruleno==245);
|
|
{yymsp[-1].minor.yy0 = yymsp[0].minor.yy0;}
|
|
break;
|
|
- case 101: /* from ::= */
|
|
-{yymsp[1].minor.yy407 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy407));}
|
|
+ case 103: /* from ::= */
|
|
+{yymsp[1].minor.yy47 = sqlite3DbMallocZero(pParse->db, sizeof(*yymsp[1].minor.yy47));}
|
|
break;
|
|
- case 102: /* from ::= FROM seltablist */
|
|
+ case 104: /* from ::= FROM seltablist */
|
|
{
|
|
- yymsp[-1].minor.yy407 = yymsp[0].minor.yy407;
|
|
- sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy407);
|
|
+ yymsp[-1].minor.yy47 = yymsp[0].minor.yy47;
|
|
+ sqlite3SrcListShiftJoinType(yymsp[-1].minor.yy47);
|
|
}
|
|
break;
|
|
- case 103: /* stl_prefix ::= seltablist joinop */
|
|
+ case 105: /* stl_prefix ::= seltablist joinop */
|
|
{
|
|
- if( ALWAYS(yymsp[-1].minor.yy407 && yymsp[-1].minor.yy407->nSrc>0) ) yymsp[-1].minor.yy407->a[yymsp[-1].minor.yy407->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy100;
|
|
+ if( ALWAYS(yymsp[-1].minor.yy47 && yymsp[-1].minor.yy47->nSrc>0) ) yymsp[-1].minor.yy47->a[yymsp[-1].minor.yy47->nSrc-1].fg.jointype = (u8)yymsp[0].minor.yy192;
|
|
}
|
|
break;
|
|
- case 104: /* stl_prefix ::= */
|
|
-{yymsp[1].minor.yy407 = 0;}
|
|
+ case 106: /* stl_prefix ::= */
|
|
+{yymsp[1].minor.yy47 = 0;}
|
|
break;
|
|
- case 105: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
|
|
+ case 107: /* seltablist ::= stl_prefix nm dbnm as indexed_opt on_opt using_opt */
|
|
{
|
|
- yymsp[-6].minor.yy407 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy407,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy102,yymsp[0].minor.yy76);
|
|
- sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy407, &yymsp[-2].minor.yy0);
|
|
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,&yymsp[-5].minor.yy0,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
|
|
+ sqlite3SrcListIndexedBy(pParse, yymsp[-6].minor.yy47, &yymsp[-2].minor.yy0);
|
|
}
|
|
break;
|
|
- case 106: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
|
|
+ case 108: /* seltablist ::= stl_prefix nm dbnm LP exprlist RP as on_opt using_opt */
|
|
{
|
|
- yymsp[-8].minor.yy407 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy407,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy102,yymsp[0].minor.yy76);
|
|
- sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy407, yymsp[-4].minor.yy94);
|
|
+ yymsp[-8].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-8].minor.yy47,&yymsp[-7].minor.yy0,&yymsp[-6].minor.yy0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
|
|
+ sqlite3SrcListFuncArgs(pParse, yymsp[-8].minor.yy47, yymsp[-4].minor.yy242);
|
|
}
|
|
break;
|
|
- case 107: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
|
|
+ case 109: /* seltablist ::= stl_prefix LP select RP as on_opt using_opt */
|
|
{
|
|
- yymsp[-6].minor.yy407 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy407,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy391,yymsp[-1].minor.yy102,yymsp[0].minor.yy76);
|
|
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,yymsp[-4].minor.yy539,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
|
|
}
|
|
break;
|
|
- case 108: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
|
|
+ case 110: /* seltablist ::= stl_prefix LP seltablist RP as on_opt using_opt */
|
|
{
|
|
- if( yymsp[-6].minor.yy407==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy102==0 && yymsp[0].minor.yy76==0 ){
|
|
- yymsp[-6].minor.yy407 = yymsp[-4].minor.yy407;
|
|
- }else if( yymsp[-4].minor.yy407->nSrc==1 ){
|
|
- yymsp[-6].minor.yy407 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy407,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy102,yymsp[0].minor.yy76);
|
|
- if( yymsp[-6].minor.yy407 ){
|
|
- struct SrcList_item *pNew = &yymsp[-6].minor.yy407->a[yymsp[-6].minor.yy407->nSrc-1];
|
|
- struct SrcList_item *pOld = yymsp[-4].minor.yy407->a;
|
|
+ if( yymsp[-6].minor.yy47==0 && yymsp[-2].minor.yy0.n==0 && yymsp[-1].minor.yy202==0 && yymsp[0].minor.yy600==0 ){
|
|
+ yymsp[-6].minor.yy47 = yymsp[-4].minor.yy47;
|
|
+ }else if( yymsp[-4].minor.yy47->nSrc==1 ){
|
|
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,0,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
|
|
+ if( yymsp[-6].minor.yy47 ){
|
|
+ struct SrcList_item *pNew = &yymsp[-6].minor.yy47->a[yymsp[-6].minor.yy47->nSrc-1];
|
|
+ struct SrcList_item *pOld = yymsp[-4].minor.yy47->a;
|
|
pNew->zName = pOld->zName;
|
|
pNew->zDatabase = pOld->zDatabase;
|
|
pNew->pSelect = pOld->pSelect;
|
|
@@ -152360,201 +157179,208 @@
|
|
pOld->zName = pOld->zDatabase = 0;
|
|
pOld->pSelect = 0;
|
|
}
|
|
- sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy407);
|
|
+ sqlite3SrcListDelete(pParse->db, yymsp[-4].minor.yy47);
|
|
}else{
|
|
Select *pSubquery;
|
|
- sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy407);
|
|
- pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy407,0,0,0,0,SF_NestedFrom,0);
|
|
- yymsp[-6].minor.yy407 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy407,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy102,yymsp[0].minor.yy76);
|
|
+ sqlite3SrcListShiftJoinType(yymsp[-4].minor.yy47);
|
|
+ pSubquery = sqlite3SelectNew(pParse,0,yymsp[-4].minor.yy47,0,0,0,0,SF_NestedFrom,0);
|
|
+ yymsp[-6].minor.yy47 = sqlite3SrcListAppendFromTerm(pParse,yymsp[-6].minor.yy47,0,0,&yymsp[-2].minor.yy0,pSubquery,yymsp[-1].minor.yy202,yymsp[0].minor.yy600);
|
|
}
|
|
}
|
|
break;
|
|
- case 109: /* dbnm ::= */
|
|
- case 123: /* indexed_opt ::= */ yytestcase(yyruleno==123);
|
|
+ case 111: /* dbnm ::= */
|
|
+ case 125: /* indexed_opt ::= */ yytestcase(yyruleno==125);
|
|
{yymsp[1].minor.yy0.z=0; yymsp[1].minor.yy0.n=0;}
|
|
break;
|
|
- case 111: /* fullname ::= nm */
|
|
+ case 113: /* fullname ::= nm */
|
|
{
|
|
- yylhsminor.yy407 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
|
|
- if( IN_RENAME_OBJECT && yylhsminor.yy407 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy407->a[0].zName, &yymsp[0].minor.yy0);
|
|
+ yylhsminor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0);
|
|
+ if( IN_RENAME_OBJECT && yylhsminor.yy47 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy47->a[0].zName, &yymsp[0].minor.yy0);
|
|
}
|
|
- yymsp[0].minor.yy407 = yylhsminor.yy407;
|
|
+ yymsp[0].minor.yy47 = yylhsminor.yy47;
|
|
break;
|
|
- case 112: /* fullname ::= nm DOT nm */
|
|
+ case 114: /* fullname ::= nm DOT nm */
|
|
{
|
|
- yylhsminor.yy407 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
|
|
- if( IN_RENAME_OBJECT && yylhsminor.yy407 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy407->a[0].zName, &yymsp[0].minor.yy0);
|
|
+ yylhsminor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0);
|
|
+ if( IN_RENAME_OBJECT && yylhsminor.yy47 ) sqlite3RenameTokenMap(pParse, yylhsminor.yy47->a[0].zName, &yymsp[0].minor.yy0);
|
|
}
|
|
- yymsp[-2].minor.yy407 = yylhsminor.yy407;
|
|
+ yymsp[-2].minor.yy47 = yylhsminor.yy47;
|
|
break;
|
|
- case 113: /* xfullname ::= nm */
|
|
-{yymsp[0].minor.yy407 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
|
|
+ case 115: /* xfullname ::= nm */
|
|
+{yymsp[0].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[0].minor.yy0,0); /*A-overwrites-X*/}
|
|
break;
|
|
- case 114: /* xfullname ::= nm DOT nm */
|
|
-{yymsp[-2].minor.yy407 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
|
|
+ case 116: /* xfullname ::= nm DOT nm */
|
|
+{yymsp[-2].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0); /*A-overwrites-X*/}
|
|
break;
|
|
- case 115: /* xfullname ::= nm DOT nm AS nm */
|
|
+ case 117: /* xfullname ::= nm DOT nm AS nm */
|
|
{
|
|
- yymsp[-4].minor.yy407 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
|
|
- if( yymsp[-4].minor.yy407 ) yymsp[-4].minor.yy407->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
|
|
+ yymsp[-4].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,&yymsp[-2].minor.yy0); /*A-overwrites-X*/
|
|
+ if( yymsp[-4].minor.yy47 ) yymsp[-4].minor.yy47->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
|
|
}
|
|
break;
|
|
- case 116: /* xfullname ::= nm AS nm */
|
|
+ case 118: /* xfullname ::= nm AS nm */
|
|
{
|
|
- yymsp[-2].minor.yy407 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
|
|
- if( yymsp[-2].minor.yy407 ) yymsp[-2].minor.yy407->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
|
|
+ yymsp[-2].minor.yy47 = sqlite3SrcListAppend(pParse,0,&yymsp[-2].minor.yy0,0); /*A-overwrites-X*/
|
|
+ if( yymsp[-2].minor.yy47 ) yymsp[-2].minor.yy47->a[0].zAlias = sqlite3NameFromToken(pParse->db, &yymsp[0].minor.yy0);
|
|
}
|
|
break;
|
|
- case 117: /* joinop ::= COMMA|JOIN */
|
|
-{ yymsp[0].minor.yy100 = JT_INNER; }
|
|
+ case 119: /* joinop ::= COMMA|JOIN */
|
|
+{ yymsp[0].minor.yy192 = JT_INNER; }
|
|
break;
|
|
- case 118: /* joinop ::= JOIN_KW JOIN */
|
|
-{yymsp[-1].minor.yy100 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
|
|
+ case 120: /* joinop ::= JOIN_KW JOIN */
|
|
+{yymsp[-1].minor.yy192 = sqlite3JoinType(pParse,&yymsp[-1].minor.yy0,0,0); /*X-overwrites-A*/}
|
|
break;
|
|
- case 119: /* joinop ::= JOIN_KW nm JOIN */
|
|
-{yymsp[-2].minor.yy100 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
|
|
+ case 121: /* joinop ::= JOIN_KW nm JOIN */
|
|
+{yymsp[-2].minor.yy192 = sqlite3JoinType(pParse,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0,0); /*X-overwrites-A*/}
|
|
break;
|
|
- case 120: /* joinop ::= JOIN_KW nm nm JOIN */
|
|
-{yymsp[-3].minor.yy100 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
|
|
+ case 122: /* joinop ::= JOIN_KW nm nm JOIN */
|
|
+{yymsp[-3].minor.yy192 = sqlite3JoinType(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);/*X-overwrites-A*/}
|
|
break;
|
|
- case 121: /* on_opt ::= ON expr */
|
|
- case 138: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==138);
|
|
- case 145: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==145);
|
|
- case 211: /* case_else ::= ELSE expr */ yytestcase(yyruleno==211);
|
|
- case 232: /* vinto ::= INTO expr */ yytestcase(yyruleno==232);
|
|
-{yymsp[-1].minor.yy102 = yymsp[0].minor.yy102;}
|
|
+ case 123: /* on_opt ::= ON expr */
|
|
+ case 143: /* having_opt ::= HAVING expr */ yytestcase(yyruleno==143);
|
|
+ case 150: /* where_opt ::= WHERE expr */ yytestcase(yyruleno==150);
|
|
+ case 216: /* case_else ::= ELSE expr */ yytestcase(yyruleno==216);
|
|
+ case 237: /* vinto ::= INTO expr */ yytestcase(yyruleno==237);
|
|
+{yymsp[-1].minor.yy202 = yymsp[0].minor.yy202;}
|
|
break;
|
|
- case 122: /* on_opt ::= */
|
|
- case 137: /* having_opt ::= */ yytestcase(yyruleno==137);
|
|
- case 139: /* limit_opt ::= */ yytestcase(yyruleno==139);
|
|
- case 144: /* where_opt ::= */ yytestcase(yyruleno==144);
|
|
- case 212: /* case_else ::= */ yytestcase(yyruleno==212);
|
|
- case 214: /* case_operand ::= */ yytestcase(yyruleno==214);
|
|
- case 233: /* vinto ::= */ yytestcase(yyruleno==233);
|
|
-{yymsp[1].minor.yy102 = 0;}
|
|
+ case 124: /* on_opt ::= */
|
|
+ case 142: /* having_opt ::= */ yytestcase(yyruleno==142);
|
|
+ case 144: /* limit_opt ::= */ yytestcase(yyruleno==144);
|
|
+ case 149: /* where_opt ::= */ yytestcase(yyruleno==149);
|
|
+ case 217: /* case_else ::= */ yytestcase(yyruleno==217);
|
|
+ case 219: /* case_operand ::= */ yytestcase(yyruleno==219);
|
|
+ case 238: /* vinto ::= */ yytestcase(yyruleno==238);
|
|
+{yymsp[1].minor.yy202 = 0;}
|
|
break;
|
|
- case 124: /* indexed_opt ::= INDEXED BY nm */
|
|
+ case 126: /* indexed_opt ::= INDEXED BY nm */
|
|
{yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;}
|
|
break;
|
|
- case 125: /* indexed_opt ::= NOT INDEXED */
|
|
+ case 127: /* indexed_opt ::= NOT INDEXED */
|
|
{yymsp[-1].minor.yy0.z=0; yymsp[-1].minor.yy0.n=1;}
|
|
break;
|
|
- case 126: /* using_opt ::= USING LP idlist RP */
|
|
-{yymsp[-3].minor.yy76 = yymsp[-1].minor.yy76;}
|
|
+ case 128: /* using_opt ::= USING LP idlist RP */
|
|
+{yymsp[-3].minor.yy600 = yymsp[-1].minor.yy600;}
|
|
break;
|
|
- case 127: /* using_opt ::= */
|
|
- case 159: /* idlist_opt ::= */ yytestcase(yyruleno==159);
|
|
-{yymsp[1].minor.yy76 = 0;}
|
|
+ case 129: /* using_opt ::= */
|
|
+ case 164: /* idlist_opt ::= */ yytestcase(yyruleno==164);
|
|
+{yymsp[1].minor.yy600 = 0;}
|
|
break;
|
|
- case 129: /* orderby_opt ::= ORDER BY sortlist */
|
|
- case 136: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==136);
|
|
-{yymsp[-2].minor.yy94 = yymsp[0].minor.yy94;}
|
|
+ case 131: /* orderby_opt ::= ORDER BY sortlist */
|
|
+ case 141: /* groupby_opt ::= GROUP BY nexprlist */ yytestcase(yyruleno==141);
|
|
+{yymsp[-2].minor.yy242 = yymsp[0].minor.yy242;}
|
|
break;
|
|
- case 130: /* sortlist ::= sortlist COMMA expr sortorder */
|
|
+ case 132: /* sortlist ::= sortlist COMMA expr sortorder nulls */
|
|
{
|
|
- yymsp[-3].minor.yy94 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy94,yymsp[-1].minor.yy102);
|
|
- sqlite3ExprListSetSortOrder(yymsp[-3].minor.yy94,yymsp[0].minor.yy100);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202);
|
|
+ sqlite3ExprListSetSortOrder(yymsp[-4].minor.yy242,yymsp[-1].minor.yy192,yymsp[0].minor.yy192);
|
|
}
|
|
break;
|
|
- case 131: /* sortlist ::= expr sortorder */
|
|
+ case 133: /* sortlist ::= expr sortorder nulls */
|
|
{
|
|
- yymsp[-1].minor.yy94 = sqlite3ExprListAppend(pParse,0,yymsp[-1].minor.yy102); /*A-overwrites-Y*/
|
|
- sqlite3ExprListSetSortOrder(yymsp[-1].minor.yy94,yymsp[0].minor.yy100);
|
|
+ yymsp[-2].minor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[-2].minor.yy202); /*A-overwrites-Y*/
|
|
+ sqlite3ExprListSetSortOrder(yymsp[-2].minor.yy242,yymsp[-1].minor.yy192,yymsp[0].minor.yy192);
|
|
}
|
|
break;
|
|
- case 132: /* sortorder ::= ASC */
|
|
-{yymsp[0].minor.yy100 = SQLITE_SO_ASC;}
|
|
+ case 134: /* sortorder ::= ASC */
|
|
+{yymsp[0].minor.yy192 = SQLITE_SO_ASC;}
|
|
break;
|
|
- case 133: /* sortorder ::= DESC */
|
|
-{yymsp[0].minor.yy100 = SQLITE_SO_DESC;}
|
|
+ case 135: /* sortorder ::= DESC */
|
|
+{yymsp[0].minor.yy192 = SQLITE_SO_DESC;}
|
|
break;
|
|
- case 134: /* sortorder ::= */
|
|
-{yymsp[1].minor.yy100 = SQLITE_SO_UNDEFINED;}
|
|
+ case 136: /* sortorder ::= */
|
|
+ case 139: /* nulls ::= */ yytestcase(yyruleno==139);
|
|
+{yymsp[1].minor.yy192 = SQLITE_SO_UNDEFINED;}
|
|
break;
|
|
- case 140: /* limit_opt ::= LIMIT expr */
|
|
-{yymsp[-1].minor.yy102 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy102,0);}
|
|
+ case 137: /* nulls ::= NULLS FIRST */
|
|
+{yymsp[-1].minor.yy192 = SQLITE_SO_ASC;}
|
|
break;
|
|
- case 141: /* limit_opt ::= LIMIT expr OFFSET expr */
|
|
-{yymsp[-3].minor.yy102 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy102,yymsp[0].minor.yy102);}
|
|
+ case 138: /* nulls ::= NULLS LAST */
|
|
+{yymsp[-1].minor.yy192 = SQLITE_SO_DESC;}
|
|
break;
|
|
- case 142: /* limit_opt ::= LIMIT expr COMMA expr */
|
|
-{yymsp[-3].minor.yy102 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy102,yymsp[-2].minor.yy102);}
|
|
+ case 145: /* limit_opt ::= LIMIT expr */
|
|
+{yymsp[-1].minor.yy202 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy202,0);}
|
|
break;
|
|
- case 143: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
|
|
+ case 146: /* limit_opt ::= LIMIT expr OFFSET expr */
|
|
+{yymsp[-3].minor.yy202 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
|
|
+ break;
|
|
+ case 147: /* limit_opt ::= LIMIT expr COMMA expr */
|
|
+{yymsp[-3].minor.yy202 = sqlite3PExpr(pParse,TK_LIMIT,yymsp[0].minor.yy202,yymsp[-2].minor.yy202);}
|
|
+ break;
|
|
+ case 148: /* cmd ::= with DELETE FROM xfullname indexed_opt where_opt */
|
|
{
|
|
- sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy407, &yymsp[-1].minor.yy0);
|
|
- sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy407,yymsp[0].minor.yy102,0,0);
|
|
+ sqlite3SrcListIndexedBy(pParse, yymsp[-2].minor.yy47, &yymsp[-1].minor.yy0);
|
|
+ sqlite3DeleteFrom(pParse,yymsp[-2].minor.yy47,yymsp[0].minor.yy202,0,0);
|
|
}
|
|
break;
|
|
- case 146: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
|
|
+ case 151: /* cmd ::= with UPDATE orconf xfullname indexed_opt SET setlist where_opt */
|
|
{
|
|
- sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy407, &yymsp[-3].minor.yy0);
|
|
- sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy94,"set list");
|
|
- sqlite3Update(pParse,yymsp[-4].minor.yy407,yymsp[-1].minor.yy94,yymsp[0].minor.yy102,yymsp[-5].minor.yy100,0,0,0);
|
|
+ sqlite3SrcListIndexedBy(pParse, yymsp[-4].minor.yy47, &yymsp[-3].minor.yy0);
|
|
+ sqlite3ExprListCheckLength(pParse,yymsp[-1].minor.yy242,"set list");
|
|
+ sqlite3Update(pParse,yymsp[-4].minor.yy47,yymsp[-1].minor.yy242,yymsp[0].minor.yy202,yymsp[-5].minor.yy192,0,0,0);
|
|
}
|
|
break;
|
|
- case 147: /* setlist ::= setlist COMMA nm EQ expr */
|
|
+ case 152: /* setlist ::= setlist COMMA nm EQ expr */
|
|
{
|
|
- yymsp[-4].minor.yy94 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy94, yymsp[0].minor.yy102);
|
|
- sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy94, &yymsp[-2].minor.yy0, 1);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse, yymsp[-4].minor.yy242, yymsp[0].minor.yy202);
|
|
+ sqlite3ExprListSetName(pParse, yymsp[-4].minor.yy242, &yymsp[-2].minor.yy0, 1);
|
|
}
|
|
break;
|
|
- case 148: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
|
|
+ case 153: /* setlist ::= setlist COMMA LP idlist RP EQ expr */
|
|
{
|
|
- yymsp[-6].minor.yy94 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy94, yymsp[-3].minor.yy76, yymsp[0].minor.yy102);
|
|
+ yymsp[-6].minor.yy242 = sqlite3ExprListAppendVector(pParse, yymsp[-6].minor.yy242, yymsp[-3].minor.yy600, yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 149: /* setlist ::= nm EQ expr */
|
|
+ case 154: /* setlist ::= nm EQ expr */
|
|
{
|
|
- yylhsminor.yy94 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy102);
|
|
- sqlite3ExprListSetName(pParse, yylhsminor.yy94, &yymsp[-2].minor.yy0, 1);
|
|
+ yylhsminor.yy242 = sqlite3ExprListAppend(pParse, 0, yymsp[0].minor.yy202);
|
|
+ sqlite3ExprListSetName(pParse, yylhsminor.yy242, &yymsp[-2].minor.yy0, 1);
|
|
}
|
|
- yymsp[-2].minor.yy94 = yylhsminor.yy94;
|
|
+ yymsp[-2].minor.yy242 = yylhsminor.yy242;
|
|
break;
|
|
- case 150: /* setlist ::= LP idlist RP EQ expr */
|
|
+ case 155: /* setlist ::= LP idlist RP EQ expr */
|
|
{
|
|
- yymsp[-4].minor.yy94 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy76, yymsp[0].minor.yy102);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppendVector(pParse, 0, yymsp[-3].minor.yy600, yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 151: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
|
|
+ case 156: /* cmd ::= with insert_cmd INTO xfullname idlist_opt select upsert */
|
|
{
|
|
- sqlite3Insert(pParse, yymsp[-3].minor.yy407, yymsp[-1].minor.yy391, yymsp[-2].minor.yy76, yymsp[-5].minor.yy100, yymsp[0].minor.yy95);
|
|
+ sqlite3Insert(pParse, yymsp[-3].minor.yy47, yymsp[-1].minor.yy539, yymsp[-2].minor.yy600, yymsp[-5].minor.yy192, yymsp[0].minor.yy318);
|
|
}
|
|
break;
|
|
- case 152: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
|
|
+ case 157: /* cmd ::= with insert_cmd INTO xfullname idlist_opt DEFAULT VALUES */
|
|
{
|
|
- sqlite3Insert(pParse, yymsp[-3].minor.yy407, 0, yymsp[-2].minor.yy76, yymsp[-5].minor.yy100, 0);
|
|
+ sqlite3Insert(pParse, yymsp[-3].minor.yy47, 0, yymsp[-2].minor.yy600, yymsp[-5].minor.yy192, 0);
|
|
}
|
|
break;
|
|
- case 153: /* upsert ::= */
|
|
-{ yymsp[1].minor.yy95 = 0; }
|
|
+ case 158: /* upsert ::= */
|
|
+{ yymsp[1].minor.yy318 = 0; }
|
|
break;
|
|
- case 154: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
|
|
-{ yymsp[-10].minor.yy95 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy94,yymsp[-5].minor.yy102,yymsp[-1].minor.yy94,yymsp[0].minor.yy102);}
|
|
+ case 159: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO UPDATE SET setlist where_opt */
|
|
+{ yymsp[-10].minor.yy318 = sqlite3UpsertNew(pParse->db,yymsp[-7].minor.yy242,yymsp[-5].minor.yy202,yymsp[-1].minor.yy242,yymsp[0].minor.yy202);}
|
|
break;
|
|
- case 155: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
|
|
-{ yymsp[-7].minor.yy95 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy94,yymsp[-2].minor.yy102,0,0); }
|
|
+ case 160: /* upsert ::= ON CONFLICT LP sortlist RP where_opt DO NOTHING */
|
|
+{ yymsp[-7].minor.yy318 = sqlite3UpsertNew(pParse->db,yymsp[-4].minor.yy242,yymsp[-2].minor.yy202,0,0); }
|
|
break;
|
|
- case 156: /* upsert ::= ON CONFLICT DO NOTHING */
|
|
-{ yymsp[-3].minor.yy95 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
|
|
+ case 161: /* upsert ::= ON CONFLICT DO NOTHING */
|
|
+{ yymsp[-3].minor.yy318 = sqlite3UpsertNew(pParse->db,0,0,0,0); }
|
|
break;
|
|
- case 160: /* idlist_opt ::= LP idlist RP */
|
|
-{yymsp[-2].minor.yy76 = yymsp[-1].minor.yy76;}
|
|
+ case 165: /* idlist_opt ::= LP idlist RP */
|
|
+{yymsp[-2].minor.yy600 = yymsp[-1].minor.yy600;}
|
|
break;
|
|
- case 161: /* idlist ::= idlist COMMA nm */
|
|
-{yymsp[-2].minor.yy76 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy76,&yymsp[0].minor.yy0);}
|
|
+ case 166: /* idlist ::= idlist COMMA nm */
|
|
+{yymsp[-2].minor.yy600 = sqlite3IdListAppend(pParse,yymsp[-2].minor.yy600,&yymsp[0].minor.yy0);}
|
|
break;
|
|
- case 162: /* idlist ::= nm */
|
|
-{yymsp[0].minor.yy76 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
|
|
+ case 167: /* idlist ::= nm */
|
|
+{yymsp[0].minor.yy600 = sqlite3IdListAppend(pParse,0,&yymsp[0].minor.yy0); /*A-overwrites-Y*/}
|
|
break;
|
|
- case 163: /* expr ::= LP expr RP */
|
|
-{yymsp[-2].minor.yy102 = yymsp[-1].minor.yy102;}
|
|
+ case 168: /* expr ::= LP expr RP */
|
|
+{yymsp[-2].minor.yy202 = yymsp[-1].minor.yy202;}
|
|
break;
|
|
- case 164: /* expr ::= ID|INDEXED */
|
|
- case 165: /* expr ::= JOIN_KW */ yytestcase(yyruleno==165);
|
|
-{yymsp[0].minor.yy102=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
|
|
+ case 169: /* expr ::= ID|INDEXED */
|
|
+ case 170: /* expr ::= JOIN_KW */ yytestcase(yyruleno==170);
|
|
+{yymsp[0].minor.yy202=tokenExpr(pParse,TK_ID,yymsp[0].minor.yy0); /*A-overwrites-X*/}
|
|
break;
|
|
- case 166: /* expr ::= nm DOT nm */
|
|
+ case 171: /* expr ::= nm DOT nm */
|
|
{
|
|
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
|
|
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[0].minor.yy0, 1);
|
|
@@ -152562,11 +157388,11 @@
|
|
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[0].minor.yy0);
|
|
sqlite3RenameTokenMap(pParse, (void*)temp1, &yymsp[-2].minor.yy0);
|
|
}
|
|
- yylhsminor.yy102 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
|
|
+ yylhsminor.yy202 = sqlite3PExpr(pParse, TK_DOT, temp1, temp2);
|
|
}
|
|
- yymsp[-2].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[-2].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 167: /* expr ::= nm DOT nm DOT nm */
|
|
+ case 172: /* expr ::= nm DOT nm DOT nm */
|
|
{
|
|
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-4].minor.yy0, 1);
|
|
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &yymsp[-2].minor.yy0, 1);
|
|
@@ -152576,26 +157402,26 @@
|
|
sqlite3RenameTokenMap(pParse, (void*)temp3, &yymsp[0].minor.yy0);
|
|
sqlite3RenameTokenMap(pParse, (void*)temp2, &yymsp[-2].minor.yy0);
|
|
}
|
|
- yylhsminor.yy102 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
|
|
+ yylhsminor.yy202 = sqlite3PExpr(pParse, TK_DOT, temp1, temp4);
|
|
}
|
|
- yymsp[-4].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[-4].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 168: /* term ::= NULL|FLOAT|BLOB */
|
|
- case 169: /* term ::= STRING */ yytestcase(yyruleno==169);
|
|
-{yymsp[0].minor.yy102=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
|
|
+ case 173: /* term ::= NULL|FLOAT|BLOB */
|
|
+ case 174: /* term ::= STRING */ yytestcase(yyruleno==174);
|
|
+{yymsp[0].minor.yy202=tokenExpr(pParse,yymsp[0].major,yymsp[0].minor.yy0); /*A-overwrites-X*/}
|
|
break;
|
|
- case 170: /* term ::= INTEGER */
|
|
+ case 175: /* term ::= INTEGER */
|
|
{
|
|
- yylhsminor.yy102 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
|
|
+ yylhsminor.yy202 = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &yymsp[0].minor.yy0, 1);
|
|
}
|
|
- yymsp[0].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[0].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 171: /* expr ::= VARIABLE */
|
|
+ case 176: /* expr ::= VARIABLE */
|
|
{
|
|
if( !(yymsp[0].minor.yy0.z[0]=='#' && sqlite3Isdigit(yymsp[0].minor.yy0.z[1])) ){
|
|
u32 n = yymsp[0].minor.yy0.n;
|
|
- yymsp[0].minor.yy102 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
|
|
- sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy102, n);
|
|
+ yymsp[0].minor.yy202 = tokenExpr(pParse, TK_VARIABLE, yymsp[0].minor.yy0);
|
|
+ sqlite3ExprAssignVarNumber(pParse, yymsp[0].minor.yy202, n);
|
|
}else{
|
|
/* When doing a nested parse, one can include terms in an expression
|
|
** that look like this: #1 #2 ... These terms refer to registers
|
|
@@ -152604,156 +157430,159 @@
|
|
assert( t.n>=2 );
|
|
if( pParse->nested==0 ){
|
|
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
|
|
- yymsp[0].minor.yy102 = 0;
|
|
+ yymsp[0].minor.yy202 = 0;
|
|
}else{
|
|
- yymsp[0].minor.yy102 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
|
|
- if( yymsp[0].minor.yy102 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy102->iTable);
|
|
+ yymsp[0].minor.yy202 = sqlite3PExpr(pParse, TK_REGISTER, 0, 0);
|
|
+ if( yymsp[0].minor.yy202 ) sqlite3GetInt32(&t.z[1], &yymsp[0].minor.yy202->iTable);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
- case 172: /* expr ::= expr COLLATE ID|STRING */
|
|
+ case 177: /* expr ::= expr COLLATE ID|STRING */
|
|
{
|
|
- yymsp[-2].minor.yy102 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy102, &yymsp[0].minor.yy0, 1);
|
|
+ yymsp[-2].minor.yy202 = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy202, &yymsp[0].minor.yy0, 1);
|
|
}
|
|
break;
|
|
- case 173: /* expr ::= CAST LP expr AS typetoken RP */
|
|
+ case 178: /* expr ::= CAST LP expr AS typetoken RP */
|
|
{
|
|
- yymsp[-5].minor.yy102 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
|
|
- sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy102, yymsp[-3].minor.yy102, 0);
|
|
+ yymsp[-5].minor.yy202 = sqlite3ExprAlloc(pParse->db, TK_CAST, &yymsp[-1].minor.yy0, 1);
|
|
+ sqlite3ExprAttachSubtrees(pParse->db, yymsp[-5].minor.yy202, yymsp[-3].minor.yy202, 0);
|
|
}
|
|
break;
|
|
- case 174: /* expr ::= ID|INDEXED LP distinct exprlist RP */
|
|
+ case 179: /* expr ::= ID|INDEXED LP distinct exprlist RP */
|
|
{
|
|
- yylhsminor.yy102 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy94, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy100);
|
|
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0, yymsp[-2].minor.yy192);
|
|
}
|
|
- yymsp[-4].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[-4].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 175: /* expr ::= ID|INDEXED LP STAR RP */
|
|
+ case 180: /* expr ::= ID|INDEXED LP STAR RP */
|
|
{
|
|
- yylhsminor.yy102 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
|
|
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, 0, &yymsp[-3].minor.yy0, 0);
|
|
}
|
|
- yymsp[-3].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[-3].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 176: /* expr ::= ID|INDEXED LP distinct exprlist RP over_clause */
|
|
+ case 181: /* expr ::= ID|INDEXED LP distinct exprlist RP filter_over */
|
|
{
|
|
- yylhsminor.yy102 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy94, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy100);
|
|
- sqlite3WindowAttach(pParse, yylhsminor.yy102, yymsp[0].minor.yy379);
|
|
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, yymsp[-2].minor.yy242, &yymsp[-5].minor.yy0, yymsp[-3].minor.yy192);
|
|
+ sqlite3WindowAttach(pParse, yylhsminor.yy202, yymsp[0].minor.yy303);
|
|
}
|
|
- yymsp[-5].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[-5].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 177: /* expr ::= ID|INDEXED LP STAR RP over_clause */
|
|
+ case 182: /* expr ::= ID|INDEXED LP STAR RP filter_over */
|
|
{
|
|
- yylhsminor.yy102 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
|
|
- sqlite3WindowAttach(pParse, yylhsminor.yy102, yymsp[0].minor.yy379);
|
|
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, 0, &yymsp[-4].minor.yy0, 0);
|
|
+ sqlite3WindowAttach(pParse, yylhsminor.yy202, yymsp[0].minor.yy303);
|
|
}
|
|
- yymsp[-4].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[-4].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 178: /* term ::= CTIME_KW */
|
|
+ case 183: /* term ::= CTIME_KW */
|
|
{
|
|
- yylhsminor.yy102 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
|
|
+ yylhsminor.yy202 = sqlite3ExprFunction(pParse, 0, &yymsp[0].minor.yy0, 0);
|
|
}
|
|
- yymsp[0].minor.yy102 = yylhsminor.yy102;
|
|
+ yymsp[0].minor.yy202 = yylhsminor.yy202;
|
|
break;
|
|
- case 179: /* expr ::= LP nexprlist COMMA expr RP */
|
|
+ case 184: /* expr ::= LP nexprlist COMMA expr RP */
|
|
{
|
|
- ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy94, yymsp[-1].minor.yy102);
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
|
- if( yymsp[-4].minor.yy102 ){
|
|
- yymsp[-4].minor.yy102->x.pList = pList;
|
|
+ ExprList *pList = sqlite3ExprListAppend(pParse, yymsp[-3].minor.yy242, yymsp[-1].minor.yy202);
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_VECTOR, 0, 0);
|
|
+ if( yymsp[-4].minor.yy202 ){
|
|
+ yymsp[-4].minor.yy202->x.pList = pList;
|
|
+ if( ALWAYS(pList->nExpr) ){
|
|
+ yymsp[-4].minor.yy202->flags |= pList->a[0].pExpr->flags & EP_Propagate;
|
|
+ }
|
|
}else{
|
|
sqlite3ExprListDelete(pParse->db, pList);
|
|
}
|
|
}
|
|
break;
|
|
- case 180: /* expr ::= expr AND expr */
|
|
-{yymsp[-2].minor.yy102=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy102,yymsp[0].minor.yy102);}
|
|
+ case 185: /* expr ::= expr AND expr */
|
|
+{yymsp[-2].minor.yy202=sqlite3ExprAnd(pParse,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
|
|
break;
|
|
- case 181: /* expr ::= expr OR expr */
|
|
- case 182: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==182);
|
|
- case 183: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==183);
|
|
- case 184: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==184);
|
|
- case 185: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==185);
|
|
- case 186: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==186);
|
|
- case 187: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==187);
|
|
-{yymsp[-2].minor.yy102=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy102,yymsp[0].minor.yy102);}
|
|
+ case 186: /* expr ::= expr OR expr */
|
|
+ case 187: /* expr ::= expr LT|GT|GE|LE expr */ yytestcase(yyruleno==187);
|
|
+ case 188: /* expr ::= expr EQ|NE expr */ yytestcase(yyruleno==188);
|
|
+ case 189: /* expr ::= expr BITAND|BITOR|LSHIFT|RSHIFT expr */ yytestcase(yyruleno==189);
|
|
+ case 190: /* expr ::= expr PLUS|MINUS expr */ yytestcase(yyruleno==190);
|
|
+ case 191: /* expr ::= expr STAR|SLASH|REM expr */ yytestcase(yyruleno==191);
|
|
+ case 192: /* expr ::= expr CONCAT expr */ yytestcase(yyruleno==192);
|
|
+{yymsp[-2].minor.yy202=sqlite3PExpr(pParse,yymsp[-1].major,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);}
|
|
break;
|
|
- case 188: /* likeop ::= NOT LIKE_KW|MATCH */
|
|
+ case 193: /* likeop ::= NOT LIKE_KW|MATCH */
|
|
{yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.n|=0x80000000; /*yymsp[-1].minor.yy0-overwrite-yymsp[0].minor.yy0*/}
|
|
break;
|
|
- case 189: /* expr ::= expr likeop expr */
|
|
+ case 194: /* expr ::= expr likeop expr */
|
|
{
|
|
ExprList *pList;
|
|
int bNot = yymsp[-1].minor.yy0.n & 0x80000000;
|
|
yymsp[-1].minor.yy0.n &= 0x7fffffff;
|
|
- pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy102);
|
|
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy102);
|
|
- yymsp[-2].minor.yy102 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
|
|
- if( bNot ) yymsp[-2].minor.yy102 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy102, 0);
|
|
- if( yymsp[-2].minor.yy102 ) yymsp[-2].minor.yy102->flags |= EP_InfixFunc;
|
|
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[0].minor.yy202);
|
|
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-2].minor.yy202);
|
|
+ yymsp[-2].minor.yy202 = sqlite3ExprFunction(pParse, pList, &yymsp[-1].minor.yy0, 0);
|
|
+ if( bNot ) yymsp[-2].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-2].minor.yy202, 0);
|
|
+ if( yymsp[-2].minor.yy202 ) yymsp[-2].minor.yy202->flags |= EP_InfixFunc;
|
|
}
|
|
break;
|
|
- case 190: /* expr ::= expr likeop expr ESCAPE expr */
|
|
+ case 195: /* expr ::= expr likeop expr ESCAPE expr */
|
|
{
|
|
ExprList *pList;
|
|
int bNot = yymsp[-3].minor.yy0.n & 0x80000000;
|
|
yymsp[-3].minor.yy0.n &= 0x7fffffff;
|
|
- pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy102);
|
|
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy102);
|
|
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy102);
|
|
- yymsp[-4].minor.yy102 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
|
|
- if( bNot ) yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy102, 0);
|
|
- if( yymsp[-4].minor.yy102 ) yymsp[-4].minor.yy102->flags |= EP_InfixFunc;
|
|
+ pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
|
|
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[-4].minor.yy202);
|
|
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy202);
|
|
+ yymsp[-4].minor.yy202 = sqlite3ExprFunction(pParse, pList, &yymsp[-3].minor.yy0, 0);
|
|
+ if( bNot ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
|
|
+ if( yymsp[-4].minor.yy202 ) yymsp[-4].minor.yy202->flags |= EP_InfixFunc;
|
|
}
|
|
break;
|
|
- case 191: /* expr ::= expr ISNULL|NOTNULL */
|
|
-{yymsp[-1].minor.yy102 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy102,0);}
|
|
+ case 196: /* expr ::= expr ISNULL|NOTNULL */
|
|
+{yymsp[-1].minor.yy202 = sqlite3PExpr(pParse,yymsp[0].major,yymsp[-1].minor.yy202,0);}
|
|
break;
|
|
- case 192: /* expr ::= expr NOT NULL */
|
|
-{yymsp[-2].minor.yy102 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy102,0);}
|
|
+ case 197: /* expr ::= expr NOT NULL */
|
|
+{yymsp[-2].minor.yy202 = sqlite3PExpr(pParse,TK_NOTNULL,yymsp[-2].minor.yy202,0);}
|
|
break;
|
|
- case 193: /* expr ::= expr IS expr */
|
|
+ case 198: /* expr ::= expr IS expr */
|
|
{
|
|
- yymsp[-2].minor.yy102 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy102,yymsp[0].minor.yy102);
|
|
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy102, yymsp[-2].minor.yy102, TK_ISNULL);
|
|
+ yymsp[-2].minor.yy202 = sqlite3PExpr(pParse,TK_IS,yymsp[-2].minor.yy202,yymsp[0].minor.yy202);
|
|
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy202, yymsp[-2].minor.yy202, TK_ISNULL);
|
|
}
|
|
break;
|
|
- case 194: /* expr ::= expr IS NOT expr */
|
|
+ case 199: /* expr ::= expr IS NOT expr */
|
|
{
|
|
- yymsp[-3].minor.yy102 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy102,yymsp[0].minor.yy102);
|
|
- binaryToUnaryIfNull(pParse, yymsp[0].minor.yy102, yymsp[-3].minor.yy102, TK_NOTNULL);
|
|
+ yymsp[-3].minor.yy202 = sqlite3PExpr(pParse,TK_ISNOT,yymsp[-3].minor.yy202,yymsp[0].minor.yy202);
|
|
+ binaryToUnaryIfNull(pParse, yymsp[0].minor.yy202, yymsp[-3].minor.yy202, TK_NOTNULL);
|
|
}
|
|
break;
|
|
- case 195: /* expr ::= NOT expr */
|
|
- case 196: /* expr ::= BITNOT expr */ yytestcase(yyruleno==196);
|
|
-{yymsp[-1].minor.yy102 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy102, 0);/*A-overwrites-B*/}
|
|
+ case 200: /* expr ::= NOT expr */
|
|
+ case 201: /* expr ::= BITNOT expr */ yytestcase(yyruleno==201);
|
|
+{yymsp[-1].minor.yy202 = sqlite3PExpr(pParse, yymsp[-1].major, yymsp[0].minor.yy202, 0);/*A-overwrites-B*/}
|
|
break;
|
|
- case 197: /* expr ::= PLUS|MINUS expr */
|
|
+ case 202: /* expr ::= PLUS|MINUS expr */
|
|
{
|
|
- yymsp[-1].minor.yy102 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy102, 0);
|
|
+ yymsp[-1].minor.yy202 = sqlite3PExpr(pParse, yymsp[-1].major==TK_PLUS ? TK_UPLUS : TK_UMINUS, yymsp[0].minor.yy202, 0);
|
|
/*A-overwrites-B*/
|
|
}
|
|
break;
|
|
- case 198: /* between_op ::= BETWEEN */
|
|
- case 201: /* in_op ::= IN */ yytestcase(yyruleno==201);
|
|
-{yymsp[0].minor.yy100 = 0;}
|
|
+ case 203: /* between_op ::= BETWEEN */
|
|
+ case 206: /* in_op ::= IN */ yytestcase(yyruleno==206);
|
|
+{yymsp[0].minor.yy192 = 0;}
|
|
break;
|
|
- case 200: /* expr ::= expr between_op expr AND expr */
|
|
+ case 205: /* expr ::= expr between_op expr AND expr */
|
|
{
|
|
- ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy102);
|
|
- pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy102);
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy102, 0);
|
|
- if( yymsp[-4].minor.yy102 ){
|
|
- yymsp[-4].minor.yy102->x.pList = pList;
|
|
+ ExprList *pList = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
|
|
+ pList = sqlite3ExprListAppend(pParse,pList, yymsp[0].minor.yy202);
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_BETWEEN, yymsp[-4].minor.yy202, 0);
|
|
+ if( yymsp[-4].minor.yy202 ){
|
|
+ yymsp[-4].minor.yy202->x.pList = pList;
|
|
}else{
|
|
sqlite3ExprListDelete(pParse->db, pList);
|
|
}
|
|
- if( yymsp[-3].minor.yy100 ) yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy102, 0);
|
|
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
|
|
}
|
|
break;
|
|
- case 203: /* expr ::= expr in_op LP exprlist RP */
|
|
+ case 208: /* expr ::= expr in_op LP exprlist RP */
|
|
{
|
|
- if( yymsp[-1].minor.yy94==0 ){
|
|
+ if( yymsp[-1].minor.yy242==0 ){
|
|
/* Expressions of the form
|
|
**
|
|
** expr1 IN ()
|
|
@@ -152762,218 +157591,197 @@
|
|
** simplify to constants 0 (false) and 1 (true), respectively,
|
|
** regardless of the value of expr1.
|
|
*/
|
|
- sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy102);
|
|
- yymsp[-4].minor.yy102 = sqlite3ExprAlloc(pParse->db, TK_INTEGER,&sqlite3IntTokens[yymsp[-3].minor.yy100],1);
|
|
- }else if( yymsp[-1].minor.yy94->nExpr==1 ){
|
|
- /* Expressions of the form:
|
|
- **
|
|
- ** expr1 IN (?1)
|
|
- ** expr1 NOT IN (?2)
|
|
- **
|
|
- ** with exactly one value on the RHS can be simplified to something
|
|
- ** like this:
|
|
- **
|
|
- ** expr1 == ?1
|
|
- ** expr1 <> ?2
|
|
- **
|
|
- ** But, the RHS of the == or <> is marked with the EP_Generic flag
|
|
- ** so that it may not contribute to the computation of comparison
|
|
- ** affinity or the collating sequence to use for comparison. Otherwise,
|
|
- ** the semantics would be subtly different from IN or NOT IN.
|
|
- */
|
|
- Expr *pRHS = yymsp[-1].minor.yy94->a[0].pExpr;
|
|
- yymsp[-1].minor.yy94->a[0].pExpr = 0;
|
|
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy94);
|
|
- /* pRHS cannot be NULL because a malloc error would have been detected
|
|
- ** before now and control would have never reached this point */
|
|
- if( ALWAYS(pRHS) ){
|
|
- pRHS->flags &= ~EP_Collate;
|
|
- pRHS->flags |= EP_Generic;
|
|
- }
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, yymsp[-3].minor.yy100 ? TK_NE : TK_EQ, yymsp[-4].minor.yy102, pRHS);
|
|
- }else{
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy102, 0);
|
|
- if( yymsp[-4].minor.yy102 ){
|
|
- yymsp[-4].minor.yy102->x.pList = yymsp[-1].minor.yy94;
|
|
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy102);
|
|
+ sqlite3ExprUnmapAndDelete(pParse, yymsp[-4].minor.yy202);
|
|
+ yymsp[-4].minor.yy202 = sqlite3Expr(pParse->db, TK_INTEGER, yymsp[-3].minor.yy192 ? "1" : "0");
|
|
+ }else if( yymsp[-1].minor.yy242->nExpr==1 && sqlite3ExprIsConstant(yymsp[-1].minor.yy242->a[0].pExpr) ){
|
|
+ Expr *pRHS = yymsp[-1].minor.yy242->a[0].pExpr;
|
|
+ yymsp[-1].minor.yy242->a[0].pExpr = 0;
|
|
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
|
|
+ pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_EQ, yymsp[-4].minor.yy202, pRHS);
|
|
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
|
|
+ }else{
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
|
|
+ if( yymsp[-4].minor.yy202 ){
|
|
+ yymsp[-4].minor.yy202->x.pList = yymsp[-1].minor.yy242;
|
|
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy202);
|
|
}else{
|
|
- sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy94);
|
|
+ sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy242);
|
|
}
|
|
- if( yymsp[-3].minor.yy100 ) yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy102, 0);
|
|
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
|
|
}
|
|
}
|
|
break;
|
|
- case 204: /* expr ::= LP select RP */
|
|
+ case 209: /* expr ::= LP select RP */
|
|
{
|
|
- yymsp[-2].minor.yy102 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
|
|
- sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy102, yymsp[-1].minor.yy391);
|
|
+ yymsp[-2].minor.yy202 = sqlite3PExpr(pParse, TK_SELECT, 0, 0);
|
|
+ sqlite3PExprAddSelect(pParse, yymsp[-2].minor.yy202, yymsp[-1].minor.yy539);
|
|
}
|
|
break;
|
|
- case 205: /* expr ::= expr in_op LP select RP */
|
|
+ case 210: /* expr ::= expr in_op LP select RP */
|
|
{
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy102, 0);
|
|
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy102, yymsp[-1].minor.yy391);
|
|
- if( yymsp[-3].minor.yy100 ) yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy102, 0);
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
|
|
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy202, yymsp[-1].minor.yy539);
|
|
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
|
|
}
|
|
break;
|
|
- case 206: /* expr ::= expr in_op nm dbnm paren_exprlist */
|
|
+ case 211: /* expr ::= expr in_op nm dbnm paren_exprlist */
|
|
{
|
|
SrcList *pSrc = sqlite3SrcListAppend(pParse, 0,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy0);
|
|
Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0);
|
|
- if( yymsp[0].minor.yy94 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy94);
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy102, 0);
|
|
- sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy102, pSelect);
|
|
- if( yymsp[-3].minor.yy100 ) yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy102, 0);
|
|
+ if( yymsp[0].minor.yy242 ) sqlite3SrcListFuncArgs(pParse, pSelect ? pSrc : 0, yymsp[0].minor.yy242);
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy202, 0);
|
|
+ sqlite3PExprAddSelect(pParse, yymsp[-4].minor.yy202, pSelect);
|
|
+ if( yymsp[-3].minor.yy192 ) yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_NOT, yymsp[-4].minor.yy202, 0);
|
|
}
|
|
break;
|
|
- case 207: /* expr ::= EXISTS LP select RP */
|
|
+ case 212: /* expr ::= EXISTS LP select RP */
|
|
{
|
|
Expr *p;
|
|
- p = yymsp[-3].minor.yy102 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
|
|
- sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy391);
|
|
+ p = yymsp[-3].minor.yy202 = sqlite3PExpr(pParse, TK_EXISTS, 0, 0);
|
|
+ sqlite3PExprAddSelect(pParse, p, yymsp[-1].minor.yy539);
|
|
}
|
|
break;
|
|
- case 208: /* expr ::= CASE case_operand case_exprlist case_else END */
|
|
+ case 213: /* expr ::= CASE case_operand case_exprlist case_else END */
|
|
{
|
|
- yymsp[-4].minor.yy102 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy102, 0);
|
|
- if( yymsp[-4].minor.yy102 ){
|
|
- yymsp[-4].minor.yy102->x.pList = yymsp[-1].minor.yy102 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy94,yymsp[-1].minor.yy102) : yymsp[-2].minor.yy94;
|
|
- sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy102);
|
|
+ yymsp[-4].minor.yy202 = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy202, 0);
|
|
+ if( yymsp[-4].minor.yy202 ){
|
|
+ yymsp[-4].minor.yy202->x.pList = yymsp[-1].minor.yy202 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[-1].minor.yy202) : yymsp[-2].minor.yy242;
|
|
+ sqlite3ExprSetHeightAndFlags(pParse, yymsp[-4].minor.yy202);
|
|
}else{
|
|
- sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy94);
|
|
- sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy102);
|
|
+ sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy242);
|
|
+ sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy202);
|
|
}
|
|
}
|
|
break;
|
|
- case 209: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
|
|
+ case 214: /* case_exprlist ::= case_exprlist WHEN expr THEN expr */
|
|
{
|
|
- yymsp[-4].minor.yy94 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy94, yymsp[-2].minor.yy102);
|
|
- yymsp[-4].minor.yy94 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy94, yymsp[0].minor.yy102);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[-2].minor.yy202);
|
|
+ yymsp[-4].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy242, yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 210: /* case_exprlist ::= WHEN expr THEN expr */
|
|
+ case 215: /* case_exprlist ::= WHEN expr THEN expr */
|
|
{
|
|
- yymsp[-3].minor.yy94 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy102);
|
|
- yymsp[-3].minor.yy94 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy94, yymsp[0].minor.yy102);
|
|
+ yymsp[-3].minor.yy242 = sqlite3ExprListAppend(pParse,0, yymsp[-2].minor.yy202);
|
|
+ yymsp[-3].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-3].minor.yy242, yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 213: /* case_operand ::= expr */
|
|
-{yymsp[0].minor.yy102 = yymsp[0].minor.yy102; /*A-overwrites-X*/}
|
|
+ case 218: /* case_operand ::= expr */
|
|
+{yymsp[0].minor.yy202 = yymsp[0].minor.yy202; /*A-overwrites-X*/}
|
|
break;
|
|
- case 216: /* nexprlist ::= nexprlist COMMA expr */
|
|
-{yymsp[-2].minor.yy94 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy94,yymsp[0].minor.yy102);}
|
|
+ case 221: /* nexprlist ::= nexprlist COMMA expr */
|
|
+{yymsp[-2].minor.yy242 = sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy242,yymsp[0].minor.yy202);}
|
|
break;
|
|
- case 217: /* nexprlist ::= expr */
|
|
-{yymsp[0].minor.yy94 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy102); /*A-overwrites-Y*/}
|
|
+ case 222: /* nexprlist ::= expr */
|
|
+{yymsp[0].minor.yy242 = sqlite3ExprListAppend(pParse,0,yymsp[0].minor.yy202); /*A-overwrites-Y*/}
|
|
break;
|
|
- case 219: /* paren_exprlist ::= LP exprlist RP */
|
|
- case 224: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==224);
|
|
-{yymsp[-2].minor.yy94 = yymsp[-1].minor.yy94;}
|
|
+ case 224: /* paren_exprlist ::= LP exprlist RP */
|
|
+ case 229: /* eidlist_opt ::= LP eidlist RP */ yytestcase(yyruleno==229);
|
|
+{yymsp[-2].minor.yy242 = yymsp[-1].minor.yy242;}
|
|
break;
|
|
- case 220: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
|
|
+ case 225: /* cmd ::= createkw uniqueflag INDEX ifnotexists nm dbnm ON nm LP sortlist RP where_opt */
|
|
{
|
|
sqlite3CreateIndex(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0,
|
|
- sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy94, yymsp[-10].minor.yy100,
|
|
- &yymsp[-11].minor.yy0, yymsp[0].minor.yy102, SQLITE_SO_ASC, yymsp[-8].minor.yy100, SQLITE_IDXTYPE_APPDEF);
|
|
+ sqlite3SrcListAppend(pParse,0,&yymsp[-4].minor.yy0,0), yymsp[-2].minor.yy242, yymsp[-10].minor.yy192,
|
|
+ &yymsp[-11].minor.yy0, yymsp[0].minor.yy202, SQLITE_SO_ASC, yymsp[-8].minor.yy192, SQLITE_IDXTYPE_APPDEF);
|
|
if( IN_RENAME_OBJECT && pParse->pNewIndex ){
|
|
sqlite3RenameTokenMap(pParse, pParse->pNewIndex->zName, &yymsp[-4].minor.yy0);
|
|
}
|
|
}
|
|
break;
|
|
- case 221: /* uniqueflag ::= UNIQUE */
|
|
- case 263: /* raisetype ::= ABORT */ yytestcase(yyruleno==263);
|
|
-{yymsp[0].minor.yy100 = OE_Abort;}
|
|
+ case 226: /* uniqueflag ::= UNIQUE */
|
|
+ case 268: /* raisetype ::= ABORT */ yytestcase(yyruleno==268);
|
|
+{yymsp[0].minor.yy192 = OE_Abort;}
|
|
break;
|
|
- case 222: /* uniqueflag ::= */
|
|
-{yymsp[1].minor.yy100 = OE_None;}
|
|
+ case 227: /* uniqueflag ::= */
|
|
+{yymsp[1].minor.yy192 = OE_None;}
|
|
break;
|
|
- case 225: /* eidlist ::= eidlist COMMA nm collate sortorder */
|
|
+ case 230: /* eidlist ::= eidlist COMMA nm collate sortorder */
|
|
{
|
|
- yymsp[-4].minor.yy94 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy94, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy100, yymsp[0].minor.yy100);
|
|
+ yymsp[-4].minor.yy242 = parserAddExprIdListTerm(pParse, yymsp[-4].minor.yy242, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy192, yymsp[0].minor.yy192);
|
|
}
|
|
break;
|
|
- case 226: /* eidlist ::= nm collate sortorder */
|
|
+ case 231: /* eidlist ::= nm collate sortorder */
|
|
{
|
|
- yymsp[-2].minor.yy94 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy100, yymsp[0].minor.yy100); /*A-overwrites-Y*/
|
|
+ yymsp[-2].minor.yy242 = parserAddExprIdListTerm(pParse, 0, &yymsp[-2].minor.yy0, yymsp[-1].minor.yy192, yymsp[0].minor.yy192); /*A-overwrites-Y*/
|
|
}
|
|
break;
|
|
- case 229: /* cmd ::= DROP INDEX ifexists fullname */
|
|
-{sqlite3DropIndex(pParse, yymsp[0].minor.yy407, yymsp[-1].minor.yy100);}
|
|
+ case 234: /* cmd ::= DROP INDEX ifexists fullname */
|
|
+{sqlite3DropIndex(pParse, yymsp[0].minor.yy47, yymsp[-1].minor.yy192);}
|
|
break;
|
|
- case 230: /* cmd ::= VACUUM vinto */
|
|
-{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy102);}
|
|
+ case 235: /* cmd ::= VACUUM vinto */
|
|
+{sqlite3Vacuum(pParse,0,yymsp[0].minor.yy202);}
|
|
break;
|
|
- case 231: /* cmd ::= VACUUM nm vinto */
|
|
-{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy102);}
|
|
+ case 236: /* cmd ::= VACUUM nm vinto */
|
|
+{sqlite3Vacuum(pParse,&yymsp[-1].minor.yy0,yymsp[0].minor.yy202);}
|
|
break;
|
|
- case 234: /* cmd ::= PRAGMA nm dbnm */
|
|
+ case 239: /* cmd ::= PRAGMA nm dbnm */
|
|
{sqlite3Pragma(pParse,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0,0,0);}
|
|
break;
|
|
- case 235: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
|
|
+ case 240: /* cmd ::= PRAGMA nm dbnm EQ nmnum */
|
|
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,0);}
|
|
break;
|
|
- case 236: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
|
|
+ case 241: /* cmd ::= PRAGMA nm dbnm LP nmnum RP */
|
|
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,0);}
|
|
break;
|
|
- case 237: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
|
|
+ case 242: /* cmd ::= PRAGMA nm dbnm EQ minus_num */
|
|
{sqlite3Pragma(pParse,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy0,1);}
|
|
break;
|
|
- case 238: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
|
|
+ case 243: /* cmd ::= PRAGMA nm dbnm LP minus_num RP */
|
|
{sqlite3Pragma(pParse,&yymsp[-4].minor.yy0,&yymsp[-3].minor.yy0,&yymsp[-1].minor.yy0,1);}
|
|
break;
|
|
- case 241: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
|
|
+ case 246: /* cmd ::= createkw trigger_decl BEGIN trigger_cmd_list END */
|
|
{
|
|
Token all;
|
|
all.z = yymsp[-3].minor.yy0.z;
|
|
all.n = (int)(yymsp[0].minor.yy0.z - yymsp[-3].minor.yy0.z) + yymsp[0].minor.yy0.n;
|
|
- sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy11, &all);
|
|
+ sqlite3FinishTrigger(pParse, yymsp[-1].minor.yy447, &all);
|
|
}
|
|
break;
|
|
- case 242: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
|
|
+ case 247: /* trigger_decl ::= temp TRIGGER ifnotexists nm dbnm trigger_time trigger_event ON fullname foreach_clause when_clause */
|
|
{
|
|
- sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy100, yymsp[-4].minor.yy298.a, yymsp[-4].minor.yy298.b, yymsp[-2].minor.yy407, yymsp[0].minor.yy102, yymsp[-10].minor.yy100, yymsp[-8].minor.yy100);
|
|
+ sqlite3BeginTrigger(pParse, &yymsp[-7].minor.yy0, &yymsp[-6].minor.yy0, yymsp[-5].minor.yy192, yymsp[-4].minor.yy230.a, yymsp[-4].minor.yy230.b, yymsp[-2].minor.yy47, yymsp[0].minor.yy202, yymsp[-10].minor.yy192, yymsp[-8].minor.yy192);
|
|
yymsp[-10].minor.yy0 = (yymsp[-6].minor.yy0.n==0?yymsp[-7].minor.yy0:yymsp[-6].minor.yy0); /*A-overwrites-T*/
|
|
}
|
|
break;
|
|
- case 243: /* trigger_time ::= BEFORE|AFTER */
|
|
-{ yymsp[0].minor.yy100 = yymsp[0].major; /*A-overwrites-X*/ }
|
|
+ case 248: /* trigger_time ::= BEFORE|AFTER */
|
|
+{ yymsp[0].minor.yy192 = yymsp[0].major; /*A-overwrites-X*/ }
|
|
break;
|
|
- case 244: /* trigger_time ::= INSTEAD OF */
|
|
-{ yymsp[-1].minor.yy100 = TK_INSTEAD;}
|
|
+ case 249: /* trigger_time ::= INSTEAD OF */
|
|
+{ yymsp[-1].minor.yy192 = TK_INSTEAD;}
|
|
break;
|
|
- case 245: /* trigger_time ::= */
|
|
-{ yymsp[1].minor.yy100 = TK_BEFORE; }
|
|
+ case 250: /* trigger_time ::= */
|
|
+{ yymsp[1].minor.yy192 = TK_BEFORE; }
|
|
break;
|
|
- case 246: /* trigger_event ::= DELETE|INSERT */
|
|
- case 247: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==247);
|
|
-{yymsp[0].minor.yy298.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy298.b = 0;}
|
|
+ case 251: /* trigger_event ::= DELETE|INSERT */
|
|
+ case 252: /* trigger_event ::= UPDATE */ yytestcase(yyruleno==252);
|
|
+{yymsp[0].minor.yy230.a = yymsp[0].major; /*A-overwrites-X*/ yymsp[0].minor.yy230.b = 0;}
|
|
break;
|
|
- case 248: /* trigger_event ::= UPDATE OF idlist */
|
|
-{yymsp[-2].minor.yy298.a = TK_UPDATE; yymsp[-2].minor.yy298.b = yymsp[0].minor.yy76;}
|
|
+ case 253: /* trigger_event ::= UPDATE OF idlist */
|
|
+{yymsp[-2].minor.yy230.a = TK_UPDATE; yymsp[-2].minor.yy230.b = yymsp[0].minor.yy600;}
|
|
break;
|
|
- case 249: /* when_clause ::= */
|
|
- case 268: /* key_opt ::= */ yytestcase(yyruleno==268);
|
|
- case 316: /* filter_opt ::= */ yytestcase(yyruleno==316);
|
|
-{ yymsp[1].minor.yy102 = 0; }
|
|
+ case 254: /* when_clause ::= */
|
|
+ case 273: /* key_opt ::= */ yytestcase(yyruleno==273);
|
|
+{ yymsp[1].minor.yy202 = 0; }
|
|
break;
|
|
- case 250: /* when_clause ::= WHEN expr */
|
|
- case 269: /* key_opt ::= KEY expr */ yytestcase(yyruleno==269);
|
|
-{ yymsp[-1].minor.yy102 = yymsp[0].minor.yy102; }
|
|
+ case 255: /* when_clause ::= WHEN expr */
|
|
+ case 274: /* key_opt ::= KEY expr */ yytestcase(yyruleno==274);
|
|
+{ yymsp[-1].minor.yy202 = yymsp[0].minor.yy202; }
|
|
break;
|
|
- case 251: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
|
|
+ case 256: /* trigger_cmd_list ::= trigger_cmd_list trigger_cmd SEMI */
|
|
{
|
|
- assert( yymsp[-2].minor.yy11!=0 );
|
|
- yymsp[-2].minor.yy11->pLast->pNext = yymsp[-1].minor.yy11;
|
|
- yymsp[-2].minor.yy11->pLast = yymsp[-1].minor.yy11;
|
|
+ assert( yymsp[-2].minor.yy447!=0 );
|
|
+ yymsp[-2].minor.yy447->pLast->pNext = yymsp[-1].minor.yy447;
|
|
+ yymsp[-2].minor.yy447->pLast = yymsp[-1].minor.yy447;
|
|
}
|
|
break;
|
|
- case 252: /* trigger_cmd_list ::= trigger_cmd SEMI */
|
|
+ case 257: /* trigger_cmd_list ::= trigger_cmd SEMI */
|
|
{
|
|
- assert( yymsp[-1].minor.yy11!=0 );
|
|
- yymsp[-1].minor.yy11->pLast = yymsp[-1].minor.yy11;
|
|
+ assert( yymsp[-1].minor.yy447!=0 );
|
|
+ yymsp[-1].minor.yy447->pLast = yymsp[-1].minor.yy447;
|
|
}
|
|
break;
|
|
- case 253: /* trnm ::= nm DOT nm */
|
|
+ case 258: /* trnm ::= nm DOT nm */
|
|
{
|
|
yymsp[-2].minor.yy0 = yymsp[0].minor.yy0;
|
|
sqlite3ErrorMsg(pParse,
|
|
@@ -152981,328 +157789,344 @@
|
|
"statements within triggers");
|
|
}
|
|
break;
|
|
- case 254: /* tridxby ::= INDEXED BY nm */
|
|
+ case 259: /* tridxby ::= INDEXED BY nm */
|
|
{
|
|
sqlite3ErrorMsg(pParse,
|
|
"the INDEXED BY clause is not allowed on UPDATE or DELETE statements "
|
|
"within triggers");
|
|
}
|
|
break;
|
|
- case 255: /* tridxby ::= NOT INDEXED */
|
|
+ case 260: /* tridxby ::= NOT INDEXED */
|
|
{
|
|
sqlite3ErrorMsg(pParse,
|
|
"the NOT INDEXED clause is not allowed on UPDATE or DELETE statements "
|
|
"within triggers");
|
|
}
|
|
break;
|
|
- case 256: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
|
|
-{yylhsminor.yy11 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy94, yymsp[-1].minor.yy102, yymsp[-6].minor.yy100, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy528);}
|
|
- yymsp[-7].minor.yy11 = yylhsminor.yy11;
|
|
+ case 261: /* trigger_cmd ::= UPDATE orconf trnm tridxby SET setlist where_opt scanpt */
|
|
+{yylhsminor.yy447 = sqlite3TriggerUpdateStep(pParse, &yymsp[-5].minor.yy0, yymsp[-2].minor.yy242, yymsp[-1].minor.yy202, yymsp[-6].minor.yy192, yymsp[-7].minor.yy0.z, yymsp[0].minor.yy436);}
|
|
+ yymsp[-7].minor.yy447 = yylhsminor.yy447;
|
|
break;
|
|
- case 257: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
|
|
+ case 262: /* trigger_cmd ::= scanpt insert_cmd INTO trnm idlist_opt select upsert scanpt */
|
|
{
|
|
- yylhsminor.yy11 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy76,yymsp[-2].minor.yy391,yymsp[-6].minor.yy100,yymsp[-1].minor.yy95,yymsp[-7].minor.yy528,yymsp[0].minor.yy528);/*yylhsminor.yy11-overwrites-yymsp[-6].minor.yy100*/
|
|
+ yylhsminor.yy447 = sqlite3TriggerInsertStep(pParse,&yymsp[-4].minor.yy0,yymsp[-3].minor.yy600,yymsp[-2].minor.yy539,yymsp[-6].minor.yy192,yymsp[-1].minor.yy318,yymsp[-7].minor.yy436,yymsp[0].minor.yy436);/*yylhsminor.yy447-overwrites-yymsp[-6].minor.yy192*/
|
|
}
|
|
- yymsp[-7].minor.yy11 = yylhsminor.yy11;
|
|
+ yymsp[-7].minor.yy447 = yylhsminor.yy447;
|
|
break;
|
|
- case 258: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
|
|
-{yylhsminor.yy11 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy102, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy528);}
|
|
- yymsp[-5].minor.yy11 = yylhsminor.yy11;
|
|
+ case 263: /* trigger_cmd ::= DELETE FROM trnm tridxby where_opt scanpt */
|
|
+{yylhsminor.yy447 = sqlite3TriggerDeleteStep(pParse, &yymsp[-3].minor.yy0, yymsp[-1].minor.yy202, yymsp[-5].minor.yy0.z, yymsp[0].minor.yy436);}
|
|
+ yymsp[-5].minor.yy447 = yylhsminor.yy447;
|
|
break;
|
|
- case 259: /* trigger_cmd ::= scanpt select scanpt */
|
|
-{yylhsminor.yy11 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy391, yymsp[-2].minor.yy528, yymsp[0].minor.yy528); /*yylhsminor.yy11-overwrites-yymsp[-1].minor.yy391*/}
|
|
- yymsp[-2].minor.yy11 = yylhsminor.yy11;
|
|
+ case 264: /* trigger_cmd ::= scanpt select scanpt */
|
|
+{yylhsminor.yy447 = sqlite3TriggerSelectStep(pParse->db, yymsp[-1].minor.yy539, yymsp[-2].minor.yy436, yymsp[0].minor.yy436); /*yylhsminor.yy447-overwrites-yymsp[-1].minor.yy539*/}
|
|
+ yymsp[-2].minor.yy447 = yylhsminor.yy447;
|
|
break;
|
|
- case 260: /* expr ::= RAISE LP IGNORE RP */
|
|
+ case 265: /* expr ::= RAISE LP IGNORE RP */
|
|
{
|
|
- yymsp[-3].minor.yy102 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
|
|
- if( yymsp[-3].minor.yy102 ){
|
|
- yymsp[-3].minor.yy102->affinity = OE_Ignore;
|
|
+ yymsp[-3].minor.yy202 = sqlite3PExpr(pParse, TK_RAISE, 0, 0);
|
|
+ if( yymsp[-3].minor.yy202 ){
|
|
+ yymsp[-3].minor.yy202->affExpr = OE_Ignore;
|
|
}
|
|
}
|
|
break;
|
|
- case 261: /* expr ::= RAISE LP raisetype COMMA nm RP */
|
|
+ case 266: /* expr ::= RAISE LP raisetype COMMA nm RP */
|
|
{
|
|
- yymsp[-5].minor.yy102 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
|
|
- if( yymsp[-5].minor.yy102 ) {
|
|
- yymsp[-5].minor.yy102->affinity = (char)yymsp[-3].minor.yy100;
|
|
+ yymsp[-5].minor.yy202 = sqlite3ExprAlloc(pParse->db, TK_RAISE, &yymsp[-1].minor.yy0, 1);
|
|
+ if( yymsp[-5].minor.yy202 ) {
|
|
+ yymsp[-5].minor.yy202->affExpr = (char)yymsp[-3].minor.yy192;
|
|
}
|
|
}
|
|
break;
|
|
- case 262: /* raisetype ::= ROLLBACK */
|
|
-{yymsp[0].minor.yy100 = OE_Rollback;}
|
|
+ case 267: /* raisetype ::= ROLLBACK */
|
|
+{yymsp[0].minor.yy192 = OE_Rollback;}
|
|
break;
|
|
- case 264: /* raisetype ::= FAIL */
|
|
-{yymsp[0].minor.yy100 = OE_Fail;}
|
|
+ case 269: /* raisetype ::= FAIL */
|
|
+{yymsp[0].minor.yy192 = OE_Fail;}
|
|
break;
|
|
- case 265: /* cmd ::= DROP TRIGGER ifexists fullname */
|
|
+ case 270: /* cmd ::= DROP TRIGGER ifexists fullname */
|
|
{
|
|
- sqlite3DropTrigger(pParse,yymsp[0].minor.yy407,yymsp[-1].minor.yy100);
|
|
+ sqlite3DropTrigger(pParse,yymsp[0].minor.yy47,yymsp[-1].minor.yy192);
|
|
}
|
|
break;
|
|
- case 266: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
|
|
+ case 271: /* cmd ::= ATTACH database_kw_opt expr AS expr key_opt */
|
|
{
|
|
- sqlite3Attach(pParse, yymsp[-3].minor.yy102, yymsp[-1].minor.yy102, yymsp[0].minor.yy102);
|
|
+ sqlite3Attach(pParse, yymsp[-3].minor.yy202, yymsp[-1].minor.yy202, yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 267: /* cmd ::= DETACH database_kw_opt expr */
|
|
+ case 272: /* cmd ::= DETACH database_kw_opt expr */
|
|
{
|
|
- sqlite3Detach(pParse, yymsp[0].minor.yy102);
|
|
+ sqlite3Detach(pParse, yymsp[0].minor.yy202);
|
|
}
|
|
break;
|
|
- case 270: /* cmd ::= REINDEX */
|
|
+ case 275: /* cmd ::= REINDEX */
|
|
{sqlite3Reindex(pParse, 0, 0);}
|
|
break;
|
|
- case 271: /* cmd ::= REINDEX nm dbnm */
|
|
+ case 276: /* cmd ::= REINDEX nm dbnm */
|
|
{sqlite3Reindex(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
|
|
break;
|
|
- case 272: /* cmd ::= ANALYZE */
|
|
+ case 277: /* cmd ::= ANALYZE */
|
|
{sqlite3Analyze(pParse, 0, 0);}
|
|
break;
|
|
- case 273: /* cmd ::= ANALYZE nm dbnm */
|
|
+ case 278: /* cmd ::= ANALYZE nm dbnm */
|
|
{sqlite3Analyze(pParse, &yymsp[-1].minor.yy0, &yymsp[0].minor.yy0);}
|
|
break;
|
|
- case 274: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
|
|
+ case 279: /* cmd ::= ALTER TABLE fullname RENAME TO nm */
|
|
{
|
|
- sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy407,&yymsp[0].minor.yy0);
|
|
+ sqlite3AlterRenameTable(pParse,yymsp[-3].minor.yy47,&yymsp[0].minor.yy0);
|
|
}
|
|
break;
|
|
- case 275: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
|
|
+ case 280: /* cmd ::= ALTER TABLE add_column_fullname ADD kwcolumn_opt columnname carglist */
|
|
{
|
|
yymsp[-1].minor.yy0.n = (int)(pParse->sLastToken.z-yymsp[-1].minor.yy0.z) + pParse->sLastToken.n;
|
|
sqlite3AlterFinishAddColumn(pParse, &yymsp[-1].minor.yy0);
|
|
}
|
|
break;
|
|
- case 276: /* add_column_fullname ::= fullname */
|
|
+ case 281: /* add_column_fullname ::= fullname */
|
|
{
|
|
disableLookaside(pParse);
|
|
- sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy407);
|
|
+ sqlite3AlterBeginAddColumn(pParse, yymsp[0].minor.yy47);
|
|
}
|
|
break;
|
|
- case 277: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
|
|
+ case 282: /* cmd ::= ALTER TABLE fullname RENAME kwcolumn_opt nm TO nm */
|
|
{
|
|
- sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy407, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
|
|
+ sqlite3AlterRenameColumn(pParse, yymsp[-5].minor.yy47, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0);
|
|
}
|
|
break;
|
|
- case 278: /* cmd ::= create_vtab */
|
|
+ case 283: /* cmd ::= create_vtab */
|
|
{sqlite3VtabFinishParse(pParse,0);}
|
|
break;
|
|
- case 279: /* cmd ::= create_vtab LP vtabarglist RP */
|
|
+ case 284: /* cmd ::= create_vtab LP vtabarglist RP */
|
|
{sqlite3VtabFinishParse(pParse,&yymsp[0].minor.yy0);}
|
|
break;
|
|
- case 280: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
|
|
+ case 285: /* create_vtab ::= createkw VIRTUAL TABLE ifnotexists nm dbnm USING nm */
|
|
{
|
|
- sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy100);
|
|
+ sqlite3VtabBeginParse(pParse, &yymsp[-3].minor.yy0, &yymsp[-2].minor.yy0, &yymsp[0].minor.yy0, yymsp[-4].minor.yy192);
|
|
}
|
|
break;
|
|
- case 281: /* vtabarg ::= */
|
|
+ case 286: /* vtabarg ::= */
|
|
{sqlite3VtabArgInit(pParse);}
|
|
break;
|
|
- case 282: /* vtabargtoken ::= ANY */
|
|
- case 283: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==283);
|
|
- case 284: /* lp ::= LP */ yytestcase(yyruleno==284);
|
|
+ case 287: /* vtabargtoken ::= ANY */
|
|
+ case 288: /* vtabargtoken ::= lp anylist RP */ yytestcase(yyruleno==288);
|
|
+ case 289: /* lp ::= LP */ yytestcase(yyruleno==289);
|
|
{sqlite3VtabArgExtend(pParse,&yymsp[0].minor.yy0);}
|
|
break;
|
|
- case 285: /* with ::= WITH wqlist */
|
|
- case 286: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==286);
|
|
-{ sqlite3WithPush(pParse, yymsp[0].minor.yy243, 1); }
|
|
+ case 290: /* with ::= WITH wqlist */
|
|
+ case 291: /* with ::= WITH RECURSIVE wqlist */ yytestcase(yyruleno==291);
|
|
+{ sqlite3WithPush(pParse, yymsp[0].minor.yy131, 1); }
|
|
break;
|
|
- case 287: /* wqlist ::= nm eidlist_opt AS LP select RP */
|
|
+ case 292: /* wqlist ::= nm eidlist_opt AS LP select RP */
|
|
{
|
|
- yymsp[-5].minor.yy243 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy94, yymsp[-1].minor.yy391); /*A-overwrites-X*/
|
|
+ yymsp[-5].minor.yy131 = sqlite3WithAdd(pParse, 0, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy242, yymsp[-1].minor.yy539); /*A-overwrites-X*/
|
|
}
|
|
break;
|
|
- case 288: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
|
|
+ case 293: /* wqlist ::= wqlist COMMA nm eidlist_opt AS LP select RP */
|
|
{
|
|
- yymsp[-7].minor.yy243 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy243, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy94, yymsp[-1].minor.yy391);
|
|
+ yymsp[-7].minor.yy131 = sqlite3WithAdd(pParse, yymsp[-7].minor.yy131, &yymsp[-5].minor.yy0, yymsp[-4].minor.yy242, yymsp[-1].minor.yy539);
|
|
}
|
|
break;
|
|
- case 289: /* windowdefn_list ::= windowdefn */
|
|
-{ yylhsminor.yy379 = yymsp[0].minor.yy379; }
|
|
- yymsp[0].minor.yy379 = yylhsminor.yy379;
|
|
+ case 294: /* windowdefn_list ::= windowdefn */
|
|
+{ yylhsminor.yy303 = yymsp[0].minor.yy303; }
|
|
+ yymsp[0].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 290: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
|
|
+ case 295: /* windowdefn_list ::= windowdefn_list COMMA windowdefn */
|
|
{
|
|
- assert( yymsp[0].minor.yy379!=0 );
|
|
- sqlite3WindowChain(pParse, yymsp[0].minor.yy379, yymsp[-2].minor.yy379);
|
|
- yymsp[0].minor.yy379->pNextWin = yymsp[-2].minor.yy379;
|
|
- yylhsminor.yy379 = yymsp[0].minor.yy379;
|
|
+ assert( yymsp[0].minor.yy303!=0 );
|
|
+ sqlite3WindowChain(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy303);
|
|
+ yymsp[0].minor.yy303->pNextWin = yymsp[-2].minor.yy303;
|
|
+ yylhsminor.yy303 = yymsp[0].minor.yy303;
|
|
}
|
|
- yymsp[-2].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-2].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 291: /* windowdefn ::= nm AS LP window RP */
|
|
+ case 296: /* windowdefn ::= nm AS LP window RP */
|
|
{
|
|
- if( ALWAYS(yymsp[-1].minor.yy379) ){
|
|
- yymsp[-1].minor.yy379->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
|
|
+ if( ALWAYS(yymsp[-1].minor.yy303) ){
|
|
+ yymsp[-1].minor.yy303->zName = sqlite3DbStrNDup(pParse->db, yymsp[-4].minor.yy0.z, yymsp[-4].minor.yy0.n);
|
|
}
|
|
- yylhsminor.yy379 = yymsp[-1].minor.yy379;
|
|
+ yylhsminor.yy303 = yymsp[-1].minor.yy303;
|
|
}
|
|
- yymsp[-4].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-4].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 292: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
|
|
+ case 297: /* window ::= PARTITION BY nexprlist orderby_opt frame_opt */
|
|
{
|
|
- yymsp[-4].minor.yy379 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy379, yymsp[-2].minor.yy94, yymsp[-1].minor.yy94, 0);
|
|
+ yymsp[-4].minor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy242, yymsp[-1].minor.yy242, 0);
|
|
}
|
|
break;
|
|
- case 293: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
|
|
+ case 298: /* window ::= nm PARTITION BY nexprlist orderby_opt frame_opt */
|
|
{
|
|
- yylhsminor.yy379 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy379, yymsp[-2].minor.yy94, yymsp[-1].minor.yy94, &yymsp[-5].minor.yy0);
|
|
+ yylhsminor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, yymsp[-2].minor.yy242, yymsp[-1].minor.yy242, &yymsp[-5].minor.yy0);
|
|
}
|
|
- yymsp[-5].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-5].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 294: /* window ::= ORDER BY sortlist frame_opt */
|
|
+ case 299: /* window ::= ORDER BY sortlist frame_opt */
|
|
{
|
|
- yymsp[-3].minor.yy379 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy379, 0, yymsp[-1].minor.yy94, 0);
|
|
+ yymsp[-3].minor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, yymsp[-1].minor.yy242, 0);
|
|
}
|
|
break;
|
|
- case 295: /* window ::= nm ORDER BY sortlist frame_opt */
|
|
+ case 300: /* window ::= nm ORDER BY sortlist frame_opt */
|
|
{
|
|
- yylhsminor.yy379 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy379, 0, yymsp[-1].minor.yy94, &yymsp[-4].minor.yy0);
|
|
+ yylhsminor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, yymsp[-1].minor.yy242, &yymsp[-4].minor.yy0);
|
|
}
|
|
- yymsp[-4].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-4].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 296: /* window ::= frame_opt */
|
|
+ case 301: /* window ::= frame_opt */
|
|
+ case 320: /* filter_over ::= over_clause */ yytestcase(yyruleno==320);
|
|
{
|
|
- yylhsminor.yy379 = yymsp[0].minor.yy379;
|
|
+ yylhsminor.yy303 = yymsp[0].minor.yy303;
|
|
}
|
|
- yymsp[0].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[0].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 297: /* window ::= nm frame_opt */
|
|
+ case 302: /* window ::= nm frame_opt */
|
|
{
|
|
- yylhsminor.yy379 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy379, 0, 0, &yymsp[-1].minor.yy0);
|
|
+ yylhsminor.yy303 = sqlite3WindowAssemble(pParse, yymsp[0].minor.yy303, 0, 0, &yymsp[-1].minor.yy0);
|
|
}
|
|
- yymsp[-1].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-1].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 298: /* frame_opt ::= */
|
|
+ case 303: /* frame_opt ::= */
|
|
{
|
|
- yymsp[1].minor.yy379 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
|
|
+ yymsp[1].minor.yy303 = sqlite3WindowAlloc(pParse, 0, TK_UNBOUNDED, 0, TK_CURRENT, 0, 0);
|
|
}
|
|
break;
|
|
- case 299: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
|
|
+ case 304: /* frame_opt ::= range_or_rows frame_bound_s frame_exclude_opt */
|
|
{
|
|
- yylhsminor.yy379 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy100, yymsp[-1].minor.yy389.eType, yymsp[-1].minor.yy389.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy218);
|
|
+ yylhsminor.yy303 = sqlite3WindowAlloc(pParse, yymsp[-2].minor.yy192, yymsp[-1].minor.yy77.eType, yymsp[-1].minor.yy77.pExpr, TK_CURRENT, 0, yymsp[0].minor.yy58);
|
|
}
|
|
- yymsp[-2].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-2].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 300: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
|
|
+ case 305: /* frame_opt ::= range_or_rows BETWEEN frame_bound_s AND frame_bound_e frame_exclude_opt */
|
|
{
|
|
- yylhsminor.yy379 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy100, yymsp[-3].minor.yy389.eType, yymsp[-3].minor.yy389.pExpr, yymsp[-1].minor.yy389.eType, yymsp[-1].minor.yy389.pExpr, yymsp[0].minor.yy218);
|
|
+ yylhsminor.yy303 = sqlite3WindowAlloc(pParse, yymsp[-5].minor.yy192, yymsp[-3].minor.yy77.eType, yymsp[-3].minor.yy77.pExpr, yymsp[-1].minor.yy77.eType, yymsp[-1].minor.yy77.pExpr, yymsp[0].minor.yy58);
|
|
}
|
|
- yymsp[-5].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-5].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 302: /* frame_bound_s ::= frame_bound */
|
|
- case 304: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==304);
|
|
-{yylhsminor.yy389 = yymsp[0].minor.yy389;}
|
|
- yymsp[0].minor.yy389 = yylhsminor.yy389;
|
|
+ case 307: /* frame_bound_s ::= frame_bound */
|
|
+ case 309: /* frame_bound_e ::= frame_bound */ yytestcase(yyruleno==309);
|
|
+{yylhsminor.yy77 = yymsp[0].minor.yy77;}
|
|
+ yymsp[0].minor.yy77 = yylhsminor.yy77;
|
|
break;
|
|
- case 303: /* frame_bound_s ::= UNBOUNDED PRECEDING */
|
|
- case 305: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==305);
|
|
- case 307: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==307);
|
|
-{yylhsminor.yy389.eType = yymsp[-1].major; yylhsminor.yy389.pExpr = 0;}
|
|
- yymsp[-1].minor.yy389 = yylhsminor.yy389;
|
|
+ case 308: /* frame_bound_s ::= UNBOUNDED PRECEDING */
|
|
+ case 310: /* frame_bound_e ::= UNBOUNDED FOLLOWING */ yytestcase(yyruleno==310);
|
|
+ case 312: /* frame_bound ::= CURRENT ROW */ yytestcase(yyruleno==312);
|
|
+{yylhsminor.yy77.eType = yymsp[-1].major; yylhsminor.yy77.pExpr = 0;}
|
|
+ yymsp[-1].minor.yy77 = yylhsminor.yy77;
|
|
break;
|
|
- case 306: /* frame_bound ::= expr PRECEDING|FOLLOWING */
|
|
-{yylhsminor.yy389.eType = yymsp[0].major; yylhsminor.yy389.pExpr = yymsp[-1].minor.yy102;}
|
|
- yymsp[-1].minor.yy389 = yylhsminor.yy389;
|
|
+ case 311: /* frame_bound ::= expr PRECEDING|FOLLOWING */
|
|
+{yylhsminor.yy77.eType = yymsp[0].major; yylhsminor.yy77.pExpr = yymsp[-1].minor.yy202;}
|
|
+ yymsp[-1].minor.yy77 = yylhsminor.yy77;
|
|
break;
|
|
- case 308: /* frame_exclude_opt ::= */
|
|
-{yymsp[1].minor.yy218 = 0;}
|
|
+ case 313: /* frame_exclude_opt ::= */
|
|
+{yymsp[1].minor.yy58 = 0;}
|
|
break;
|
|
- case 309: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
|
|
-{yymsp[-1].minor.yy218 = yymsp[0].minor.yy218;}
|
|
+ case 314: /* frame_exclude_opt ::= EXCLUDE frame_exclude */
|
|
+{yymsp[-1].minor.yy58 = yymsp[0].minor.yy58;}
|
|
break;
|
|
- case 310: /* frame_exclude ::= NO OTHERS */
|
|
- case 311: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==311);
|
|
-{yymsp[-1].minor.yy218 = yymsp[-1].major; /*A-overwrites-X*/}
|
|
+ case 315: /* frame_exclude ::= NO OTHERS */
|
|
+ case 316: /* frame_exclude ::= CURRENT ROW */ yytestcase(yyruleno==316);
|
|
+{yymsp[-1].minor.yy58 = yymsp[-1].major; /*A-overwrites-X*/}
|
|
break;
|
|
- case 312: /* frame_exclude ::= GROUP|TIES */
|
|
-{yymsp[0].minor.yy218 = yymsp[0].major; /*A-overwrites-X*/}
|
|
+ case 317: /* frame_exclude ::= GROUP|TIES */
|
|
+{yymsp[0].minor.yy58 = yymsp[0].major; /*A-overwrites-X*/}
|
|
break;
|
|
- case 313: /* window_clause ::= WINDOW windowdefn_list */
|
|
-{ yymsp[-1].minor.yy379 = yymsp[0].minor.yy379; }
|
|
+ case 318: /* window_clause ::= WINDOW windowdefn_list */
|
|
+{ yymsp[-1].minor.yy303 = yymsp[0].minor.yy303; }
|
|
break;
|
|
- case 314: /* over_clause ::= filter_opt OVER LP window RP */
|
|
+ case 319: /* filter_over ::= filter_clause over_clause */
|
|
{
|
|
- yylhsminor.yy379 = yymsp[-1].minor.yy379;
|
|
- assert( yylhsminor.yy379!=0 );
|
|
- yylhsminor.yy379->pFilter = yymsp[-4].minor.yy102;
|
|
+ yymsp[0].minor.yy303->pFilter = yymsp[-1].minor.yy202;
|
|
+ yylhsminor.yy303 = yymsp[0].minor.yy303;
|
|
}
|
|
- yymsp[-4].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[-1].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 315: /* over_clause ::= filter_opt OVER nm */
|
|
+ case 321: /* filter_over ::= filter_clause */
|
|
{
|
|
- yylhsminor.yy379 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
|
|
- if( yylhsminor.yy379 ){
|
|
- yylhsminor.yy379->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
|
|
- yylhsminor.yy379->pFilter = yymsp[-2].minor.yy102;
|
|
+ yylhsminor.yy303 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
|
|
+ if( yylhsminor.yy303 ){
|
|
+ yylhsminor.yy303->eFrmType = TK_FILTER;
|
|
+ yylhsminor.yy303->pFilter = yymsp[0].minor.yy202;
|
|
}else{
|
|
- sqlite3ExprDelete(pParse->db, yymsp[-2].minor.yy102);
|
|
+ sqlite3ExprDelete(pParse->db, yymsp[0].minor.yy202);
|
|
}
|
|
}
|
|
- yymsp[-2].minor.yy379 = yylhsminor.yy379;
|
|
+ yymsp[0].minor.yy303 = yylhsminor.yy303;
|
|
break;
|
|
- case 317: /* filter_opt ::= FILTER LP WHERE expr RP */
|
|
-{ yymsp[-4].minor.yy102 = yymsp[-1].minor.yy102; }
|
|
+ case 322: /* over_clause ::= OVER LP window RP */
|
|
+{
|
|
+ yymsp[-3].minor.yy303 = yymsp[-1].minor.yy303;
|
|
+ assert( yymsp[-3].minor.yy303!=0 );
|
|
+}
|
|
+ break;
|
|
+ case 323: /* over_clause ::= OVER nm */
|
|
+{
|
|
+ yymsp[-1].minor.yy303 = (Window*)sqlite3DbMallocZero(pParse->db, sizeof(Window));
|
|
+ if( yymsp[-1].minor.yy303 ){
|
|
+ yymsp[-1].minor.yy303->zName = sqlite3DbStrNDup(pParse->db, yymsp[0].minor.yy0.z, yymsp[0].minor.yy0.n);
|
|
+ }
|
|
+}
|
|
+ break;
|
|
+ case 324: /* filter_clause ::= FILTER LP WHERE expr RP */
|
|
+{ yymsp[-4].minor.yy202 = yymsp[-1].minor.yy202; }
|
|
break;
|
|
default:
|
|
- /* (318) input ::= cmdlist */ yytestcase(yyruleno==318);
|
|
- /* (319) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==319);
|
|
- /* (320) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=320);
|
|
- /* (321) ecmd ::= SEMI */ yytestcase(yyruleno==321);
|
|
- /* (322) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==322);
|
|
- /* (323) ecmd ::= explain cmdx */ yytestcase(yyruleno==323);
|
|
- /* (324) trans_opt ::= */ yytestcase(yyruleno==324);
|
|
- /* (325) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==325);
|
|
- /* (326) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==326);
|
|
- /* (327) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==327);
|
|
- /* (328) savepoint_opt ::= */ yytestcase(yyruleno==328);
|
|
- /* (329) cmd ::= create_table create_table_args */ yytestcase(yyruleno==329);
|
|
- /* (330) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==330);
|
|
- /* (331) columnlist ::= columnname carglist */ yytestcase(yyruleno==331);
|
|
- /* (332) nm ::= ID|INDEXED */ yytestcase(yyruleno==332);
|
|
- /* (333) nm ::= STRING */ yytestcase(yyruleno==333);
|
|
- /* (334) nm ::= JOIN_KW */ yytestcase(yyruleno==334);
|
|
- /* (335) typetoken ::= typename */ yytestcase(yyruleno==335);
|
|
- /* (336) typename ::= ID|STRING */ yytestcase(yyruleno==336);
|
|
- /* (337) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=337);
|
|
- /* (338) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=338);
|
|
- /* (339) carglist ::= carglist ccons */ yytestcase(yyruleno==339);
|
|
- /* (340) carglist ::= */ yytestcase(yyruleno==340);
|
|
- /* (341) ccons ::= NULL onconf */ yytestcase(yyruleno==341);
|
|
- /* (342) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==342);
|
|
- /* (343) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==343);
|
|
- /* (344) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=344);
|
|
- /* (345) tconscomma ::= */ yytestcase(yyruleno==345);
|
|
- /* (346) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=346);
|
|
- /* (347) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=347);
|
|
- /* (348) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=348);
|
|
- /* (349) oneselect ::= values */ yytestcase(yyruleno==349);
|
|
- /* (350) sclp ::= selcollist COMMA */ yytestcase(yyruleno==350);
|
|
- /* (351) as ::= ID|STRING */ yytestcase(yyruleno==351);
|
|
- /* (352) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=352);
|
|
- /* (353) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==353);
|
|
- /* (354) exprlist ::= nexprlist */ yytestcase(yyruleno==354);
|
|
- /* (355) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=355);
|
|
- /* (356) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=356);
|
|
- /* (357) nmnum ::= ON */ yytestcase(yyruleno==357);
|
|
- /* (358) nmnum ::= DELETE */ yytestcase(yyruleno==358);
|
|
- /* (359) nmnum ::= DEFAULT */ yytestcase(yyruleno==359);
|
|
- /* (360) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==360);
|
|
- /* (361) foreach_clause ::= */ yytestcase(yyruleno==361);
|
|
- /* (362) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==362);
|
|
- /* (363) trnm ::= nm */ yytestcase(yyruleno==363);
|
|
- /* (364) tridxby ::= */ yytestcase(yyruleno==364);
|
|
- /* (365) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==365);
|
|
- /* (366) database_kw_opt ::= */ yytestcase(yyruleno==366);
|
|
- /* (367) kwcolumn_opt ::= */ yytestcase(yyruleno==367);
|
|
- /* (368) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==368);
|
|
- /* (369) vtabarglist ::= vtabarg */ yytestcase(yyruleno==369);
|
|
- /* (370) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==370);
|
|
- /* (371) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==371);
|
|
- /* (372) anylist ::= */ yytestcase(yyruleno==372);
|
|
- /* (373) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==373);
|
|
- /* (374) anylist ::= anylist ANY */ yytestcase(yyruleno==374);
|
|
- /* (375) with ::= */ yytestcase(yyruleno==375);
|
|
+ /* (325) input ::= cmdlist */ yytestcase(yyruleno==325);
|
|
+ /* (326) cmdlist ::= cmdlist ecmd */ yytestcase(yyruleno==326);
|
|
+ /* (327) cmdlist ::= ecmd (OPTIMIZED OUT) */ assert(yyruleno!=327);
|
|
+ /* (328) ecmd ::= SEMI */ yytestcase(yyruleno==328);
|
|
+ /* (329) ecmd ::= cmdx SEMI */ yytestcase(yyruleno==329);
|
|
+ /* (330) ecmd ::= explain cmdx SEMI (NEVER REDUCES) */ assert(yyruleno!=330);
|
|
+ /* (331) trans_opt ::= */ yytestcase(yyruleno==331);
|
|
+ /* (332) trans_opt ::= TRANSACTION */ yytestcase(yyruleno==332);
|
|
+ /* (333) trans_opt ::= TRANSACTION nm */ yytestcase(yyruleno==333);
|
|
+ /* (334) savepoint_opt ::= SAVEPOINT */ yytestcase(yyruleno==334);
|
|
+ /* (335) savepoint_opt ::= */ yytestcase(yyruleno==335);
|
|
+ /* (336) cmd ::= create_table create_table_args */ yytestcase(yyruleno==336);
|
|
+ /* (337) columnlist ::= columnlist COMMA columnname carglist */ yytestcase(yyruleno==337);
|
|
+ /* (338) columnlist ::= columnname carglist */ yytestcase(yyruleno==338);
|
|
+ /* (339) nm ::= ID|INDEXED */ yytestcase(yyruleno==339);
|
|
+ /* (340) nm ::= STRING */ yytestcase(yyruleno==340);
|
|
+ /* (341) nm ::= JOIN_KW */ yytestcase(yyruleno==341);
|
|
+ /* (342) typetoken ::= typename */ yytestcase(yyruleno==342);
|
|
+ /* (343) typename ::= ID|STRING */ yytestcase(yyruleno==343);
|
|
+ /* (344) signed ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=344);
|
|
+ /* (345) signed ::= minus_num (OPTIMIZED OUT) */ assert(yyruleno!=345);
|
|
+ /* (346) carglist ::= carglist ccons */ yytestcase(yyruleno==346);
|
|
+ /* (347) carglist ::= */ yytestcase(yyruleno==347);
|
|
+ /* (348) ccons ::= NULL onconf */ yytestcase(yyruleno==348);
|
|
+ /* (349) ccons ::= GENERATED ALWAYS AS generated */ yytestcase(yyruleno==349);
|
|
+ /* (350) ccons ::= AS generated */ yytestcase(yyruleno==350);
|
|
+ /* (351) conslist_opt ::= COMMA conslist */ yytestcase(yyruleno==351);
|
|
+ /* (352) conslist ::= conslist tconscomma tcons */ yytestcase(yyruleno==352);
|
|
+ /* (353) conslist ::= tcons (OPTIMIZED OUT) */ assert(yyruleno!=353);
|
|
+ /* (354) tconscomma ::= */ yytestcase(yyruleno==354);
|
|
+ /* (355) defer_subclause_opt ::= defer_subclause (OPTIMIZED OUT) */ assert(yyruleno!=355);
|
|
+ /* (356) resolvetype ::= raisetype (OPTIMIZED OUT) */ assert(yyruleno!=356);
|
|
+ /* (357) selectnowith ::= oneselect (OPTIMIZED OUT) */ assert(yyruleno!=357);
|
|
+ /* (358) oneselect ::= values */ yytestcase(yyruleno==358);
|
|
+ /* (359) sclp ::= selcollist COMMA */ yytestcase(yyruleno==359);
|
|
+ /* (360) as ::= ID|STRING */ yytestcase(yyruleno==360);
|
|
+ /* (361) expr ::= term (OPTIMIZED OUT) */ assert(yyruleno!=361);
|
|
+ /* (362) likeop ::= LIKE_KW|MATCH */ yytestcase(yyruleno==362);
|
|
+ /* (363) exprlist ::= nexprlist */ yytestcase(yyruleno==363);
|
|
+ /* (364) nmnum ::= plus_num (OPTIMIZED OUT) */ assert(yyruleno!=364);
|
|
+ /* (365) nmnum ::= nm (OPTIMIZED OUT) */ assert(yyruleno!=365);
|
|
+ /* (366) nmnum ::= ON */ yytestcase(yyruleno==366);
|
|
+ /* (367) nmnum ::= DELETE */ yytestcase(yyruleno==367);
|
|
+ /* (368) nmnum ::= DEFAULT */ yytestcase(yyruleno==368);
|
|
+ /* (369) plus_num ::= INTEGER|FLOAT */ yytestcase(yyruleno==369);
|
|
+ /* (370) foreach_clause ::= */ yytestcase(yyruleno==370);
|
|
+ /* (371) foreach_clause ::= FOR EACH ROW */ yytestcase(yyruleno==371);
|
|
+ /* (372) trnm ::= nm */ yytestcase(yyruleno==372);
|
|
+ /* (373) tridxby ::= */ yytestcase(yyruleno==373);
|
|
+ /* (374) database_kw_opt ::= DATABASE */ yytestcase(yyruleno==374);
|
|
+ /* (375) database_kw_opt ::= */ yytestcase(yyruleno==375);
|
|
+ /* (376) kwcolumn_opt ::= */ yytestcase(yyruleno==376);
|
|
+ /* (377) kwcolumn_opt ::= COLUMNKW */ yytestcase(yyruleno==377);
|
|
+ /* (378) vtabarglist ::= vtabarg */ yytestcase(yyruleno==378);
|
|
+ /* (379) vtabarglist ::= vtabarglist COMMA vtabarg */ yytestcase(yyruleno==379);
|
|
+ /* (380) vtabarg ::= vtabarg vtabargtoken */ yytestcase(yyruleno==380);
|
|
+ /* (381) anylist ::= */ yytestcase(yyruleno==381);
|
|
+ /* (382) anylist ::= anylist LP anylist RP */ yytestcase(yyruleno==382);
|
|
+ /* (383) anylist ::= anylist ANY */ yytestcase(yyruleno==383);
|
|
+ /* (384) with ::= */ yytestcase(yyruleno==384);
|
|
break;
|
|
/********** End reduce actions ************************************************/
|
|
};
|
|
@@ -153594,13 +158418,12 @@
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3ParserFallback(int iToken){
|
|
#ifdef YYFALLBACK
|
|
- if( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) ){
|
|
- return yyFallback[iToken];
|
|
- }
|
|
+ assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
|
|
+ return yyFallback[iToken];
|
|
#else
|
|
(void)iToken;
|
|
-#endif
|
|
return 0;
|
|
+#endif
|
|
}
|
|
|
|
/************** End of parse.c ***********************************************/
|
|
@@ -153765,145 +158588,279 @@
|
|
** is substantially reduced. This is important for embedded applications
|
|
** on platforms with limited memory.
|
|
*/
|
|
-/* Hash score: 214 */
|
|
-/* zKWText[] encodes 950 bytes of keyword text in 629 bytes */
|
|
+/* Hash score: 227 */
|
|
+/* zKWText[] encodes 984 bytes of keyword text in 648 bytes */
|
|
/* REINDEXEDESCAPEACHECKEYBEFOREIGNOREGEXPLAINSTEADDATABASELECT */
|
|
-/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYCONSTRAINTERSECTIES */
|
|
-/* AVEPOINTOFFSETRANSACTIONATURALTERAISEXCEPTRIGGEREFERENCES */
|
|
-/* UNIQUERYWITHOUTERELEASEXCLUSIVEXISTSATTACHAVINGLOBEGINNERANGE */
|
|
-/* BETWEENOTHINGROUPSCASCADETACHCASECOLLATECREATECURRENT_DATE */
|
|
-/* IMMEDIATEJOINSERTLIKEMATCHPLANALYZEPRAGMABORTUPDATEVALUES */
|
|
-/* VIRTUALIMITWHENOTNULLWHERECURSIVEAFTERENAMEANDEFAULT */
|
|
-/* AUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSSCURRENT_TIMESTAMP */
|
|
-/* ARTITIONDEFERREDISTINCTDROPRECEDINGFAILFILTEREPLACEFOLLOWING */
|
|
-/* FROMFULLIFISNULLORDERESTRICTOTHERSOVERIGHTROLLBACKROWS */
|
|
+/* ABLEFTHENDEFERRABLELSEXCLUDELETEMPORARYISNULLSAVEPOINTERSECT */
|
|
+/* IESNOTNULLIKEXCEPTRANSACTIONATURALTERAISEXCLUSIVEXISTS */
|
|
+/* CONSTRAINTOFFSETRIGGERANGENERATEDETACHAVINGLOBEGINNEREFERENCES */
|
|
+/* UNIQUERYWITHOUTERELEASEATTACHBETWEENOTHINGROUPSCASCADEFAULT */
|
|
+/* CASECOLLATECREATECURRENT_DATEIMMEDIATEJOINSERTMATCHPLANALYZE */
|
|
+/* PRAGMABORTUPDATEVALUESVIRTUALWAYSWHENWHERECURSIVEAFTERENAMEAND */
|
|
+/* EFERREDISTINCTAUTOINCREMENTCASTCOLUMNCOMMITCONFLICTCROSS */
|
|
+/* CURRENT_TIMESTAMPARTITIONDROPRECEDINGFAILASTFILTEREPLACEFIRST */
|
|
+/* FOLLOWINGFROMFULLIMITIFORDERESTRICTOTHERSOVERIGHTROLLBACKROWS */
|
|
/* UNBOUNDEDUNIONUSINGVACUUMVIEWINDOWBYINITIALLYPRIMARY */
|
|
-static const char zKWText[628] = {
|
|
+static const char zKWText[647] = {
|
|
'R','E','I','N','D','E','X','E','D','E','S','C','A','P','E','A','C','H',
|
|
'E','C','K','E','Y','B','E','F','O','R','E','I','G','N','O','R','E','G',
|
|
'E','X','P','L','A','I','N','S','T','E','A','D','D','A','T','A','B','A',
|
|
'S','E','L','E','C','T','A','B','L','E','F','T','H','E','N','D','E','F',
|
|
'E','R','R','A','B','L','E','L','S','E','X','C','L','U','D','E','L','E',
|
|
- 'T','E','M','P','O','R','A','R','Y','C','O','N','S','T','R','A','I','N',
|
|
- 'T','E','R','S','E','C','T','I','E','S','A','V','E','P','O','I','N','T',
|
|
- 'O','F','F','S','E','T','R','A','N','S','A','C','T','I','O','N','A','T',
|
|
- 'U','R','A','L','T','E','R','A','I','S','E','X','C','E','P','T','R','I',
|
|
- 'G','G','E','R','E','F','E','R','E','N','C','E','S','U','N','I','Q','U',
|
|
- 'E','R','Y','W','I','T','H','O','U','T','E','R','E','L','E','A','S','E',
|
|
- 'X','C','L','U','S','I','V','E','X','I','S','T','S','A','T','T','A','C',
|
|
- 'H','A','V','I','N','G','L','O','B','E','G','I','N','N','E','R','A','N',
|
|
- 'G','E','B','E','T','W','E','E','N','O','T','H','I','N','G','R','O','U',
|
|
- 'P','S','C','A','S','C','A','D','E','T','A','C','H','C','A','S','E','C',
|
|
- 'O','L','L','A','T','E','C','R','E','A','T','E','C','U','R','R','E','N',
|
|
- 'T','_','D','A','T','E','I','M','M','E','D','I','A','T','E','J','O','I',
|
|
- 'N','S','E','R','T','L','I','K','E','M','A','T','C','H','P','L','A','N',
|
|
- 'A','L','Y','Z','E','P','R','A','G','M','A','B','O','R','T','U','P','D',
|
|
- 'A','T','E','V','A','L','U','E','S','V','I','R','T','U','A','L','I','M',
|
|
- 'I','T','W','H','E','N','O','T','N','U','L','L','W','H','E','R','E','C',
|
|
- 'U','R','S','I','V','E','A','F','T','E','R','E','N','A','M','E','A','N',
|
|
- 'D','E','F','A','U','L','T','A','U','T','O','I','N','C','R','E','M','E',
|
|
- 'N','T','C','A','S','T','C','O','L','U','M','N','C','O','M','M','I','T',
|
|
- 'C','O','N','F','L','I','C','T','C','R','O','S','S','C','U','R','R','E',
|
|
- 'N','T','_','T','I','M','E','S','T','A','M','P','A','R','T','I','T','I',
|
|
- 'O','N','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','D',
|
|
- 'R','O','P','R','E','C','E','D','I','N','G','F','A','I','L','F','I','L',
|
|
- 'T','E','R','E','P','L','A','C','E','F','O','L','L','O','W','I','N','G',
|
|
- 'F','R','O','M','F','U','L','L','I','F','I','S','N','U','L','L','O','R',
|
|
- 'D','E','R','E','S','T','R','I','C','T','O','T','H','E','R','S','O','V',
|
|
- 'E','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O','W','S',
|
|
- 'U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S','I','N',
|
|
- 'G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W','B','Y',
|
|
- 'I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y',
|
|
+ 'T','E','M','P','O','R','A','R','Y','I','S','N','U','L','L','S','A','V',
|
|
+ 'E','P','O','I','N','T','E','R','S','E','C','T','I','E','S','N','O','T',
|
|
+ 'N','U','L','L','I','K','E','X','C','E','P','T','R','A','N','S','A','C',
|
|
+ 'T','I','O','N','A','T','U','R','A','L','T','E','R','A','I','S','E','X',
|
|
+ 'C','L','U','S','I','V','E','X','I','S','T','S','C','O','N','S','T','R',
|
|
+ 'A','I','N','T','O','F','F','S','E','T','R','I','G','G','E','R','A','N',
|
|
+ 'G','E','N','E','R','A','T','E','D','E','T','A','C','H','A','V','I','N',
|
|
+ 'G','L','O','B','E','G','I','N','N','E','R','E','F','E','R','E','N','C',
|
|
+ 'E','S','U','N','I','Q','U','E','R','Y','W','I','T','H','O','U','T','E',
|
|
+ 'R','E','L','E','A','S','E','A','T','T','A','C','H','B','E','T','W','E',
|
|
+ 'E','N','O','T','H','I','N','G','R','O','U','P','S','C','A','S','C','A',
|
|
+ 'D','E','F','A','U','L','T','C','A','S','E','C','O','L','L','A','T','E',
|
|
+ 'C','R','E','A','T','E','C','U','R','R','E','N','T','_','D','A','T','E',
|
|
+ 'I','M','M','E','D','I','A','T','E','J','O','I','N','S','E','R','T','M',
|
|
+ 'A','T','C','H','P','L','A','N','A','L','Y','Z','E','P','R','A','G','M',
|
|
+ 'A','B','O','R','T','U','P','D','A','T','E','V','A','L','U','E','S','V',
|
|
+ 'I','R','T','U','A','L','W','A','Y','S','W','H','E','N','W','H','E','R',
|
|
+ 'E','C','U','R','S','I','V','E','A','F','T','E','R','E','N','A','M','E',
|
|
+ 'A','N','D','E','F','E','R','R','E','D','I','S','T','I','N','C','T','A',
|
|
+ 'U','T','O','I','N','C','R','E','M','E','N','T','C','A','S','T','C','O',
|
|
+ 'L','U','M','N','C','O','M','M','I','T','C','O','N','F','L','I','C','T',
|
|
+ 'C','R','O','S','S','C','U','R','R','E','N','T','_','T','I','M','E','S',
|
|
+ 'T','A','M','P','A','R','T','I','T','I','O','N','D','R','O','P','R','E',
|
|
+ 'C','E','D','I','N','G','F','A','I','L','A','S','T','F','I','L','T','E',
|
|
+ 'R','E','P','L','A','C','E','F','I','R','S','T','F','O','L','L','O','W',
|
|
+ 'I','N','G','F','R','O','M','F','U','L','L','I','M','I','T','I','F','O',
|
|
+ 'R','D','E','R','E','S','T','R','I','C','T','O','T','H','E','R','S','O',
|
|
+ 'V','E','R','I','G','H','T','R','O','L','L','B','A','C','K','R','O','W',
|
|
+ 'S','U','N','B','O','U','N','D','E','D','U','N','I','O','N','U','S','I',
|
|
+ 'N','G','V','A','C','U','U','M','V','I','E','W','I','N','D','O','W','B',
|
|
+ 'Y','I','N','I','T','I','A','L','L','Y','P','R','I','M','A','R','Y',
|
|
};
|
|
/* aKWHash[i] is the hash value for the i-th keyword */
|
|
static const unsigned char aKWHash[127] = {
|
|
- 75, 111, 127, 73, 108, 29, 0, 0, 83, 0, 77, 63, 0,
|
|
- 37, 33, 78, 15, 0, 126, 86, 57, 120, 128, 19, 0, 0,
|
|
- 133, 0, 131, 123, 0, 22, 98, 0, 9, 0, 0, 117, 71,
|
|
- 0, 69, 6, 0, 49, 95, 140, 0, 129, 106, 0, 0, 54,
|
|
- 0, 109, 24, 0, 17, 0, 134, 56, 23, 26, 5, 58, 135,
|
|
- 101, 0, 0, 139, 112, 62, 138, 59, 115, 65, 0, 96, 0,
|
|
- 105, 45, 0, 104, 0, 0, 0, 100, 97, 102, 107, 119, 14,
|
|
- 31, 118, 0, 81, 0, 136, 116, 137, 61, 124, 132, 80, 121,
|
|
- 88, 30, 85, 0, 0, 99, 35, 125, 122, 0, 130, 0, 0,
|
|
- 41, 0, 91, 89, 90, 0, 20, 87, 113, 82,
|
|
+ 84, 102, 132, 82, 114, 29, 0, 0, 91, 0, 85, 72, 0,
|
|
+ 53, 35, 86, 15, 0, 42, 94, 54, 126, 133, 19, 0, 0,
|
|
+ 138, 0, 40, 128, 0, 22, 104, 0, 9, 0, 0, 122, 80,
|
|
+ 0, 78, 6, 0, 65, 99, 145, 0, 134, 112, 0, 0, 48,
|
|
+ 0, 100, 24, 0, 17, 0, 27, 70, 23, 26, 5, 60, 140,
|
|
+ 107, 121, 0, 73, 101, 71, 143, 61, 119, 74, 0, 49, 0,
|
|
+ 11, 41, 0, 110, 0, 0, 0, 106, 10, 108, 113, 124, 14,
|
|
+ 50, 123, 0, 89, 0, 18, 120, 142, 56, 129, 137, 88, 83,
|
|
+ 37, 30, 125, 0, 0, 105, 51, 130, 127, 0, 34, 0, 0,
|
|
+ 44, 0, 95, 38, 39, 0, 20, 45, 116, 90,
|
|
};
|
|
/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0
|
|
** then the i-th keyword has no more hash collisions. Otherwise,
|
|
** the next keyword with the same hash is aKWHash[i]-1. */
|
|
-static const unsigned char aKWNext[140] = {
|
|
- 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
- 0, 2, 0, 0, 0, 0, 0, 0, 13, 0, 0, 0, 0,
|
|
- 0, 0, 0, 21, 0, 0, 12, 0, 0, 0, 0, 0, 0,
|
|
- 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
- 51, 28, 0, 0, 38, 0, 0, 0, 44, 0, 0, 0, 3,
|
|
- 0, 0, 67, 1, 66, 0, 0, 0, 36, 0, 47, 0, 0,
|
|
- 0, 0, 0, 48, 50, 76, 0, 0, 42, 0, 60, 0, 0,
|
|
- 0, 43, 0, 16, 55, 10, 0, 0, 0, 0, 0, 0, 0,
|
|
- 11, 72, 93, 0, 0, 8, 0, 110, 0, 103, 40, 53, 70,
|
|
- 0, 114, 0, 74, 52, 0, 0, 92, 39, 46, 0, 68, 32,
|
|
- 84, 0, 34, 27, 25, 18, 94, 0, 64, 79,
|
|
+static const unsigned char aKWNext[145] = {
|
|
+ 0, 0, 0, 0, 4, 0, 43, 0, 0, 103, 111, 0, 0,
|
|
+ 0, 2, 0, 0, 141, 0, 0, 0, 13, 0, 0, 0, 0,
|
|
+ 139, 0, 0, 118, 52, 0, 0, 135, 12, 0, 0, 62, 0,
|
|
+ 136, 0, 131, 0, 0, 36, 0, 0, 28, 77, 0, 0, 0,
|
|
+ 0, 59, 0, 47, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
+ 0, 69, 0, 0, 0, 0, 0, 144, 3, 0, 58, 0, 1,
|
|
+ 75, 0, 0, 0, 31, 0, 0, 0, 0, 0, 0, 64, 66,
|
|
+ 63, 0, 0, 0, 0, 46, 0, 16, 0, 115, 0, 0, 0,
|
|
+ 0, 0, 0, 0, 0, 0, 0, 81, 97, 0, 8, 0, 109,
|
|
+ 21, 7, 67, 0, 79, 93, 117, 0, 0, 68, 0, 0, 96,
|
|
+ 0, 55, 0, 76, 0, 92, 32, 33, 57, 25, 0, 98, 0,
|
|
+ 0, 87,
|
|
};
|
|
/* aKWLen[i] is the length (in bytes) of the i-th keyword */
|
|
-static const unsigned char aKWLen[140] = {
|
|
+static const unsigned char aKWLen[145] = {
|
|
7, 7, 5, 4, 6, 4, 5, 3, 6, 7, 3, 6, 6,
|
|
7, 7, 3, 8, 2, 6, 5, 4, 4, 3, 10, 4, 7,
|
|
- 6, 9, 4, 2, 10, 9, 4, 9, 4, 6, 2, 3, 11,
|
|
- 6, 2, 7, 5, 5, 6, 7, 10, 6, 5, 7, 4, 5,
|
|
- 7, 9, 6, 6, 6, 4, 5, 5, 5, 7, 7, 6, 5,
|
|
- 7, 3, 6, 4, 7, 6, 12, 9, 4, 6, 4, 5, 4,
|
|
- 7, 6, 5, 6, 6, 7, 5, 4, 7, 3, 2, 4, 5,
|
|
- 9, 5, 6, 3, 7, 13, 2, 2, 4, 6, 6, 8, 5,
|
|
- 17, 12, 7, 9, 8, 8, 2, 4, 9, 4, 6, 7, 9,
|
|
- 4, 4, 2, 6, 5, 8, 6, 4, 5, 8, 4, 3, 9,
|
|
- 5, 5, 6, 4, 6, 2, 2, 9, 3, 7,
|
|
+ 6, 9, 4, 2, 6, 5, 9, 9, 4, 7, 3, 2, 4,
|
|
+ 4, 6, 11, 6, 2, 7, 5, 5, 9, 6, 10, 4, 6,
|
|
+ 2, 3, 7, 5, 9, 6, 6, 4, 5, 5, 10, 6, 5,
|
|
+ 7, 4, 5, 7, 6, 7, 7, 6, 5, 7, 3, 7, 4,
|
|
+ 7, 6, 12, 9, 4, 6, 5, 4, 7, 6, 5, 6, 6,
|
|
+ 7, 6, 4, 5, 9, 5, 6, 3, 8, 8, 2, 13, 2,
|
|
+ 2, 4, 6, 6, 8, 5, 17, 12, 7, 9, 4, 9, 4,
|
|
+ 4, 6, 7, 5, 9, 4, 4, 5, 2, 5, 8, 6, 4,
|
|
+ 5, 8, 4, 3, 9, 5, 5, 6, 4, 6, 2, 2, 9,
|
|
+ 3, 7,
|
|
};
|
|
/* aKWOffset[i] is the index into zKWText[] of the start of
|
|
** the text for the i-th keyword. */
|
|
-static const unsigned short int aKWOffset[140] = {
|
|
+static const unsigned short int aKWOffset[145] = {
|
|
0, 2, 2, 8, 9, 14, 16, 20, 23, 25, 25, 29, 33,
|
|
36, 41, 46, 48, 53, 54, 59, 62, 65, 67, 69, 78, 81,
|
|
- 86, 90, 90, 94, 99, 106, 114, 117, 123, 126, 126, 129, 131,
|
|
- 136, 140, 141, 146, 150, 154, 159, 165, 175, 178, 183, 183, 187,
|
|
- 191, 197, 205, 211, 216, 221, 224, 227, 231, 236, 242, 248, 248,
|
|
- 254, 255, 259, 265, 269, 276, 282, 294, 303, 305, 311, 315, 320,
|
|
- 322, 329, 334, 339, 345, 351, 357, 362, 365, 365, 365, 368, 372,
|
|
- 375, 384, 388, 394, 396, 403, 405, 407, 416, 420, 426, 432, 440,
|
|
- 445, 445, 445, 461, 470, 477, 478, 485, 488, 497, 501, 506, 513,
|
|
- 522, 526, 530, 532, 538, 542, 550, 556, 559, 564, 572, 572, 576,
|
|
- 585, 590, 595, 601, 604, 607, 610, 612, 617, 621,
|
|
+ 86, 90, 90, 94, 99, 101, 105, 111, 119, 123, 123, 123, 126,
|
|
+ 129, 132, 137, 142, 146, 147, 152, 156, 160, 168, 174, 181, 184,
|
|
+ 184, 187, 189, 195, 198, 206, 211, 216, 219, 222, 226, 236, 239,
|
|
+ 244, 244, 248, 252, 259, 265, 271, 277, 277, 283, 284, 288, 295,
|
|
+ 299, 306, 312, 324, 333, 335, 341, 346, 348, 355, 360, 365, 371,
|
|
+ 377, 382, 388, 392, 395, 404, 408, 414, 416, 423, 424, 431, 433,
|
|
+ 435, 444, 448, 454, 460, 468, 473, 473, 473, 489, 498, 501, 510,
|
|
+ 513, 517, 522, 529, 534, 543, 547, 550, 555, 557, 561, 569, 575,
|
|
+ 578, 583, 591, 591, 595, 604, 609, 614, 620, 623, 626, 629, 631,
|
|
+ 636, 640,
|
|
};
|
|
/* aKWCode[i] is the parser symbol code for the i-th keyword */
|
|
-static const unsigned char aKWCode[140] = {
|
|
+static const unsigned char aKWCode[145] = {
|
|
TK_REINDEX, TK_INDEXED, TK_INDEX, TK_DESC, TK_ESCAPE,
|
|
TK_EACH, TK_CHECK, TK_KEY, TK_BEFORE, TK_FOREIGN,
|
|
TK_FOR, TK_IGNORE, TK_LIKE_KW, TK_EXPLAIN, TK_INSTEAD,
|
|
TK_ADD, TK_DATABASE, TK_AS, TK_SELECT, TK_TABLE,
|
|
TK_JOIN_KW, TK_THEN, TK_END, TK_DEFERRABLE, TK_ELSE,
|
|
TK_EXCLUDE, TK_DELETE, TK_TEMP, TK_TEMP, TK_OR,
|
|
- TK_CONSTRAINT, TK_INTERSECT, TK_TIES, TK_SAVEPOINT, TK_INTO,
|
|
- TK_OFFSET, TK_OF, TK_SET, TK_TRANSACTION,TK_ACTION,
|
|
- TK_ON, TK_JOIN_KW, TK_ALTER, TK_RAISE, TK_EXCEPT,
|
|
- TK_TRIGGER, TK_REFERENCES, TK_UNIQUE, TK_QUERY, TK_WITHOUT,
|
|
- TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_EXCLUSIVE, TK_EXISTS,
|
|
- TK_ATTACH, TK_HAVING, TK_LIKE_KW, TK_BEGIN, TK_JOIN_KW,
|
|
- TK_RANGE, TK_BETWEEN, TK_NOTHING, TK_GROUPS, TK_GROUP,
|
|
- TK_CASCADE, TK_ASC, TK_DETACH, TK_CASE, TK_COLLATE,
|
|
- TK_CREATE, TK_CTIME_KW, TK_IMMEDIATE, TK_JOIN, TK_INSERT,
|
|
- TK_LIKE_KW, TK_MATCH, TK_PLAN, TK_ANALYZE, TK_PRAGMA,
|
|
- TK_ABORT, TK_UPDATE, TK_VALUES, TK_VIRTUAL, TK_LIMIT,
|
|
- TK_WHEN, TK_NOTNULL, TK_NOT, TK_NO, TK_NULL,
|
|
- TK_WHERE, TK_RECURSIVE, TK_AFTER, TK_RENAME, TK_AND,
|
|
- TK_DEFAULT, TK_AUTOINCR, TK_TO, TK_IN, TK_CAST,
|
|
- TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW, TK_CTIME_KW,
|
|
- TK_CTIME_KW, TK_CURRENT, TK_PARTITION, TK_DEFERRED, TK_DISTINCT,
|
|
- TK_IS, TK_DROP, TK_PRECEDING, TK_FAIL, TK_FILTER,
|
|
- TK_REPLACE, TK_FOLLOWING, TK_FROM, TK_JOIN_KW, TK_IF,
|
|
- TK_ISNULL, TK_ORDER, TK_RESTRICT, TK_OTHERS, TK_OVER,
|
|
+ TK_ISNULL, TK_NULLS, TK_SAVEPOINT, TK_INTERSECT, TK_TIES,
|
|
+ TK_NOTNULL, TK_NOT, TK_NO, TK_NULL, TK_LIKE_KW,
|
|
+ TK_EXCEPT, TK_TRANSACTION,TK_ACTION, TK_ON, TK_JOIN_KW,
|
|
+ TK_ALTER, TK_RAISE, TK_EXCLUSIVE, TK_EXISTS, TK_CONSTRAINT,
|
|
+ TK_INTO, TK_OFFSET, TK_OF, TK_SET, TK_TRIGGER,
|
|
+ TK_RANGE, TK_GENERATED, TK_DETACH, TK_HAVING, TK_LIKE_KW,
|
|
+ TK_BEGIN, TK_JOIN_KW, TK_REFERENCES, TK_UNIQUE, TK_QUERY,
|
|
+ TK_WITHOUT, TK_WITH, TK_JOIN_KW, TK_RELEASE, TK_ATTACH,
|
|
+ TK_BETWEEN, TK_NOTHING, TK_GROUPS, TK_GROUP, TK_CASCADE,
|
|
+ TK_ASC, TK_DEFAULT, TK_CASE, TK_COLLATE, TK_CREATE,
|
|
+ TK_CTIME_KW, TK_IMMEDIATE, TK_JOIN, TK_INSERT, TK_MATCH,
|
|
+ TK_PLAN, TK_ANALYZE, TK_PRAGMA, TK_ABORT, TK_UPDATE,
|
|
+ TK_VALUES, TK_VIRTUAL, TK_ALWAYS, TK_WHEN, TK_WHERE,
|
|
+ TK_RECURSIVE, TK_AFTER, TK_RENAME, TK_AND, TK_DEFERRED,
|
|
+ TK_DISTINCT, TK_IS, TK_AUTOINCR, TK_TO, TK_IN,
|
|
+ TK_CAST, TK_COLUMNKW, TK_COMMIT, TK_CONFLICT, TK_JOIN_KW,
|
|
+ TK_CTIME_KW, TK_CTIME_KW, TK_CURRENT, TK_PARTITION, TK_DROP,
|
|
+ TK_PRECEDING, TK_FAIL, TK_LAST, TK_FILTER, TK_REPLACE,
|
|
+ TK_FIRST, TK_FOLLOWING, TK_FROM, TK_JOIN_KW, TK_LIMIT,
|
|
+ TK_IF, TK_ORDER, TK_RESTRICT, TK_OTHERS, TK_OVER,
|
|
TK_JOIN_KW, TK_ROLLBACK, TK_ROWS, TK_ROW, TK_UNBOUNDED,
|
|
TK_UNION, TK_USING, TK_VACUUM, TK_VIEW, TK_WINDOW,
|
|
TK_DO, TK_BY, TK_INITIALLY, TK_ALL, TK_PRIMARY,
|
|
};
|
|
+/* Hash table decoded:
|
|
+** 0: INSERT
|
|
+** 1: IS
|
|
+** 2: ROLLBACK TRIGGER
|
|
+** 3: IMMEDIATE
|
|
+** 4: PARTITION
|
|
+** 5: TEMP
|
|
+** 6:
|
|
+** 7:
|
|
+** 8: VALUES WITHOUT
|
|
+** 9:
|
|
+** 10: MATCH
|
|
+** 11: NOTHING
|
|
+** 12:
|
|
+** 13: OF
|
|
+** 14: TIES IGNORE
|
|
+** 15: PLAN
|
|
+** 16: INSTEAD INDEXED
|
|
+** 17:
|
|
+** 18: TRANSACTION RIGHT
|
|
+** 19: WHEN
|
|
+** 20: SET HAVING
|
|
+** 21: IF
|
|
+** 22: ROWS
|
|
+** 23: SELECT
|
|
+** 24:
|
|
+** 25:
|
|
+** 26: VACUUM SAVEPOINT
|
|
+** 27:
|
|
+** 28: LIKE UNION VIRTUAL REFERENCES
|
|
+** 29: RESTRICT
|
|
+** 30:
|
|
+** 31: THEN REGEXP
|
|
+** 32: TO
|
|
+** 33:
|
|
+** 34: BEFORE
|
|
+** 35:
|
|
+** 36:
|
|
+** 37: FOLLOWING COLLATE CASCADE
|
|
+** 38: CREATE
|
|
+** 39:
|
|
+** 40: CASE REINDEX
|
|
+** 41: EACH
|
|
+** 42:
|
|
+** 43: QUERY
|
|
+** 44: AND ADD
|
|
+** 45: PRIMARY ANALYZE
|
|
+** 46:
|
|
+** 47: ROW ASC DETACH
|
|
+** 48: CURRENT_TIME CURRENT_DATE
|
|
+** 49:
|
|
+** 50:
|
|
+** 51: EXCLUSIVE TEMPORARY
|
|
+** 52:
|
|
+** 53: DEFERRED
|
|
+** 54: DEFERRABLE
|
|
+** 55:
|
|
+** 56: DATABASE
|
|
+** 57:
|
|
+** 58: DELETE VIEW GENERATED
|
|
+** 59: ATTACH
|
|
+** 60: END
|
|
+** 61: EXCLUDE
|
|
+** 62: ESCAPE DESC
|
|
+** 63: GLOB
|
|
+** 64: WINDOW ELSE
|
|
+** 65: COLUMN
|
|
+** 66: FIRST
|
|
+** 67:
|
|
+** 68: GROUPS ALL
|
|
+** 69: DISTINCT DROP KEY
|
|
+** 70: BETWEEN
|
|
+** 71: INITIALLY
|
|
+** 72: BEGIN
|
|
+** 73: FILTER CHECK ACTION
|
|
+** 74: GROUP INDEX
|
|
+** 75:
|
|
+** 76: EXISTS DEFAULT
|
|
+** 77:
|
|
+** 78: FOR CURRENT_TIMESTAMP
|
|
+** 79: EXCEPT
|
|
+** 80:
|
|
+** 81: CROSS
|
|
+** 82:
|
|
+** 83:
|
|
+** 84:
|
|
+** 85: CAST
|
|
+** 86: FOREIGN AUTOINCREMENT
|
|
+** 87: COMMIT
|
|
+** 88: CURRENT AFTER ALTER
|
|
+** 89: FULL FAIL CONFLICT
|
|
+** 90: EXPLAIN
|
|
+** 91: CONSTRAINT
|
|
+** 92: FROM ALWAYS
|
|
+** 93:
|
|
+** 94: ABORT
|
|
+** 95:
|
|
+** 96: AS DO
|
|
+** 97: REPLACE WITH RELEASE
|
|
+** 98: BY RENAME
|
|
+** 99: RANGE RAISE
|
|
+** 100: OTHERS
|
|
+** 101: USING NULLS
|
|
+** 102: PRAGMA
|
|
+** 103: JOIN ISNULL OFFSET
|
|
+** 104: NOT
|
|
+** 105: OR LAST LEFT
|
|
+** 106: LIMIT
|
|
+** 107:
|
|
+** 108:
|
|
+** 109: IN
|
|
+** 110: INTO
|
|
+** 111: OVER RECURSIVE
|
|
+** 112: ORDER OUTER
|
|
+** 113:
|
|
+** 114: INTERSECT UNBOUNDED
|
|
+** 115:
|
|
+** 116:
|
|
+** 117: ON
|
|
+** 118:
|
|
+** 119: WHERE
|
|
+** 120: NO INNER
|
|
+** 121: NULL
|
|
+** 122:
|
|
+** 123: TABLE
|
|
+** 124: NATURAL NOTNULL
|
|
+** 125: PRECEDING
|
|
+** 126: UPDATE UNIQUE
|
|
+*/
|
|
/* Check to see if z[0..n-1] is a keyword. If it is, write the
|
|
** parser symbol code for that keyword into *pType. Always
|
|
** return the integer n (the length of the token). */
|
|
@@ -153914,12 +158871,17 @@
|
|
i = ((charMap(z[0])*4) ^ (charMap(z[n-1])*3) ^ n) % 127;
|
|
for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){
|
|
if( aKWLen[i]!=n ) continue;
|
|
- j = 0;
|
|
zKW = &zKWText[aKWOffset[i]];
|
|
#ifdef SQLITE_ASCII
|
|
+ if( (z[0]&~0x20)!=zKW[0] ) continue;
|
|
+ if( (z[1]&~0x20)!=zKW[1] ) continue;
|
|
+ j = 2;
|
|
while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; }
|
|
#endif
|
|
#ifdef SQLITE_EBCDIC
|
|
+ if( toupper(z[0])!=zKW[0] ) continue;
|
|
+ if( toupper(z[1])!=zKW[1] ) continue;
|
|
+ j = 2;
|
|
while( j<n && toupper(z[j])==zKW[j] ){ j++; }
|
|
#endif
|
|
if( j<n ) continue;
|
|
@@ -153953,116 +158915,121 @@
|
|
testcase( i==27 ); /* TEMPORARY */
|
|
testcase( i==28 ); /* TEMP */
|
|
testcase( i==29 ); /* OR */
|
|
- testcase( i==30 ); /* CONSTRAINT */
|
|
- testcase( i==31 ); /* INTERSECT */
|
|
- testcase( i==32 ); /* TIES */
|
|
- testcase( i==33 ); /* SAVEPOINT */
|
|
- testcase( i==34 ); /* INTO */
|
|
- testcase( i==35 ); /* OFFSET */
|
|
- testcase( i==36 ); /* OF */
|
|
- testcase( i==37 ); /* SET */
|
|
- testcase( i==38 ); /* TRANSACTION */
|
|
- testcase( i==39 ); /* ACTION */
|
|
- testcase( i==40 ); /* ON */
|
|
- testcase( i==41 ); /* NATURAL */
|
|
- testcase( i==42 ); /* ALTER */
|
|
- testcase( i==43 ); /* RAISE */
|
|
- testcase( i==44 ); /* EXCEPT */
|
|
- testcase( i==45 ); /* TRIGGER */
|
|
- testcase( i==46 ); /* REFERENCES */
|
|
- testcase( i==47 ); /* UNIQUE */
|
|
- testcase( i==48 ); /* QUERY */
|
|
- testcase( i==49 ); /* WITHOUT */
|
|
- testcase( i==50 ); /* WITH */
|
|
- testcase( i==51 ); /* OUTER */
|
|
- testcase( i==52 ); /* RELEASE */
|
|
- testcase( i==53 ); /* EXCLUSIVE */
|
|
- testcase( i==54 ); /* EXISTS */
|
|
- testcase( i==55 ); /* ATTACH */
|
|
- testcase( i==56 ); /* HAVING */
|
|
- testcase( i==57 ); /* GLOB */
|
|
- testcase( i==58 ); /* BEGIN */
|
|
- testcase( i==59 ); /* INNER */
|
|
- testcase( i==60 ); /* RANGE */
|
|
- testcase( i==61 ); /* BETWEEN */
|
|
- testcase( i==62 ); /* NOTHING */
|
|
- testcase( i==63 ); /* GROUPS */
|
|
- testcase( i==64 ); /* GROUP */
|
|
- testcase( i==65 ); /* CASCADE */
|
|
- testcase( i==66 ); /* ASC */
|
|
- testcase( i==67 ); /* DETACH */
|
|
- testcase( i==68 ); /* CASE */
|
|
- testcase( i==69 ); /* COLLATE */
|
|
- testcase( i==70 ); /* CREATE */
|
|
- testcase( i==71 ); /* CURRENT_DATE */
|
|
- testcase( i==72 ); /* IMMEDIATE */
|
|
- testcase( i==73 ); /* JOIN */
|
|
- testcase( i==74 ); /* INSERT */
|
|
- testcase( i==75 ); /* LIKE */
|
|
- testcase( i==76 ); /* MATCH */
|
|
- testcase( i==77 ); /* PLAN */
|
|
- testcase( i==78 ); /* ANALYZE */
|
|
- testcase( i==79 ); /* PRAGMA */
|
|
- testcase( i==80 ); /* ABORT */
|
|
- testcase( i==81 ); /* UPDATE */
|
|
- testcase( i==82 ); /* VALUES */
|
|
- testcase( i==83 ); /* VIRTUAL */
|
|
- testcase( i==84 ); /* LIMIT */
|
|
- testcase( i==85 ); /* WHEN */
|
|
- testcase( i==86 ); /* NOTNULL */
|
|
- testcase( i==87 ); /* NOT */
|
|
- testcase( i==88 ); /* NO */
|
|
- testcase( i==89 ); /* NULL */
|
|
- testcase( i==90 ); /* WHERE */
|
|
- testcase( i==91 ); /* RECURSIVE */
|
|
- testcase( i==92 ); /* AFTER */
|
|
- testcase( i==93 ); /* RENAME */
|
|
- testcase( i==94 ); /* AND */
|
|
- testcase( i==95 ); /* DEFAULT */
|
|
- testcase( i==96 ); /* AUTOINCREMENT */
|
|
- testcase( i==97 ); /* TO */
|
|
- testcase( i==98 ); /* IN */
|
|
- testcase( i==99 ); /* CAST */
|
|
- testcase( i==100 ); /* COLUMN */
|
|
- testcase( i==101 ); /* COMMIT */
|
|
- testcase( i==102 ); /* CONFLICT */
|
|
- testcase( i==103 ); /* CROSS */
|
|
- testcase( i==104 ); /* CURRENT_TIMESTAMP */
|
|
- testcase( i==105 ); /* CURRENT_TIME */
|
|
- testcase( i==106 ); /* CURRENT */
|
|
- testcase( i==107 ); /* PARTITION */
|
|
- testcase( i==108 ); /* DEFERRED */
|
|
- testcase( i==109 ); /* DISTINCT */
|
|
- testcase( i==110 ); /* IS */
|
|
- testcase( i==111 ); /* DROP */
|
|
- testcase( i==112 ); /* PRECEDING */
|
|
- testcase( i==113 ); /* FAIL */
|
|
- testcase( i==114 ); /* FILTER */
|
|
- testcase( i==115 ); /* REPLACE */
|
|
- testcase( i==116 ); /* FOLLOWING */
|
|
- testcase( i==117 ); /* FROM */
|
|
- testcase( i==118 ); /* FULL */
|
|
- testcase( i==119 ); /* IF */
|
|
- testcase( i==120 ); /* ISNULL */
|
|
- testcase( i==121 ); /* ORDER */
|
|
- testcase( i==122 ); /* RESTRICT */
|
|
- testcase( i==123 ); /* OTHERS */
|
|
- testcase( i==124 ); /* OVER */
|
|
- testcase( i==125 ); /* RIGHT */
|
|
- testcase( i==126 ); /* ROLLBACK */
|
|
- testcase( i==127 ); /* ROWS */
|
|
- testcase( i==128 ); /* ROW */
|
|
- testcase( i==129 ); /* UNBOUNDED */
|
|
- testcase( i==130 ); /* UNION */
|
|
- testcase( i==131 ); /* USING */
|
|
- testcase( i==132 ); /* VACUUM */
|
|
- testcase( i==133 ); /* VIEW */
|
|
- testcase( i==134 ); /* WINDOW */
|
|
- testcase( i==135 ); /* DO */
|
|
- testcase( i==136 ); /* BY */
|
|
- testcase( i==137 ); /* INITIALLY */
|
|
- testcase( i==138 ); /* ALL */
|
|
- testcase( i==139 ); /* PRIMARY */
|
|
+ testcase( i==30 ); /* ISNULL */
|
|
+ testcase( i==31 ); /* NULLS */
|
|
+ testcase( i==32 ); /* SAVEPOINT */
|
|
+ testcase( i==33 ); /* INTERSECT */
|
|
+ testcase( i==34 ); /* TIES */
|
|
+ testcase( i==35 ); /* NOTNULL */
|
|
+ testcase( i==36 ); /* NOT */
|
|
+ testcase( i==37 ); /* NO */
|
|
+ testcase( i==38 ); /* NULL */
|
|
+ testcase( i==39 ); /* LIKE */
|
|
+ testcase( i==40 ); /* EXCEPT */
|
|
+ testcase( i==41 ); /* TRANSACTION */
|
|
+ testcase( i==42 ); /* ACTION */
|
|
+ testcase( i==43 ); /* ON */
|
|
+ testcase( i==44 ); /* NATURAL */
|
|
+ testcase( i==45 ); /* ALTER */
|
|
+ testcase( i==46 ); /* RAISE */
|
|
+ testcase( i==47 ); /* EXCLUSIVE */
|
|
+ testcase( i==48 ); /* EXISTS */
|
|
+ testcase( i==49 ); /* CONSTRAINT */
|
|
+ testcase( i==50 ); /* INTO */
|
|
+ testcase( i==51 ); /* OFFSET */
|
|
+ testcase( i==52 ); /* OF */
|
|
+ testcase( i==53 ); /* SET */
|
|
+ testcase( i==54 ); /* TRIGGER */
|
|
+ testcase( i==55 ); /* RANGE */
|
|
+ testcase( i==56 ); /* GENERATED */
|
|
+ testcase( i==57 ); /* DETACH */
|
|
+ testcase( i==58 ); /* HAVING */
|
|
+ testcase( i==59 ); /* GLOB */
|
|
+ testcase( i==60 ); /* BEGIN */
|
|
+ testcase( i==61 ); /* INNER */
|
|
+ testcase( i==62 ); /* REFERENCES */
|
|
+ testcase( i==63 ); /* UNIQUE */
|
|
+ testcase( i==64 ); /* QUERY */
|
|
+ testcase( i==65 ); /* WITHOUT */
|
|
+ testcase( i==66 ); /* WITH */
|
|
+ testcase( i==67 ); /* OUTER */
|
|
+ testcase( i==68 ); /* RELEASE */
|
|
+ testcase( i==69 ); /* ATTACH */
|
|
+ testcase( i==70 ); /* BETWEEN */
|
|
+ testcase( i==71 ); /* NOTHING */
|
|
+ testcase( i==72 ); /* GROUPS */
|
|
+ testcase( i==73 ); /* GROUP */
|
|
+ testcase( i==74 ); /* CASCADE */
|
|
+ testcase( i==75 ); /* ASC */
|
|
+ testcase( i==76 ); /* DEFAULT */
|
|
+ testcase( i==77 ); /* CASE */
|
|
+ testcase( i==78 ); /* COLLATE */
|
|
+ testcase( i==79 ); /* CREATE */
|
|
+ testcase( i==80 ); /* CURRENT_DATE */
|
|
+ testcase( i==81 ); /* IMMEDIATE */
|
|
+ testcase( i==82 ); /* JOIN */
|
|
+ testcase( i==83 ); /* INSERT */
|
|
+ testcase( i==84 ); /* MATCH */
|
|
+ testcase( i==85 ); /* PLAN */
|
|
+ testcase( i==86 ); /* ANALYZE */
|
|
+ testcase( i==87 ); /* PRAGMA */
|
|
+ testcase( i==88 ); /* ABORT */
|
|
+ testcase( i==89 ); /* UPDATE */
|
|
+ testcase( i==90 ); /* VALUES */
|
|
+ testcase( i==91 ); /* VIRTUAL */
|
|
+ testcase( i==92 ); /* ALWAYS */
|
|
+ testcase( i==93 ); /* WHEN */
|
|
+ testcase( i==94 ); /* WHERE */
|
|
+ testcase( i==95 ); /* RECURSIVE */
|
|
+ testcase( i==96 ); /* AFTER */
|
|
+ testcase( i==97 ); /* RENAME */
|
|
+ testcase( i==98 ); /* AND */
|
|
+ testcase( i==99 ); /* DEFERRED */
|
|
+ testcase( i==100 ); /* DISTINCT */
|
|
+ testcase( i==101 ); /* IS */
|
|
+ testcase( i==102 ); /* AUTOINCREMENT */
|
|
+ testcase( i==103 ); /* TO */
|
|
+ testcase( i==104 ); /* IN */
|
|
+ testcase( i==105 ); /* CAST */
|
|
+ testcase( i==106 ); /* COLUMN */
|
|
+ testcase( i==107 ); /* COMMIT */
|
|
+ testcase( i==108 ); /* CONFLICT */
|
|
+ testcase( i==109 ); /* CROSS */
|
|
+ testcase( i==110 ); /* CURRENT_TIMESTAMP */
|
|
+ testcase( i==111 ); /* CURRENT_TIME */
|
|
+ testcase( i==112 ); /* CURRENT */
|
|
+ testcase( i==113 ); /* PARTITION */
|
|
+ testcase( i==114 ); /* DROP */
|
|
+ testcase( i==115 ); /* PRECEDING */
|
|
+ testcase( i==116 ); /* FAIL */
|
|
+ testcase( i==117 ); /* LAST */
|
|
+ testcase( i==118 ); /* FILTER */
|
|
+ testcase( i==119 ); /* REPLACE */
|
|
+ testcase( i==120 ); /* FIRST */
|
|
+ testcase( i==121 ); /* FOLLOWING */
|
|
+ testcase( i==122 ); /* FROM */
|
|
+ testcase( i==123 ); /* FULL */
|
|
+ testcase( i==124 ); /* LIMIT */
|
|
+ testcase( i==125 ); /* IF */
|
|
+ testcase( i==126 ); /* ORDER */
|
|
+ testcase( i==127 ); /* RESTRICT */
|
|
+ testcase( i==128 ); /* OTHERS */
|
|
+ testcase( i==129 ); /* OVER */
|
|
+ testcase( i==130 ); /* RIGHT */
|
|
+ testcase( i==131 ); /* ROLLBACK */
|
|
+ testcase( i==132 ); /* ROWS */
|
|
+ testcase( i==133 ); /* ROW */
|
|
+ testcase( i==134 ); /* UNBOUNDED */
|
|
+ testcase( i==135 ); /* UNION */
|
|
+ testcase( i==136 ); /* USING */
|
|
+ testcase( i==137 ); /* VACUUM */
|
|
+ testcase( i==138 ); /* VIEW */
|
|
+ testcase( i==139 ); /* WINDOW */
|
|
+ testcase( i==140 ); /* DO */
|
|
+ testcase( i==141 ); /* BY */
|
|
+ testcase( i==142 ); /* INITIALLY */
|
|
+ testcase( i==143 ); /* ALL */
|
|
+ testcase( i==144 ); /* PRIMARY */
|
|
*pType = aKWCode[i];
|
|
break;
|
|
}
|
|
@@ -154074,7 +159041,7 @@
|
|
keywordCode((char*)z, n, &id);
|
|
return id;
|
|
}
|
|
-#define SQLITE_N_KEYWORD 140
|
|
+#define SQLITE_N_KEYWORD 145
|
|
SQLITE_API int sqlite3_keyword_name(int i,const char **pzName,int *pnName){
|
|
if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;
|
|
*pzName = zKWText + aKWOffset[i];
|
|
@@ -154512,7 +159479,7 @@
|
|
assert( zSql!=0 );
|
|
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
|
|
if( db->nVdbeActive==0 ){
|
|
- db->u1.isInterrupted = 0;
|
|
+ AtomicStore(&db->u1.isInterrupted, 0);
|
|
}
|
|
pParse->rc = SQLITE_OK;
|
|
pParse->zTail = zSql;
|
|
@@ -154557,7 +159524,7 @@
|
|
if( tokenType>=TK_SPACE ){
|
|
assert( tokenType==TK_SPACE || tokenType==TK_ILLEGAL );
|
|
#endif /* SQLITE_OMIT_WINDOWFUNC */
|
|
- if( db->u1.isInterrupted ){
|
|
+ if( AtomicLoad(&db->u1.isInterrupted) ){
|
|
pParse->rc = SQLITE_INTERRUPT;
|
|
break;
|
|
}
|
|
@@ -154701,7 +159668,7 @@
|
|
int nParen; /* Number of nested levels of parentheses */
|
|
int iStartIN; /* Start of RHS of IN operator in z[] */
|
|
int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
|
|
- int j; /* Bytes of normalized SQL generated so far */
|
|
+ u32 j; /* Bytes of normalized SQL generated so far */
|
|
sqlite3_str *pStr; /* The normalized SQL string under construction */
|
|
|
|
db = sqlite3VdbeDb(pVdbe);
|
|
@@ -154745,7 +159712,7 @@
|
|
}
|
|
case TK_RP: {
|
|
if( iStartIN>0 && nParen==nParenAtIN ){
|
|
- assert( pStr->nChar>=iStartIN );
|
|
+ assert( pStr->nChar>=(u32)iStartIN );
|
|
pStr->nChar = iStartIN+1;
|
|
sqlite3_str_append(pStr, "?,?,?", 5);
|
|
iStartIN = 0;
|
|
@@ -155224,15 +160191,78 @@
|
|
/************** End of sqliteicu.h *******************************************/
|
|
/************** Continuing where we left off in main.c ***********************/
|
|
#endif
|
|
+
|
|
+/*
|
|
+** This is an extension initializer that is a no-op and always
|
|
+** succeeds, except that it fails if the fault-simulation is set
|
|
+** to 500.
|
|
+*/
|
|
+static int sqlite3TestExtInit(sqlite3 *db){
|
|
+ (void)db;
|
|
+ return sqlite3FaultSim(500);
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+** Forward declarations of external module initializer functions
|
|
+** for modules that need them.
|
|
+*/
|
|
+#ifdef SQLITE_ENABLE_FTS1
|
|
+SQLITE_PRIVATE int sqlite3Fts1Init(sqlite3*);
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_FTS2
|
|
+SQLITE_PRIVATE int sqlite3Fts2Init(sqlite3*);
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_FTS5
|
|
+SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
|
|
+#endif
|
|
#ifdef SQLITE_ENABLE_JSON1
|
|
SQLITE_PRIVATE int sqlite3Json1Init(sqlite3*);
|
|
#endif
|
|
#ifdef SQLITE_ENABLE_STMTVTAB
|
|
SQLITE_PRIVATE int sqlite3StmtVtabInit(sqlite3*);
|
|
#endif
|
|
+
|
|
+/*
|
|
+** An array of pointers to extension initializer functions for
|
|
+** built-in extensions.
|
|
+*/
|
|
+static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
|
|
+#ifdef SQLITE_ENABLE_FTS1
|
|
+ sqlite3Fts1Init,
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_FTS2
|
|
+ sqlite3Fts2Init,
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_FTS3
|
|
+ sqlite3Fts3Init,
|
|
+#endif
|
|
#ifdef SQLITE_ENABLE_FTS5
|
|
-SQLITE_PRIVATE int sqlite3Fts5Init(sqlite3*);
|
|
+ sqlite3Fts5Init,
|
|
+#endif
|
|
+#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
|
|
+ sqlite3IcuInit,
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_RTREE
|
|
+ sqlite3RtreeInit,
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_DBPAGE_VTAB
|
|
+ sqlite3DbpageRegister,
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB
|
|
+ sqlite3DbstatRegister,
|
|
+#endif
|
|
+ sqlite3TestExtInit,
|
|
+#ifdef SQLITE_ENABLE_JSON1
|
|
+ sqlite3Json1Init,
|
|
+#endif
|
|
+#ifdef SQLITE_ENABLE_STMTVTAB
|
|
+ sqlite3StmtVtabInit,
|
|
#endif
|
|
+#ifdef SQLITE_ENABLE_BYTECODE_VTAB
|
|
+ sqlite3VdbeBytecodeVtabInit,
|
|
+#endif
|
|
+};
|
|
|
|
#ifndef SQLITE_AMALGAMATION
|
|
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
|
|
@@ -155360,7 +160390,10 @@
|
|
** must be complete. So isInit must not be set until the very end
|
|
** of this routine.
|
|
*/
|
|
- if( sqlite3GlobalConfig.isInit ) return SQLITE_OK;
|
|
+ if( sqlite3GlobalConfig.isInit ){
|
|
+ sqlite3MemoryBarrier();
|
|
+ return SQLITE_OK;
|
|
+ }
|
|
|
|
/* Make sure the mutex subsystem is initialized. If unable to
|
|
** initialize the mutex subsystem, return early with the error.
|
|
@@ -155446,6 +160479,7 @@
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3PCacheBufferSetup( sqlite3GlobalConfig.pPage,
|
|
sqlite3GlobalConfig.szPage, sqlite3GlobalConfig.nPage);
|
|
+ sqlite3MemoryBarrier();
|
|
sqlite3GlobalConfig.isInit = 1;
|
|
#ifdef SQLITE_EXTRA_INIT
|
|
bRunExtraInit = 1;
|
|
@@ -155882,6 +160916,9 @@
|
|
static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
|
|
#ifndef SQLITE_OMIT_LOOKASIDE
|
|
void *pStart;
|
|
+ sqlite3_int64 szAlloc = sz*(sqlite3_int64)cnt;
|
|
+ int nBig; /* Number of full-size slots */
|
|
+ int nSm; /* Number smaller LOOKASIDE_SMALL-byte slots */
|
|
|
|
if( sqlite3LookasideUsed(db,0)>0 ){
|
|
return SQLITE_BUSY;
|
|
@@ -155904,37 +160941,71 @@
|
|
pStart = 0;
|
|
}else if( pBuf==0 ){
|
|
sqlite3BeginBenignMalloc();
|
|
- pStart = sqlite3Malloc( sz*(sqlite3_int64)cnt ); /* IMP: R-61949-35727 */
|
|
+ pStart = sqlite3Malloc( szAlloc ); /* IMP: R-61949-35727 */
|
|
sqlite3EndBenignMalloc();
|
|
- if( pStart ) cnt = sqlite3MallocSize(pStart)/sz;
|
|
+ if( pStart ) szAlloc = sqlite3MallocSize(pStart);
|
|
}else{
|
|
pStart = pBuf;
|
|
}
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ if( sz>=LOOKASIDE_SMALL*3 ){
|
|
+ nBig = szAlloc/(3*LOOKASIDE_SMALL+sz);
|
|
+ nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
|
|
+ }else if( sz>=LOOKASIDE_SMALL*2 ){
|
|
+ nBig = szAlloc/(LOOKASIDE_SMALL+sz);
|
|
+ nSm = (szAlloc - sz*nBig)/LOOKASIDE_SMALL;
|
|
+ }else
|
|
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
+ if( sz>0 ){
|
|
+ nBig = szAlloc/sz;
|
|
+ nSm = 0;
|
|
+ }else{
|
|
+ nBig = nSm = 0;
|
|
+ }
|
|
db->lookaside.pStart = pStart;
|
|
db->lookaside.pInit = 0;
|
|
db->lookaside.pFree = 0;
|
|
db->lookaside.sz = (u16)sz;
|
|
+ db->lookaside.szTrue = (u16)sz;
|
|
if( pStart ){
|
|
int i;
|
|
LookasideSlot *p;
|
|
assert( sz > (int)sizeof(LookasideSlot*) );
|
|
- db->lookaside.nSlot = cnt;
|
|
p = (LookasideSlot*)pStart;
|
|
- for(i=cnt-1; i>=0; i--){
|
|
+ for(i=0; i<nBig; i++){
|
|
p->pNext = db->lookaside.pInit;
|
|
db->lookaside.pInit = p;
|
|
p = (LookasideSlot*)&((u8*)p)[sz];
|
|
}
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ db->lookaside.pSmallInit = 0;
|
|
+ db->lookaside.pSmallFree = 0;
|
|
+ db->lookaside.pMiddle = p;
|
|
+ for(i=0; i<nSm; i++){
|
|
+ p->pNext = db->lookaside.pSmallInit;
|
|
+ db->lookaside.pSmallInit = p;
|
|
+ p = (LookasideSlot*)&((u8*)p)[LOOKASIDE_SMALL];
|
|
+ }
|
|
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
+ assert( ((uptr)p)<=szAlloc + (uptr)pStart );
|
|
db->lookaside.pEnd = p;
|
|
db->lookaside.bDisable = 0;
|
|
db->lookaside.bMalloced = pBuf==0 ?1:0;
|
|
+ db->lookaside.nSlot = nBig+nSm;
|
|
}else{
|
|
db->lookaside.pStart = db;
|
|
+#ifndef SQLITE_OMIT_TWOSIZE_LOOKASIDE
|
|
+ db->lookaside.pSmallInit = 0;
|
|
+ db->lookaside.pSmallFree = 0;
|
|
+ db->lookaside.pMiddle = db;
|
|
+#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
|
db->lookaside.pEnd = db;
|
|
db->lookaside.bDisable = 1;
|
|
+ db->lookaside.sz = 0;
|
|
db->lookaside.bMalloced = 0;
|
|
db->lookaside.nSlot = 0;
|
|
}
|
|
+ assert( sqlite3LookasideUsed(db,0)==0 );
|
|
#endif /* SQLITE_OMIT_LOOKASIDE */
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -156035,6 +161106,7 @@
|
|
} aFlagOp[] = {
|
|
{ SQLITE_DBCONFIG_ENABLE_FKEY, SQLITE_ForeignKeys },
|
|
{ SQLITE_DBCONFIG_ENABLE_TRIGGER, SQLITE_EnableTrigger },
|
|
+ { SQLITE_DBCONFIG_ENABLE_VIEW, SQLITE_EnableView },
|
|
{ SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER, SQLITE_Fts3Tokenizer },
|
|
{ SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION, SQLITE_LoadExtension },
|
|
{ SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
|
|
@@ -156047,6 +161119,8 @@
|
|
{ SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter },
|
|
{ SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL },
|
|
{ SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML },
|
|
+ { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, SQLITE_LegacyFileFmt },
|
|
+ { SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema },
|
|
};
|
|
unsigned int i;
|
|
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
|
|
@@ -156434,11 +161508,8 @@
|
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
|
for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
|
|
Module *pMod = (Module *)sqliteHashData(i);
|
|
- if( pMod->xDestroy ){
|
|
- pMod->xDestroy(pMod->pAux);
|
|
- }
|
|
sqlite3VtabEponymousTableClear(db, pMod);
|
|
- sqlite3DbFree(db, pMod);
|
|
+ sqlite3VtabModuleUnref(db, pMod);
|
|
}
|
|
sqlite3HashClear(&db->aModule);
|
|
#endif
|
|
@@ -156588,6 +161659,7 @@
|
|
case SQLITE_CANTOPEN_ISDIR: zName = "SQLITE_CANTOPEN_ISDIR"; break;
|
|
case SQLITE_CANTOPEN_FULLPATH: zName = "SQLITE_CANTOPEN_FULLPATH"; break;
|
|
case SQLITE_CANTOPEN_CONVPATH: zName = "SQLITE_CANTOPEN_CONVPATH"; break;
|
|
+ case SQLITE_CANTOPEN_SYMLINK: zName = "SQLITE_CANTOPEN_SYMLINK"; break;
|
|
case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
|
|
case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
|
|
case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
|
|
@@ -156709,8 +161781,7 @@
|
|
*/
|
|
static int sqliteDefaultBusyCallback(
|
|
void *ptr, /* Database connection */
|
|
- int count, /* Number of times table has been busy */
|
|
- sqlite3_file *pFile /* The file on which the lock occurred */
|
|
+ int count /* Number of times table has been busy */
|
|
){
|
|
#if SQLITE_OS_WIN || HAVE_USLEEP
|
|
/* This case is for systems that have support for sleeping for fractions of
|
|
@@ -156724,19 +161795,6 @@
|
|
int tmout = db->busyTimeout;
|
|
int delay, prior;
|
|
|
|
-#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
|
|
- if( sqlite3OsFileControl(pFile,SQLITE_FCNTL_LOCK_TIMEOUT,&tmout)==SQLITE_OK ){
|
|
- if( count ){
|
|
- tmout = 0;
|
|
- sqlite3OsFileControl(pFile, SQLITE_FCNTL_LOCK_TIMEOUT, &tmout);
|
|
- return 0;
|
|
- }else{
|
|
- return 1;
|
|
- }
|
|
- }
|
|
-#else
|
|
- UNUSED_PARAMETER(pFile);
|
|
-#endif
|
|
assert( count>=0 );
|
|
if( count < NDELAY ){
|
|
delay = delays[count];
|
|
@@ -156756,7 +161814,6 @@
|
|
** must be done in increments of whole seconds */
|
|
sqlite3 *db = (sqlite3 *)ptr;
|
|
int tmout = ((sqlite3 *)ptr)->busyTimeout;
|
|
- UNUSED_PARAMETER(pFile);
|
|
if( (count+1)*1000 > tmout ){
|
|
return 0;
|
|
}
|
|
@@ -156774,19 +161831,10 @@
|
|
** If this routine returns non-zero, the lock is retried. If it
|
|
** returns 0, the operation aborts with an SQLITE_BUSY error.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p, sqlite3_file *pFile){
|
|
+SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
|
|
int rc;
|
|
if( p->xBusyHandler==0 || p->nBusy<0 ) return 0;
|
|
- if( p->bExtraFileArg ){
|
|
- /* Add an extra parameter with the pFile pointer to the end of the
|
|
- ** callback argument list */
|
|
- int (*xTra)(void*,int,sqlite3_file*);
|
|
- xTra = (int(*)(void*,int,sqlite3_file*))p->xBusyHandler;
|
|
- rc = xTra(p->pBusyArg, p->nBusy, pFile);
|
|
- }else{
|
|
- /* Legacy style busy handler callback */
|
|
- rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
|
|
- }
|
|
+ rc = p->xBusyHandler(p->pBusyArg, p->nBusy);
|
|
if( rc==0 ){
|
|
p->nBusy = -1;
|
|
}else{
|
|
@@ -156811,7 +161859,6 @@
|
|
db->busyHandler.xBusyHandler = xBusy;
|
|
db->busyHandler.pBusyArg = pArg;
|
|
db->busyHandler.nBusy = 0;
|
|
- db->busyHandler.bExtraFileArg = 0;
|
|
db->busyTimeout = 0;
|
|
sqlite3_mutex_leave(db->mutex);
|
|
return SQLITE_OK;
|
|
@@ -156862,7 +161909,6 @@
|
|
sqlite3_busy_handler(db, (int(*)(void*,int))sqliteDefaultBusyCallback,
|
|
(void*)db);
|
|
db->busyTimeout = ms;
|
|
- db->busyHandler.bExtraFileArg = 1;
|
|
}else{
|
|
sqlite3_busy_handler(db, 0, 0);
|
|
}
|
|
@@ -156879,7 +161925,7 @@
|
|
return;
|
|
}
|
|
#endif
|
|
- db->u1.isInterrupted = 1;
|
|
+ AtomicStore(&db->u1.isInterrupted, 1);
|
|
}
|
|
|
|
|
|
@@ -156919,8 +161965,16 @@
|
|
}
|
|
|
|
assert( SQLITE_FUNC_CONSTANT==SQLITE_DETERMINISTIC );
|
|
- extraFlags = enc & SQLITE_DETERMINISTIC;
|
|
+ assert( SQLITE_FUNC_DIRECT==SQLITE_DIRECTONLY );
|
|
+ extraFlags = enc & (SQLITE_DETERMINISTIC|SQLITE_DIRECTONLY|
|
|
+ SQLITE_SUBTYPE|SQLITE_INNOCUOUS);
|
|
enc &= (SQLITE_FUNC_ENCMASK|SQLITE_ANY);
|
|
+
|
|
+ /* The SQLITE_INNOCUOUS flag is the same bit as SQLITE_FUNC_UNSAFE. But
|
|
+ ** the meaning is inverted. So flip the bit. */
|
|
+ assert( SQLITE_FUNC_UNSAFE==SQLITE_INNOCUOUS );
|
|
+ extraFlags ^= SQLITE_FUNC_UNSAFE;
|
|
+
|
|
|
|
#ifndef SQLITE_OMIT_UTF16
|
|
/* If SQLITE_UTF16 is specified as the encoding type, transform this
|
|
@@ -156934,11 +161988,13 @@
|
|
enc = SQLITE_UTF16NATIVE;
|
|
}else if( enc==SQLITE_ANY ){
|
|
int rc;
|
|
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF8|extraFlags,
|
|
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
|
+ (SQLITE_UTF8|extraFlags)^SQLITE_FUNC_UNSAFE,
|
|
pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
|
if( rc==SQLITE_OK ){
|
|
- rc = sqlite3CreateFunc(db, zFunctionName, nArg, SQLITE_UTF16LE|extraFlags,
|
|
- pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
|
+ rc = sqlite3CreateFunc(db, zFunctionName, nArg,
|
|
+ (SQLITE_UTF16LE|extraFlags)^SQLITE_FUNC_UNSAFE,
|
|
+ pUserData, xSFunc, xStep, xFinal, xValue, xInverse, pDestructor);
|
|
}
|
|
if( rc!=SQLITE_OK ){
|
|
return rc;
|
|
@@ -156982,6 +162038,7 @@
|
|
p->u.pDestructor = pDestructor;
|
|
p->funcFlags = (p->funcFlags & SQLITE_FUNC_ENCMASK) | extraFlags;
|
|
testcase( p->funcFlags & SQLITE_DETERMINISTIC );
|
|
+ testcase( p->funcFlags & SQLITE_DIRECTONLY );
|
|
p->xSFunc = xSFunc ? xSFunc : xStep;
|
|
p->xFinalize = xFinal;
|
|
p->xValue = xValue;
|
|
@@ -157490,7 +162547,7 @@
|
|
/* If there are no active statements, clear the interrupt flag at this
|
|
** point. */
|
|
if( db->nVdbeActive==0 ){
|
|
- db->u1.isInterrupted = 0;
|
|
+ AtomicStore(&db->u1.isInterrupted, 0);
|
|
}
|
|
|
|
sqlite3_mutex_leave(db->mutex);
|
|
@@ -157900,9 +162957,11 @@
|
|
**
|
|
** If successful, SQLITE_OK is returned. In this case *ppVfs is set to point to
|
|
** the VFS that should be used to open the database file. *pzFile is set to
|
|
-** point to a buffer containing the name of the file to open. It is the
|
|
-** responsibility of the caller to eventually call sqlite3_free() to release
|
|
-** this buffer.
|
|
+** point to a buffer containing the name of the file to open. The value
|
|
+** stored in *pzFile is a database name acceptable to sqlite3_uri_parameter()
|
|
+** and is in the same format as names created using sqlite3_create_filename().
|
|
+** The caller must invoke sqlite3_free_filename() (not sqlite3_free()!) on
|
|
+** the value returned in *pzFile to avoid a memory leak.
|
|
**
|
|
** If an error occurs, then an SQLite error code is returned and *pzErrMsg
|
|
** may be set to point to a buffer containing an English language error
|
|
@@ -157934,7 +162993,7 @@
|
|
int eState; /* Parser state when parsing URI */
|
|
int iIn; /* Input character index */
|
|
int iOut = 0; /* Output character index */
|
|
- u64 nByte = nUri+2; /* Bytes of space to allocate */
|
|
+ u64 nByte = nUri+8; /* Bytes of space to allocate */
|
|
|
|
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
|
|
** method that there may be extra parameters following the file-name. */
|
|
@@ -157944,6 +163003,9 @@
|
|
zFile = sqlite3_malloc64(nByte);
|
|
if( !zFile ) return SQLITE_NOMEM_BKPT;
|
|
|
|
+ memset(zFile, 0, 4); /* 4-byte of 0x00 is the start of DB name marker */
|
|
+ zFile += 4;
|
|
+
|
|
iIn = 5;
|
|
#ifdef SQLITE_ALLOW_URI_AUTHORITY
|
|
if( strncmp(zUri+5, "///", 3)==0 ){
|
|
@@ -158033,8 +163095,7 @@
|
|
zFile[iOut++] = c;
|
|
}
|
|
if( eState==1 ) zFile[iOut++] = '\0';
|
|
- zFile[iOut++] = '\0';
|
|
- zFile[iOut++] = '\0';
|
|
+ memset(zFile+iOut, 0, 4); /* end-of-options + empty journal filenames */
|
|
|
|
/* Check if there were any options specified that should be interpreted
|
|
** here. Options that are interpreted here include "vfs" and those that
|
|
@@ -158114,13 +163175,14 @@
|
|
}
|
|
|
|
}else{
|
|
- zFile = sqlite3_malloc64(nUri+2);
|
|
+ zFile = sqlite3_malloc64(nUri+8);
|
|
if( !zFile ) return SQLITE_NOMEM_BKPT;
|
|
+ memset(zFile, 0, 4);
|
|
+ zFile += 4;
|
|
if( nUri ){
|
|
memcpy(zFile, zUri, nUri);
|
|
}
|
|
- zFile[nUri] = '\0';
|
|
- zFile[nUri+1] = '\0';
|
|
+ memset(zFile+nUri, 0, 4);
|
|
flags &= ~SQLITE_OPEN_URI;
|
|
}
|
|
|
|
@@ -158131,7 +163193,7 @@
|
|
}
|
|
parse_uri_out:
|
|
if( rc!=SQLITE_OK ){
|
|
- sqlite3_free(zFile);
|
|
+ sqlite3_free_filename(zFile);
|
|
zFile = 0;
|
|
}
|
|
*pFlags = flags;
|
|
@@ -158139,39 +163201,21 @@
|
|
return rc;
|
|
}
|
|
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
/*
|
|
-** Process URI filename query parameters relevant to the SQLite Encryption
|
|
-** Extension. Return true if any of the relevant query parameters are
|
|
-** seen and return false if not.
|
|
+** This routine does the core work of extracting URI parameters from a
|
|
+** database filename for the sqlite3_uri_parameter() interface.
|
|
*/
|
|
-SQLITE_PRIVATE int sqlite3CodecQueryParameters(
|
|
- sqlite3 *db, /* Database connection */
|
|
- const char *zDb, /* Which schema is being created/attached */
|
|
- const char *zUri /* URI filename */
|
|
-){
|
|
- const char *zKey;
|
|
- if( (zKey = sqlite3_uri_parameter(zUri, "hexkey"))!=0 && zKey[0] ){
|
|
- u8 iByte;
|
|
- int i;
|
|
- char zDecoded[40];
|
|
- for(i=0, iByte=0; i<sizeof(zDecoded)*2 && sqlite3Isxdigit(zKey[i]); i++){
|
|
- iByte = (iByte<<4) + sqlite3HexToInt(zKey[i]);
|
|
- if( (i&1)!=0 ) zDecoded[i/2] = iByte;
|
|
- }
|
|
- sqlite3_key_v2(db, zDb, zDecoded, i/2);
|
|
- return 1;
|
|
- }else if( (zKey = sqlite3_uri_parameter(zUri, "key"))!=0 ){
|
|
- sqlite3_key_v2(db, zDb, zKey, sqlite3Strlen30(zKey));
|
|
- return 1;
|
|
- }else if( (zKey = sqlite3_uri_parameter(zUri, "textkey"))!=0 ){
|
|
- sqlite3_key_v2(db, zDb, zKey, -1);
|
|
- return 1;
|
|
- }else{
|
|
- return 0;
|
|
+static const char *uriParameter(const char *zFilename, const char *zParam){
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
+ while( zFilename[0] ){
|
|
+ int x = strcmp(zFilename, zParam);
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
+ if( x==0 ) return zFilename;
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
}
|
|
+ return 0;
|
|
}
|
|
-#endif
|
|
+
|
|
|
|
|
|
/*
|
|
@@ -158190,6 +163234,7 @@
|
|
int isThreadsafe; /* True for threadsafe connections */
|
|
char *zOpen = 0; /* Filename argument to pass to BtreeOpen() */
|
|
char *zErrMsg = 0; /* Error message from sqlite3ParseUri() */
|
|
+ int i; /* Loop counter */
|
|
|
|
#ifdef SQLITE_ENABLE_API_ARMOR
|
|
if( ppDb==0 ) return SQLITE_MISUSE_BKPT;
|
|
@@ -158263,6 +163308,7 @@
|
|
db->magic = SQLITE_MAGIC_BUSY;
|
|
db->aDb = db->aDbStatic;
|
|
db->lookaside.bDisable = 1;
|
|
+ db->lookaside.sz = 0;
|
|
|
|
assert( sizeof(db->aLimit)==sizeof(aHardLimit) );
|
|
memcpy(db->aLimit, aHardLimit, sizeof(db->aLimit));
|
|
@@ -158274,8 +163320,11 @@
|
|
db->nMaxSorterMmap = 0x7FFFFFFF;
|
|
db->flags |= SQLITE_ShortColNames
|
|
| SQLITE_EnableTrigger
|
|
+ | SQLITE_EnableView
|
|
| SQLITE_CacheSpill
|
|
-
|
|
+#if !defined(SQLITE_TRUSTED_SCHEMA) || SQLITE_TRUSTED_SCHEMA+0!=0
|
|
+ | SQLITE_TrustedSchema
|
|
+#endif
|
|
/* The SQLITE_DQS compile-time option determines the default settings
|
|
** for SQLITE_DBCONFIG_DQS_DDL and SQLITE_DBCONFIG_DQS_DML.
|
|
**
|
|
@@ -158333,6 +163382,9 @@
|
|
#endif
|
|
#if defined(SQLITE_DEFAULT_DEFENSIVE)
|
|
| SQLITE_Defensive
|
|
+#endif
|
|
+#if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE)
|
|
+ | SQLITE_LegacyAlter
|
|
#endif
|
|
;
|
|
sqlite3HashInit(&db->aCollSeq);
|
|
@@ -158355,11 +163407,6 @@
|
|
if( db->mallocFailed ){
|
|
goto opendb_out;
|
|
}
|
|
- /* EVIDENCE-OF: R-08308-17224 The default collating function for all
|
|
- ** strings is BINARY.
|
|
- */
|
|
- db->pDfltColl = sqlite3FindCollSeq(db, SQLITE_UTF8, sqlite3StrBINARY, 0);
|
|
- assert( db->pDfltColl!=0 );
|
|
|
|
/* Parse the filename/URI argument
|
|
**
|
|
@@ -158381,7 +163428,7 @@
|
|
testcase( (1<<(flags&7))==0x04 ); /* READWRITE */
|
|
testcase( (1<<(flags&7))==0x40 ); /* READWRITE | CREATE */
|
|
if( ((1<<(flags&7)) & 0x46)==0 ){
|
|
- rc = SQLITE_MISUSE_BKPT; /* IMP: R-65497-44594 */
|
|
+ rc = SQLITE_MISUSE_BKPT; /* IMP: R-18321-05872 */
|
|
}else{
|
|
rc = sqlite3ParseUri(zVfs, zFilename, &flags, &db->pVfs, &zOpen, &zErrMsg);
|
|
}
|
|
@@ -158404,7 +163451,9 @@
|
|
}
|
|
sqlite3BtreeEnter(db->aDb[0].pBt);
|
|
db->aDb[0].pSchema = sqlite3SchemaGet(db, db->aDb[0].pBt);
|
|
- if( !db->mallocFailed ) ENC(db) = SCHEMA_ENC(db);
|
|
+ if( !db->mallocFailed ){
|
|
+ sqlite3SetTextEncoding(db, SCHEMA_ENC(db));
|
|
+ }
|
|
sqlite3BtreeLeave(db->aDb[0].pBt);
|
|
db->aDb[1].pSchema = sqlite3SchemaGet(db, 0);
|
|
|
|
@@ -158429,14 +163478,11 @@
|
|
sqlite3RegisterPerConnectionBuiltinFunctions(db);
|
|
rc = sqlite3_errcode(db);
|
|
|
|
-#ifdef SQLITE_ENABLE_FTS5
|
|
- /* Register any built-in FTS5 module before loading the automatic
|
|
- ** extensions. This allows automatic extensions to register FTS5
|
|
- ** tokenizers and auxiliary functions. */
|
|
- if( !db->mallocFailed && rc==SQLITE_OK ){
|
|
- rc = sqlite3Fts5Init(db);
|
|
+
|
|
+ /* Load compiled-in extensions */
|
|
+ for(i=0; rc==SQLITE_OK && i<ArraySize(sqlite3BuiltinExtensions); i++){
|
|
+ rc = sqlite3BuiltinExtensions[i](db);
|
|
}
|
|
-#endif
|
|
|
|
/* Load automatic extensions - extensions that have been registered
|
|
** using the sqlite3_automatic_extension() API.
|
|
@@ -158449,60 +163495,11 @@
|
|
}
|
|
}
|
|
|
|
-#ifdef SQLITE_ENABLE_FTS1
|
|
- if( !db->mallocFailed ){
|
|
- extern int sqlite3Fts1Init(sqlite3*);
|
|
- rc = sqlite3Fts1Init(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_FTS2
|
|
- if( !db->mallocFailed && rc==SQLITE_OK ){
|
|
- extern int sqlite3Fts2Init(sqlite3*);
|
|
- rc = sqlite3Fts2Init(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_FTS3 /* automatically defined by SQLITE_ENABLE_FTS4 */
|
|
- if( !db->mallocFailed && rc==SQLITE_OK ){
|
|
- rc = sqlite3Fts3Init(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#if defined(SQLITE_ENABLE_ICU) || defined(SQLITE_ENABLE_ICU_COLLATIONS)
|
|
- if( !db->mallocFailed && rc==SQLITE_OK ){
|
|
- rc = sqlite3IcuInit(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_RTREE
|
|
- if( !db->mallocFailed && rc==SQLITE_OK){
|
|
- rc = sqlite3RtreeInit(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_DBPAGE_VTAB
|
|
- if( !db->mallocFailed && rc==SQLITE_OK){
|
|
- rc = sqlite3DbpageRegister(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_DBSTAT_VTAB
|
|
- if( !db->mallocFailed && rc==SQLITE_OK){
|
|
- rc = sqlite3DbstatRegister(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_JSON1
|
|
- if( !db->mallocFailed && rc==SQLITE_OK){
|
|
- rc = sqlite3Json1Init(db);
|
|
- }
|
|
-#endif
|
|
-
|
|
-#ifdef SQLITE_ENABLE_STMTVTAB
|
|
- if( !db->mallocFailed && rc==SQLITE_OK){
|
|
- rc = sqlite3StmtVtabInit(db);
|
|
- }
|
|
+#ifdef SQLITE_ENABLE_INTERNAL_FUNCTIONS
|
|
+ /* Testing use only!!! The -DSQLITE_ENABLE_INTERNAL_FUNCTIONS=1 compile-time
|
|
+ ** option gives access to internal functions by default.
|
|
+ ** Testing use only!!! */
|
|
+ db->mDbFlags |= DBFLAG_InternalFunc;
|
|
#endif
|
|
|
|
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
|
|
@@ -158545,10 +163542,7 @@
|
|
sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0);
|
|
}
|
|
#endif
|
|
-#if defined(SQLITE_HAS_CODEC)
|
|
- if( rc==SQLITE_OK ) sqlite3CodecQueryParameters(db, 0, zOpen);
|
|
-#endif
|
|
- sqlite3_free(zOpen);
|
|
+ sqlite3_free_filename(zOpen);
|
|
return rc & 0xff;
|
|
}
|
|
|
|
@@ -158775,13 +163769,15 @@
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
return sqlite3ReportError(SQLITE_CANTOPEN, lineno, "cannot open file");
|
|
}
|
|
-#ifdef SQLITE_DEBUG
|
|
+#if defined(SQLITE_DEBUG) || defined(SQLITE_ENABLE_CORRUPT_PGNO)
|
|
SQLITE_PRIVATE int sqlite3CorruptPgnoError(int lineno, Pgno pgno){
|
|
char zMsg[100];
|
|
sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno);
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
return sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg);
|
|
}
|
|
+#endif
|
|
+#ifdef SQLITE_DEBUG
|
|
SQLITE_PRIVATE int sqlite3NomemError(int lineno){
|
|
testcase( sqlite3GlobalConfig.xLog!=0 );
|
|
return sqlite3ReportError(SQLITE_NOMEM, lineno, "OOM");
|
|
@@ -158984,6 +163980,13 @@
|
|
}else if( op==SQLITE_FCNTL_DATA_VERSION ){
|
|
*(unsigned int*)pArg = sqlite3PagerDataVersion(pPager);
|
|
rc = SQLITE_OK;
|
|
+ }else if( op==SQLITE_FCNTL_RESERVE_BYTES ){
|
|
+ int iNew = *(int*)pArg;
|
|
+ *(int*)pArg = sqlite3BtreeGetRequestedReserve(pBtree);
|
|
+ if( iNew>=0 && iNew<=255 ){
|
|
+ sqlite3BtreeSetPageSize(pBtree, 0, iNew, 0);
|
|
+ }
|
|
+ rc = SQLITE_OK;
|
|
}else{
|
|
rc = sqlite3OsFileControl(fd, op, pArg);
|
|
}
|
|
@@ -159023,15 +164026,38 @@
|
|
break;
|
|
}
|
|
|
|
- /*
|
|
- ** Reset the PRNG back to its uninitialized state. The next call
|
|
- ** to sqlite3_randomness() will reseed the PRNG using a single call
|
|
- ** to the xRandomness method of the default VFS.
|
|
+ /* sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SEED, int x, sqlite3 *db);
|
|
+ **
|
|
+ ** Control the seed for the pseudo-random number generator (PRNG) that
|
|
+ ** is built into SQLite. Cases:
|
|
+ **
|
|
+ ** x!=0 && db!=0 Seed the PRNG to the current value of the
|
|
+ ** schema cookie in the main database for db, or
|
|
+ ** x if the schema cookie is zero. This case
|
|
+ ** is convenient to use with database fuzzers
|
|
+ ** as it allows the fuzzer some control over the
|
|
+ ** the PRNG seed.
|
|
+ **
|
|
+ ** x!=0 && db==0 Seed the PRNG to the value of x.
|
|
+ **
|
|
+ ** x==0 && db==0 Revert to default behavior of using the
|
|
+ ** xRandomness method on the primary VFS.
|
|
+ **
|
|
+ ** This test-control also resets the PRNG so that the new seed will
|
|
+ ** be used for the next call to sqlite3_randomness().
|
|
*/
|
|
- case SQLITE_TESTCTRL_PRNG_RESET: {
|
|
+#ifndef SQLITE_OMIT_WSD
|
|
+ case SQLITE_TESTCTRL_PRNG_SEED: {
|
|
+ int x = va_arg(ap, int);
|
|
+ int y;
|
|
+ sqlite3 *db = va_arg(ap, sqlite3*);
|
|
+ assert( db==0 || db->aDb[0].pSchema!=0 );
|
|
+ if( db && (y = db->aDb[0].pSchema->schema_cookie)!=0 ){ x = y; }
|
|
+ sqlite3Config.iPrngSeed = x;
|
|
sqlite3_randomness(0,0);
|
|
break;
|
|
}
|
|
+#endif
|
|
|
|
/*
|
|
** sqlite3_test_control(BITVEC_TEST, size, program)
|
|
@@ -159177,20 +164203,6 @@
|
|
break;
|
|
}
|
|
|
|
- /* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
|
|
- **
|
|
- ** Set the nReserve size to N for the main database on the database
|
|
- ** connection db.
|
|
- */
|
|
- case SQLITE_TESTCTRL_RESERVE: {
|
|
- sqlite3 *db = va_arg(ap, sqlite3*);
|
|
- int x = va_arg(ap,int);
|
|
- sqlite3_mutex_enter(db->mutex);
|
|
- sqlite3BtreeSetPageSize(db->aDb[0].pBt, 0, x, 0);
|
|
- sqlite3_mutex_leave(db->mutex);
|
|
- break;
|
|
- }
|
|
-
|
|
/* sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, sqlite3 *db, int N)
|
|
**
|
|
** Enable or disable various optimizations for testing purposes. The
|
|
@@ -159216,15 +164228,14 @@
|
|
break;
|
|
}
|
|
|
|
- /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCS, int onoff);
|
|
+ /* sqlite3_test_control(SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, sqlite3*);
|
|
**
|
|
- ** If parameter onoff is non-zero, internal-use-only SQL functions
|
|
- ** are visible to ordinary SQL. This is useful for testing but is
|
|
- ** unsafe because invalid parameters to those internal-use-only functions
|
|
- ** can result in crashes or segfaults.
|
|
+ ** Toggle the ability to use internal functions on or off for
|
|
+ ** the database connection given in the argument.
|
|
*/
|
|
case SQLITE_TESTCTRL_INTERNAL_FUNCTIONS: {
|
|
- sqlite3GlobalConfig.bInternalFunctions = va_arg(ap, int);
|
|
+ sqlite3 *db = va_arg(ap, sqlite3*);
|
|
+ db->mDbFlags ^= DBFLAG_InternalFunc;
|
|
break;
|
|
}
|
|
|
|
@@ -159241,6 +164252,17 @@
|
|
break;
|
|
}
|
|
|
|
+ /* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int);
|
|
+ **
|
|
+ ** Set or clear a flag that causes SQLite to verify that type, name,
|
|
+ ** and tbl_name fields of the sqlite_master table. This is normally
|
|
+ ** on, but it is sometimes useful to turn it off for testing.
|
|
+ */
|
|
+ case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: {
|
|
+ sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int);
|
|
+ break;
|
|
+ }
|
|
+
|
|
/* Set the threshold at which OP_Once counters reset back to zero.
|
|
** By default this is 0x7ffffffe (over 2 billion), but that value is
|
|
** too big to test in a reasonable amount of time, so this control is
|
|
@@ -159349,6 +164371,83 @@
|
|
return rc;
|
|
}
|
|
|
|
+/*
|
|
+** The Pager stores the Database filename, Journal filename, and WAL filename
|
|
+** consecutively in memory, in that order. The database filename is prefixed
|
|
+** by four zero bytes. Locate the start of the database filename by searching
|
|
+** backwards for the first byte following four consecutive zero bytes.
|
|
+**
|
|
+** This only works if the filename passed in was obtained from the Pager.
|
|
+*/
|
|
+static const char *databaseName(const char *zName){
|
|
+ while( zName[-1]!=0 || zName[-2]!=0 || zName[-3]!=0 || zName[-4]!=0 ){
|
|
+ zName--;
|
|
+ }
|
|
+ return zName;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Append text z[] to the end of p[]. Return a pointer to the first
|
|
+** character after then zero terminator on the new text in p[].
|
|
+*/
|
|
+static char *appendText(char *p, const char *z){
|
|
+ size_t n = strlen(z);
|
|
+ memcpy(p, z, n+1);
|
|
+ return p+n+1;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Allocate memory to hold names for a database, journal file, WAL file,
|
|
+** and query parameters. The pointer returned is valid for use by
|
|
+** sqlite3_filename_database() and sqlite3_uri_parameter() and related
|
|
+** functions.
|
|
+**
|
|
+** Memory layout must be compatible with that generated by the pager
|
|
+** and expected by sqlite3_uri_parameter() and databaseName().
|
|
+*/
|
|
+SQLITE_API char *sqlite3_create_filename(
|
|
+ const char *zDatabase,
|
|
+ const char *zJournal,
|
|
+ const char *zWal,
|
|
+ int nParam,
|
|
+ const char **azParam
|
|
+){
|
|
+ sqlite3_int64 nByte;
|
|
+ int i;
|
|
+ char *pResult, *p;
|
|
+ nByte = strlen(zDatabase) + strlen(zJournal) + strlen(zWal) + 10;
|
|
+ for(i=0; i<nParam*2; i++){
|
|
+ nByte += strlen(azParam[i])+1;
|
|
+ }
|
|
+ pResult = p = sqlite3_malloc64( nByte );
|
|
+ if( p==0 ) return 0;
|
|
+ memset(p, 0, 4);
|
|
+ p += 4;
|
|
+ p = appendText(p, zDatabase);
|
|
+ for(i=0; i<nParam*2; i++){
|
|
+ p = appendText(p, azParam[i]);
|
|
+ }
|
|
+ *(p++) = 0;
|
|
+ p = appendText(p, zJournal);
|
|
+ p = appendText(p, zWal);
|
|
+ *(p++) = 0;
|
|
+ *(p++) = 0;
|
|
+ assert( (sqlite3_int64)(p - pResult)==nByte );
|
|
+ return pResult + 4;
|
|
+}
|
|
+
|
|
+/*
|
|
+** Free memory obtained from sqlite3_create_filename(). It is a severe
|
|
+** error to call this routine with any parameter other than a pointer
|
|
+** previously obtained from sqlite3_create_filename() or a NULL pointer.
|
|
+*/
|
|
+SQLITE_API void sqlite3_free_filename(char *p){
|
|
+ if( p==0 ) return;
|
|
+ p = (char*)databaseName(p);
|
|
+ sqlite3_free(p - 4);
|
|
+}
|
|
+
|
|
+
|
|
/*
|
|
** This is a utility routine, useful to VFS implementations, that checks
|
|
** to see if a database file was a URI that contained a specific query
|
|
@@ -159362,14 +164461,22 @@
|
|
*/
|
|
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
|
|
if( zFilename==0 || zParam==0 ) return 0;
|
|
+ zFilename = databaseName(zFilename);
|
|
+ return uriParameter(zFilename, zParam);
|
|
+}
|
|
+
|
|
+/*
|
|
+** Return a pointer to the name of Nth query parameter of the filename.
|
|
+*/
|
|
+SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N){
|
|
+ if( zFilename==0 || N<0 ) return 0;
|
|
+ zFilename = databaseName(zFilename);
|
|
zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
- while( zFilename[0] ){
|
|
- int x = strcmp(zFilename, zParam);
|
|
+ while( zFilename[0] && (N--)>0 ){
|
|
zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
- if( x==0 ) return zFilename;
|
|
zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
}
|
|
- return 0;
|
|
+ return zFilename[0] ? zFilename : 0;
|
|
}
|
|
|
|
/*
|
|
@@ -159397,6 +164504,38 @@
|
|
return bDflt;
|
|
}
|
|
|
|
+/*
|
|
+** Translate a filename that was handed to a VFS routine into the corresponding
|
|
+** database, journal, or WAL file.
|
|
+**
|
|
+** It is an error to pass this routine a filename string that was not
|
|
+** passed into the VFS from the SQLite core. Doing so is similar to
|
|
+** passing free() a pointer that was not obtained from malloc() - it is
|
|
+** an error that we cannot easily detect but that will likely cause memory
|
|
+** corruption.
|
|
+*/
|
|
+SQLITE_API const char *sqlite3_filename_database(const char *zFilename){
|
|
+ return databaseName(zFilename);
|
|
+}
|
|
+SQLITE_API const char *sqlite3_filename_journal(const char *zFilename){
|
|
+ zFilename = databaseName(zFilename);
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
+ while( zFilename[0] ){
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
+ }
|
|
+ return zFilename + 1;
|
|
+}
|
|
+SQLITE_API const char *sqlite3_filename_wal(const char *zFilename){
|
|
+#ifdef SQLITE_OMIT_WAL
|
|
+ return 0;
|
|
+#else
|
|
+ zFilename = sqlite3_filename_journal(zFilename);
|
|
+ zFilename += sqlite3Strlen30(zFilename) + 1;
|
|
+ return zFilename;
|
|
+#endif
|
|
+}
|
|
+
|
|
/*
|
|
** Return the Btree pointer identified by zDbName. Return NULL if not found.
|
|
*/
|
|
@@ -160730,6 +165869,9 @@
|
|
# define TESTONLY(X)
|
|
#endif
|
|
|
|
+#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
|
|
+#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
|
|
+
|
|
#endif /* SQLITE_AMALGAMATION */
|
|
|
|
#ifdef SQLITE_DEBUG
|
|
@@ -160773,6 +165915,7 @@
|
|
char *zLanguageid; /* languageid=xxx option, or NULL */
|
|
int nAutoincrmerge; /* Value configured by 'automerge' */
|
|
u32 nLeafAdd; /* Number of leaf blocks added this trans */
|
|
+ int bLock; /* Used to prevent recursive content= tbls */
|
|
|
|
/* Precompiled statements used by the implementation. Each of these
|
|
** statements is run and reset within a single virtual table API call.
|
|
@@ -160831,13 +165974,23 @@
|
|
int mxSavepoint; /* Largest valid xSavepoint integer */
|
|
#endif
|
|
|
|
-#ifdef SQLITE_TEST
|
|
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
/* True to disable the incremental doclist optimization. This is controled
|
|
** by special insert command 'test-no-incr-doclist'. */
|
|
int bNoIncrDoclist;
|
|
+
|
|
+ /* Number of segments in a level */
|
|
+ int nMergeCount;
|
|
#endif
|
|
};
|
|
|
|
+/* Macro to find the number of segments to merge */
|
|
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
+# define MergeCount(P) ((P)->nMergeCount)
|
|
+#else
|
|
+# define MergeCount(P) FTS3_MERGE_COUNT
|
|
+#endif
|
|
+
|
|
/*
|
|
** When the core wants to read from the virtual table, it creates a
|
|
** virtual table cursor (an instance of the following structure) using
|
|
@@ -161101,6 +166254,8 @@
|
|
SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
|
|
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
|
|
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
|
|
+SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *, sqlite_uint64 *);
|
|
+SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(const char*,const char*,sqlite3_int64*);
|
|
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
|
|
SQLITE_PRIVATE int sqlite3Fts3VarintLen(sqlite3_uint64);
|
|
SQLITE_PRIVATE void sqlite3Fts3Dequote(char *);
|
|
@@ -161109,6 +166264,7 @@
|
|
SQLITE_PRIVATE int sqlite3Fts3FirstFilter(sqlite3_int64, char *, int, char *);
|
|
SQLITE_PRIVATE void sqlite3Fts3CreateStatTable(int*, Fts3Table*);
|
|
SQLITE_PRIVATE int sqlite3Fts3EvalTestDeferred(Fts3Cursor *pCsr, int *pRc);
|
|
+SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut);
|
|
|
|
/* fts3_tokenizer.c */
|
|
SQLITE_PRIVATE const char *sqlite3Fts3NextToken(const char *, int *);
|
|
@@ -161231,12 +166387,7 @@
|
|
v = (*ptr++); \
|
|
if( (v & mask2)==0 ){ var = v; return ret; }
|
|
|
|
-/*
|
|
-** Read a 64-bit variable-length integer from memory starting at p[0].
|
|
-** Return the number of bytes read, or 0 on error.
|
|
-** The value is stored in *v.
|
|
-*/
|
|
-SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
|
+SQLITE_PRIVATE int sqlite3Fts3GetVarintU(const char *pBuf, sqlite_uint64 *v){
|
|
const unsigned char *p = (const unsigned char*)pBuf;
|
|
const unsigned char *pStart = p;
|
|
u32 a;
|
|
@@ -161258,6 +166409,41 @@
|
|
return (int)(p - pStart);
|
|
}
|
|
|
|
+/*
|
|
+** Read a 64-bit variable-length integer from memory starting at p[0].
|
|
+** Return the number of bytes read, or 0 on error.
|
|
+** The value is stored in *v.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
|
+ return sqlite3Fts3GetVarintU(pBuf, (sqlite3_uint64*)v);
|
|
+}
|
|
+
|
|
+/*
|
|
+** Read a 64-bit variable-length integer from memory starting at p[0] and
|
|
+** not extending past pEnd[-1].
|
|
+** Return the number of bytes read, or 0 on error.
|
|
+** The value is stored in *v.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3Fts3GetVarintBounded(
|
|
+ const char *pBuf,
|
|
+ const char *pEnd,
|
|
+ sqlite_int64 *v
|
|
+){
|
|
+ const unsigned char *p = (const unsigned char*)pBuf;
|
|
+ const unsigned char *pStart = p;
|
|
+ const unsigned char *pX = (const unsigned char*)pEnd;
|
|
+ u64 b = 0;
|
|
+ int shift;
|
|
+ for(shift=0; shift<=63; shift+=7){
|
|
+ u64 c = p<pX ? *p : 0;
|
|
+ p++;
|
|
+ b += (c&0x7F) << shift;
|
|
+ if( (c & 0x80)==0 ) break;
|
|
+ }
|
|
+ *v = b;
|
|
+ return (int)(p - pStart);
|
|
+}
|
|
+
|
|
/*
|
|
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
|
|
** a non-negative 32-bit integer before it is returned.
|
|
@@ -161811,6 +166997,22 @@
|
|
return zRet;
|
|
}
|
|
|
|
+/*
|
|
+** Buffer z contains a positive integer value encoded as utf-8 text.
|
|
+** Decode this value and store it in *pnOut, returning the number of bytes
|
|
+** consumed. If an overflow error occurs return a negative value.
|
|
+*/
|
|
+SQLITE_PRIVATE int sqlite3Fts3ReadInt(const char *z, int *pnOut){
|
|
+ u64 iVal = 0;
|
|
+ int i;
|
|
+ for(i=0; z[i]>='0' && z[i]<='9'; i++){
|
|
+ iVal = iVal*10 + (z[i] - '0');
|
|
+ if( iVal>0x7FFFFFFF ) return -1;
|
|
+ }
|
|
+ *pnOut = (int)iVal;
|
|
+ return i;
|
|
+}
|
|
+
|
|
/*
|
|
** This function interprets the string at (*pp) as a non-negative integer
|
|
** value. It reads the integer and sets *pnOut to the value read, then
|
|
@@ -161826,19 +167028,17 @@
|
|
*/
|
|
static int fts3GobbleInt(const char **pp, int *pnOut){
|
|
const int MAX_NPREFIX = 10000000;
|
|
- const char *p; /* Iterator pointer */
|
|
int nInt = 0; /* Output value */
|
|
-
|
|
- for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
|
|
- nInt = nInt * 10 + (p[0] - '0');
|
|
- if( nInt>MAX_NPREFIX ){
|
|
- nInt = 0;
|
|
- break;
|
|
- }
|
|
+ int nByte;
|
|
+ nByte = sqlite3Fts3ReadInt(*pp, &nInt);
|
|
+ if( nInt>MAX_NPREFIX ){
|
|
+ nInt = 0;
|
|
+ }
|
|
+ if( nByte==0 ){
|
|
+ return SQLITE_ERROR;
|
|
}
|
|
- if( p==*pp ) return SQLITE_ERROR;
|
|
*pnOut = nInt;
|
|
- *pp = p;
|
|
+ *pp += nByte;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
@@ -162353,6 +167553,10 @@
|
|
fts3DatabasePageSize(&rc, p);
|
|
p->nNodeSize = p->nPgsz-35;
|
|
|
|
+#if defined(SQLITE_DEBUG)||defined(SQLITE_TEST)
|
|
+ p->nMergeCount = FTS3_MERGE_COUNT;
|
|
+#endif
|
|
+
|
|
/* Declare the table schema to SQLite. */
|
|
fts3DeclareVtab(&rc, p);
|
|
|
|
@@ -162448,6 +167652,10 @@
|
|
int iDocidLe = -1; /* Index of docid<=x constraint, if present */
|
|
int iIdx;
|
|
|
|
+ if( p->bLock ){
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
+
|
|
/* By default use a full table scan. This is an expensive option,
|
|
** so search through the constraints to see if a more efficient
|
|
** strategy is possible.
|
|
@@ -162646,7 +167854,11 @@
|
|
}else{
|
|
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
|
|
if( !zSql ) return SQLITE_NOMEM;
|
|
- rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
|
+ p->bLock++;
|
|
+ rc = sqlite3_prepare_v3(
|
|
+ p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
|
|
+ );
|
|
+ p->bLock--;
|
|
sqlite3_free(zSql);
|
|
}
|
|
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
|
|
@@ -162664,11 +167876,15 @@
|
|
if( pCsr->isRequireSeek ){
|
|
rc = fts3CursorSeekStmt(pCsr);
|
|
if( rc==SQLITE_OK ){
|
|
+ Fts3Table *pTab = (Fts3Table*)pCsr->base.pVtab;
|
|
+ pTab->bLock++;
|
|
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iPrevId);
|
|
pCsr->isRequireSeek = 0;
|
|
if( SQLITE_ROW==sqlite3_step(pCsr->pStmt) ){
|
|
+ pTab->bLock--;
|
|
return SQLITE_OK;
|
|
}else{
|
|
+ pTab->bLock--;
|
|
rc = sqlite3_reset(pCsr->pStmt);
|
|
if( rc==SQLITE_OK && ((Fts3Table *)pCsr->base.pVtab)->zContentTbl==0 ){
|
|
/* If no row was found and no error has occurred, then the %_content
|
|
@@ -162717,6 +167933,7 @@
|
|
i64 nAlloc = 0; /* Size of allocated buffer */
|
|
int isFirstTerm = 1; /* True when processing first term on page */
|
|
sqlite3_int64 iChild; /* Block id of child node to descend to */
|
|
+ int nBuffer = 0; /* Total term size */
|
|
|
|
/* Skip over the 'height' varint that occurs at the start of every
|
|
** interior node. Then load the blockid of the left-child of the b-tree
|
|
@@ -162741,12 +167958,15 @@
|
|
int cmp; /* memcmp() result */
|
|
int nSuffix; /* Size of term suffix */
|
|
int nPrefix = 0; /* Size of term prefix */
|
|
- int nBuffer; /* Total term size */
|
|
|
|
/* Load the next term on the node into zBuffer. Use realloc() to expand
|
|
** the size of zBuffer if required. */
|
|
if( !isFirstTerm ){
|
|
zCsr += fts3GetVarint32(zCsr, &nPrefix);
|
|
+ if( nPrefix>nBuffer ){
|
|
+ rc = FTS_CORRUPT_VTAB;
|
|
+ goto finish_scan;
|
|
+ }
|
|
}
|
|
isFirstTerm = 0;
|
|
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
|
@@ -162840,7 +168060,7 @@
|
|
|
|
fts3GetVarint32(zNode, &iHeight);
|
|
rc = fts3ScanInteriorNode(zTerm, nTerm, zNode, nNode, piLeaf, piLeaf2);
|
|
- assert( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
|
|
+ assert_fts3_nc( !piLeaf2 || !piLeaf || rc!=SQLITE_OK || (*piLeaf<=*piLeaf2) );
|
|
|
|
if( rc==SQLITE_OK && iHeight>1 ){
|
|
char *zBlob = 0; /* Blob read from %_segments table */
|
|
@@ -162860,7 +168080,13 @@
|
|
rc = sqlite3Fts3ReadBlock(p, piLeaf?*piLeaf:*piLeaf2, &zBlob, &nBlob, 0);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
- rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
|
|
+ int iNewHeight = 0;
|
|
+ fts3GetVarint32(zBlob, &iNewHeight);
|
|
+ if( iNewHeight>=iHeight ){
|
|
+ rc = FTS_CORRUPT_VTAB;
|
|
+ }else{
|
|
+ rc = fts3SelectLeaf(p, zTerm, nTerm, zBlob, nBlob, piLeaf, piLeaf2);
|
|
+ }
|
|
}
|
|
sqlite3_free(zBlob);
|
|
}
|
|
@@ -162965,10 +168191,11 @@
|
|
}
|
|
|
|
/*
|
|
-** Value used to signify the end of an position-list. This is safe because
|
|
-** it is not possible to have a document with 2^31 terms.
|
|
+** Value used to signify the end of an position-list. This must be
|
|
+** as large or larger than any value that might appear on the
|
|
+** position-list, even a position list that has been corrupted.
|
|
*/
|
|
-#define POSITION_LIST_END 0x7fffffff
|
|
+#define POSITION_LIST_END LARGEST_INT64
|
|
|
|
/*
|
|
** This function is used to help parse position-lists. When this function is
|
|
@@ -162993,7 +168220,9 @@
|
|
sqlite3_int64 *pi /* IN/OUT: Value read from position-list */
|
|
){
|
|
if( (**pp)&0xFE ){
|
|
- fts3GetDeltaVarint(pp, pi);
|
|
+ int iVal;
|
|
+ *pp += fts3GetVarint32((*pp), &iVal);
|
|
+ *pi += iVal;
|
|
*pi -= 2;
|
|
}else{
|
|
*pi = POSITION_LIST_END;
|
|
@@ -163044,14 +168273,14 @@
|
|
fts3GetVarint32(&p1[1], &iCol1);
|
|
if( iCol1==0 ) return FTS_CORRUPT_VTAB;
|
|
}
|
|
- else if( *p1==POS_END ) iCol1 = POSITION_LIST_END;
|
|
+ else if( *p1==POS_END ) iCol1 = 0x7fffffff;
|
|
else iCol1 = 0;
|
|
|
|
if( *p2==POS_COLUMN ){
|
|
fts3GetVarint32(&p2[1], &iCol2);
|
|
if( iCol2==0 ) return FTS_CORRUPT_VTAB;
|
|
}
|
|
- else if( *p2==POS_END ) iCol2 = POSITION_LIST_END;
|
|
+ else if( *p2==POS_END ) iCol2 = 0x7fffffff;
|
|
else iCol2 = 0;
|
|
|
|
if( iCol1==iCol2 ){
|
|
@@ -163314,12 +168543,12 @@
|
|
if( *pp>=pEnd ){
|
|
*pp = 0;
|
|
}else{
|
|
- sqlite3_int64 iVal;
|
|
- *pp += sqlite3Fts3GetVarint(*pp, &iVal);
|
|
+ u64 iVal;
|
|
+ *pp += sqlite3Fts3GetVarintU(*pp, &iVal);
|
|
if( bDescIdx ){
|
|
- *pVal -= iVal;
|
|
+ *pVal = (i64)((u64)*pVal - iVal);
|
|
}else{
|
|
- *pVal += iVal;
|
|
+ *pVal = (i64)((u64)*pVal + iVal);
|
|
}
|
|
}
|
|
}
|
|
@@ -163346,14 +168575,16 @@
|
|
int *pbFirst, /* IN/OUT: True after first int written */
|
|
sqlite3_int64 iVal /* Write this value to the list */
|
|
){
|
|
- sqlite3_int64 iWrite;
|
|
+ sqlite3_uint64 iWrite;
|
|
if( bDescIdx==0 || *pbFirst==0 ){
|
|
- iWrite = iVal - *piPrev;
|
|
+ assert_fts3_nc( *pbFirst==0 || iVal>=*piPrev );
|
|
+ iWrite = (u64)iVal - (u64)*piPrev;
|
|
}else{
|
|
- iWrite = *piPrev - iVal;
|
|
+ assert_fts3_nc( *piPrev>=iVal );
|
|
+ iWrite = (u64)*piPrev - (u64)iVal;
|
|
}
|
|
assert( *pbFirst || *piPrev==0 );
|
|
- assert( *pbFirst==0 || iWrite>0 );
|
|
+ assert_fts3_nc( *pbFirst==0 || iWrite>0 );
|
|
*pp += sqlite3Fts3PutVarint(*pp, iWrite);
|
|
*piPrev = iVal;
|
|
*pbFirst = 1;
|
|
@@ -163369,7 +168600,8 @@
|
|
** Using this makes it easier to write code that can merge doclists that are
|
|
** sorted in either ascending or descending order.
|
|
*/
|
|
-#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1-i2))
|
|
+/* #define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i64)((u64)i1-i2)) */
|
|
+#define DOCID_CMP(i1, i2) ((bDescDoclist?-1:1) * (i1>i2?1:((i1==i2)?0:-1)))
|
|
|
|
/*
|
|
** This function does an "OR" merge of two doclists (output contains all
|
|
@@ -163459,6 +168691,8 @@
|
|
fts3PoslistCopy(&p, &p2);
|
|
fts3GetDeltaVarint3(&p2, pEnd2, bDescDoclist, &i2);
|
|
}
|
|
+
|
|
+ assert( (p-aOut)<=((p1?(p1-a1):n1)+(p2?(p2-a2):n2)+FTS3_VARINT_MAX-1) );
|
|
}
|
|
|
|
if( rc!=SQLITE_OK ){
|
|
@@ -163781,7 +169015,7 @@
|
|
** Fts3SegReaderPending might segfault, as the data structures used by
|
|
** fts4aux are not completely populated. So it's easiest to filter these
|
|
** calls out here. */
|
|
- if( iLevel<0 && p->aIndex ){
|
|
+ if( iLevel<0 && p->aIndex && p->iPrevLangid==iLangid ){
|
|
Fts3SegReader *pSeg = 0;
|
|
rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
|
|
if( rc==SQLITE_OK && pSeg ){
|
|
@@ -164044,6 +169278,8 @@
|
|
int rc;
|
|
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
|
|
if( pCsr->eSearch==FTS3_DOCID_SEARCH || pCsr->eSearch==FTS3_FULLSCAN_SEARCH ){
|
|
+ Fts3Table *pTab = (Fts3Table*)pCursor->pVtab;
|
|
+ pTab->bLock++;
|
|
if( SQLITE_ROW!=sqlite3_step(pCsr->pStmt) ){
|
|
pCsr->isEof = 1;
|
|
rc = sqlite3_reset(pCsr->pStmt);
|
|
@@ -164051,6 +169287,7 @@
|
|
pCsr->iPrevId = sqlite3_column_int64(pCsr->pStmt, 0);
|
|
rc = SQLITE_OK;
|
|
}
|
|
+ pTab->bLock--;
|
|
}else{
|
|
rc = fts3EvalNext((Fts3Cursor *)pCursor);
|
|
}
|
|
@@ -164058,18 +169295,6 @@
|
|
return rc;
|
|
}
|
|
|
|
-/*
|
|
-** The following are copied from sqliteInt.h.
|
|
-**
|
|
-** Constants for the largest and smallest possible 64-bit signed integers.
|
|
-** These macros are designed to work correctly on both 32-bit and 64-bit
|
|
-** compilers.
|
|
-*/
|
|
-#ifndef SQLITE_AMALGAMATION
|
|
-# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
|
|
-# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
|
|
-#endif
|
|
-
|
|
/*
|
|
** If the numeric type of argument pVal is "integer", then return it
|
|
** converted to a 64-bit signed integer. Otherwise, return a copy of
|
|
@@ -164123,6 +169348,10 @@
|
|
UNUSED_PARAMETER(idxStr);
|
|
UNUSED_PARAMETER(nVal);
|
|
|
|
+ if( p->bLock ){
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
+
|
|
eSearch = (idxNum & 0x0000FFFF);
|
|
assert( eSearch>=0 && eSearch<=(FTS3_FULLTEXT_SEARCH+p->nColumn) );
|
|
assert( p->pSegments==0 );
|
|
@@ -164194,7 +169423,11 @@
|
|
);
|
|
}
|
|
if( zSql ){
|
|
- rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
|
|
+ p->bLock++;
|
|
+ rc = sqlite3_prepare_v3(
|
|
+ p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0
|
|
+ );
|
|
+ p->bLock--;
|
|
sqlite3_free(zSql);
|
|
}else{
|
|
rc = SQLITE_NOMEM;
|
|
@@ -165211,7 +170444,7 @@
|
|
int bIncrOk = (bOptOk
|
|
&& pCsr->bDesc==pTab->bDescIdx
|
|
&& p->nToken<=MAX_INCR_PHRASE_TOKENS && p->nToken>0
|
|
-#ifdef SQLITE_TEST
|
|
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
&& pTab->bNoIncrDoclist==0
|
|
#endif
|
|
);
|
|
@@ -165353,15 +170586,16 @@
|
|
u8 *pbEof
|
|
){
|
|
char *pIter; /* Used to iterate through aAll */
|
|
- char *pEnd = &pDL->aAll[pDL->nAll]; /* 1 byte past end of aAll */
|
|
+ char *pEnd; /* 1 byte past end of aAll */
|
|
|
|
if( pDL->pNextDocid ){
|
|
pIter = pDL->pNextDocid;
|
|
+ assert( pDL->aAll!=0 || pIter==0 );
|
|
}else{
|
|
pIter = pDL->aAll;
|
|
}
|
|
|
|
- if( pIter>=pEnd ){
|
|
+ if( pIter==0 || pIter>=(pEnd = pDL->aAll + pDL->nAll) ){
|
|
/* We have already reached the end of this doclist. EOF. */
|
|
*pbEof = 1;
|
|
}else{
|
|
@@ -165733,12 +170967,13 @@
|
|
rc = sqlite3Fts3SelectDoctotal(p, &pStmt);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
a = sqlite3_column_blob(pStmt, 0);
|
|
- assert( a );
|
|
-
|
|
- pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
|
|
- a += sqlite3Fts3GetVarint(a, &nDoc);
|
|
- while( a<pEnd ){
|
|
- a += sqlite3Fts3GetVarint(a, &nByte);
|
|
+ testcase( a==0 ); /* If %_stat.value set to X'' */
|
|
+ if( a ){
|
|
+ pEnd = &a[sqlite3_column_bytes(pStmt, 0)];
|
|
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
|
|
+ while( a<pEnd ){
|
|
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nByte);
|
|
+ }
|
|
}
|
|
if( nDoc==0 || nByte==0 ){
|
|
sqlite3_reset(pStmt);
|
|
@@ -166117,6 +171352,7 @@
|
|
fts3EvalNextRow(pCsr, pLeft, pRc);
|
|
}
|
|
}
|
|
+ pRight->bEof = pLeft->bEof = 1;
|
|
}
|
|
}
|
|
break;
|
|
@@ -167887,10 +173123,7 @@
|
|
if( pKey->eType==FTSQUERY_NEAR ){
|
|
assert( nKey==4 );
|
|
if( zInput[4]=='/' && zInput[5]>='0' && zInput[5]<='9' ){
|
|
- nNear = 0;
|
|
- for(nKey=5; zInput[nKey]>='0' && zInput[nKey]<='9'; nKey++){
|
|
- nNear = nNear * 10 + (zInput[nKey] - '0');
|
|
- }
|
|
+ nKey += 1+sqlite3Fts3ReadInt(&zInput[nKey+1], &nNear);
|
|
}
|
|
}
|
|
|
|
@@ -170176,7 +175409,9 @@
|
|
|
|
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
|
|
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
|
- if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
|
|
+ if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB
|
|
+ && sqlite3_column_bytes(pStmt, 0)==sizeof(*pp)
|
|
+ ){
|
|
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
|
}
|
|
}
|
|
@@ -170265,7 +175500,7 @@
|
|
){
|
|
int rc = SQLITE_OK;
|
|
void *p = (void *)pHash;
|
|
- const int any = SQLITE_ANY;
|
|
+ const int any = SQLITE_UTF8|SQLITE_DIRECTONLY;
|
|
|
|
#ifdef SQLITE_TEST
|
|
char *zTest = 0;
|
|
@@ -170894,7 +176129,7 @@
|
|
if( pCsr->zInput==0 ){
|
|
rc = SQLITE_NOMEM;
|
|
}else{
|
|
- memcpy(pCsr->zInput, zByte, nByte);
|
|
+ if( nByte>0 ) memcpy(pCsr->zInput, zByte, nByte);
|
|
pCsr->zInput[nByte] = 0;
|
|
rc = pTab->pMod->xOpen(pTab->pTok, pCsr->zInput, nByte, &pCsr->pCsr);
|
|
if( rc==SQLITE_OK ){
|
|
@@ -171025,7 +176260,7 @@
|
|
/* #include <string.h> */
|
|
/* #include <assert.h> */
|
|
/* #include <stdlib.h> */
|
|
-
|
|
+/* #include <stdio.h> */
|
|
|
|
#define FTS_MAX_APPENDABLE_HEIGHT 16
|
|
|
|
@@ -171069,7 +176304,7 @@
|
|
#endif
|
|
|
|
/*
|
|
-** The two values that may be meaningfully bound to the :1 parameter in
|
|
+** The values that may be meaningfully bound to the :1 parameter in
|
|
** statements SQL_REPLACE_STAT and SQL_SELECT_STAT.
|
|
*/
|
|
#define FTS_STAT_DOCTOTAL 0
|
|
@@ -171337,7 +176572,7 @@
|
|
** returns zero rows. */
|
|
/* 28 */ "SELECT level, count(*) AS cnt FROM %Q.'%q_segdir' "
|
|
" GROUP BY level HAVING cnt>=?"
|
|
- " ORDER BY (level %% 1024) ASC LIMIT 1",
|
|
+ " ORDER BY (level %% 1024) ASC, 2 DESC LIMIT 1",
|
|
|
|
/* Estimate the upper limit on the number of leaf nodes in a new segment
|
|
** created by merging the oldest :2 segments from absolute level :1. See
|
|
@@ -171698,7 +176933,7 @@
|
|
assert( !p || p->iLastDocid<=iDocid );
|
|
|
|
if( !p || p->iLastDocid!=iDocid ){
|
|
- sqlite3_int64 iDelta = iDocid - (p ? p->iLastDocid : 0);
|
|
+ u64 iDelta = (u64)iDocid - (u64)(p ? p->iLastDocid : 0);
|
|
if( p ){
|
|
assert( p->nData<p->nSpace );
|
|
assert( p->aData[p->nData]==0 );
|
|
@@ -172155,7 +177390,7 @@
|
|
** segment and allocate (newly freed) index 0 at level iLevel. Otherwise,
|
|
** if iNext is less than FTS3_MERGE_COUNT, allocate index iNext.
|
|
*/
|
|
- if( iNext>=FTS3_MERGE_COUNT ){
|
|
+ if( iNext>=MergeCount(p) ){
|
|
fts3LogMerge(16, getAbsoluteLevel(p, iLangid, iIndex, iLevel));
|
|
rc = fts3SegmentMerge(p, iLangid, iIndex, iLevel);
|
|
*piIdx = 0;
|
|
@@ -172239,6 +177474,8 @@
|
|
}
|
|
*paBlob = aByte;
|
|
}
|
|
+ }else if( rc==SQLITE_ERROR ){
|
|
+ rc = FTS_CORRUPT_VTAB;
|
|
}
|
|
|
|
return rc;
|
|
@@ -172381,7 +177618,7 @@
|
|
pNext += fts3GetVarint32(pNext, &nSuffix);
|
|
if( nSuffix<=0
|
|
|| (&pReader->aNode[pReader->nNode] - pNext)<nSuffix
|
|
- || nPrefix>pReader->nTermAlloc
|
|
+ || nPrefix>pReader->nTerm
|
|
){
|
|
return FTS_CORRUPT_VTAB;
|
|
}
|
|
@@ -172415,6 +177652,7 @@
|
|
*/
|
|
if( pReader->nDoclist > pReader->nNode-(pReader->aDoclist-pReader->aNode)
|
|
|| (pReader->nPopulate==0 && pReader->aDoclist[pReader->nDoclist-1])
|
|
+ || pReader->nDoclist==0
|
|
){
|
|
return FTS_CORRUPT_VTAB;
|
|
}
|
|
@@ -172531,18 +177769,18 @@
|
|
}else{
|
|
rc = fts3SegReaderRequire(pReader, p, FTS3_VARINT_MAX);
|
|
if( rc==SQLITE_OK ){
|
|
- sqlite3_int64 iDelta;
|
|
- pReader->pOffsetList = p + sqlite3Fts3GetVarint(p, &iDelta);
|
|
+ u64 iDelta;
|
|
+ pReader->pOffsetList = p + sqlite3Fts3GetVarintU(p, &iDelta);
|
|
if( pTab->bDescIdx ){
|
|
- pReader->iDocid -= iDelta;
|
|
+ pReader->iDocid = (i64)((u64)pReader->iDocid - iDelta);
|
|
}else{
|
|
- pReader->iDocid += iDelta;
|
|
+ pReader->iDocid = (i64)((u64)pReader->iDocid + iDelta);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
- return SQLITE_OK;
|
|
+ return rc;
|
|
}
|
|
|
|
|
|
@@ -173032,6 +178270,11 @@
|
|
nPrefix = fts3PrefixCompress(pTree->zTerm, pTree->nTerm, zTerm, nTerm);
|
|
nSuffix = nTerm-nPrefix;
|
|
|
|
+ /* If nSuffix is zero or less, then zTerm/nTerm must be a prefix of
|
|
+ ** pWriter->zTerm/pWriter->nTerm. i.e. must be equal to or less than when
|
|
+ ** compared with BINARY collation. This indicates corruption. */
|
|
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
|
+
|
|
nReq += sqlite3Fts3VarintLen(nPrefix)+sqlite3Fts3VarintLen(nSuffix)+nSuffix;
|
|
if( nReq<=p->nNodeSize || !pTree->zTerm ){
|
|
|
|
@@ -173276,6 +178519,7 @@
|
|
int rc;
|
|
|
|
/* The current leaf node is full. Write it out to the database. */
|
|
+ if( pWriter->iFree==LARGEST_INT64 ) return FTS_CORRUPT_VTAB;
|
|
rc = fts3WriteSegment(p, pWriter->iFree++, pWriter->aData, nData);
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
p->nLeafAdd++;
|
|
@@ -173325,9 +178569,11 @@
|
|
/* Append the prefix-compressed term and doclist to the buffer. */
|
|
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nPrefix);
|
|
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nSuffix);
|
|
+ assert( nSuffix>0 );
|
|
memcpy(&pWriter->aData[nData], &zTerm[nPrefix], nSuffix);
|
|
nData += nSuffix;
|
|
nData += sqlite3Fts3PutVarint(&pWriter->aData[nData], nDoclist);
|
|
+ assert( nDoclist>0 );
|
|
memcpy(&pWriter->aData[nData], aDoclist, nDoclist);
|
|
pWriter->nData = nData + nDoclist;
|
|
|
|
@@ -173347,6 +178593,7 @@
|
|
pWriter->zTerm = zNew;
|
|
}
|
|
assert( pWriter->zTerm==pWriter->zMalloc );
|
|
+ assert( nTerm>0 );
|
|
memcpy(pWriter->zTerm, zTerm, nTerm);
|
|
}else{
|
|
pWriter->zTerm = (char *)zTerm;
|
|
@@ -173493,7 +178740,7 @@
|
|
if( rc!=SQLITE_OK ) return rc;
|
|
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
|
|
sqlite3_bind_int64(pStmt, 2,
|
|
- ((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
|
+ (((u64)iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
|
|
);
|
|
|
|
*pbMax = 0;
|
|
@@ -173655,6 +178902,7 @@
|
|
pMsr->aBuffer = pNew;
|
|
}
|
|
|
|
+ assert( nList>0 );
|
|
memcpy(pMsr->aBuffer, pList, nList);
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -173968,14 +179216,12 @@
|
|
** doclist. */
|
|
sqlite3_int64 iDelta;
|
|
if( p->bDescIdx && nDoclist>0 ){
|
|
- iDelta = iPrev - iDocid;
|
|
+ if( iPrev<=iDocid ) return FTS_CORRUPT_VTAB;
|
|
+ iDelta = (i64)((u64)iPrev - (u64)iDocid);
|
|
}else{
|
|
- iDelta = iDocid - iPrev;
|
|
+ if( nDoclist>0 && iPrev>=iDocid ) return FTS_CORRUPT_VTAB;
|
|
+ iDelta = (i64)((u64)iDocid - (u64)iPrev);
|
|
}
|
|
- if( iDelta<=0 && (nDoclist>0 || iDelta!=iDocid) ){
|
|
- return FTS_CORRUPT_VTAB;
|
|
- }
|
|
- assert( nDoclist>0 || iDelta==iDocid );
|
|
|
|
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
|
|
if( nDoclist+nByte>pCsr->nBuffer ){
|
|
@@ -174060,11 +179306,11 @@
|
|
if( zText ){
|
|
int i;
|
|
int iMul = 1;
|
|
- i64 iVal = 0;
|
|
+ u64 iVal = 0;
|
|
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
|
|
iVal = iVal*10 + (zText[i] - '0');
|
|
}
|
|
- *piEndBlock = iVal;
|
|
+ *piEndBlock = (i64)iVal;
|
|
while( zText[i]==' ' ) i++;
|
|
iVal = 0;
|
|
if( zText[i]=='-' ){
|
|
@@ -174074,7 +179320,7 @@
|
|
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
|
|
iVal = iVal*10 + (zText[i] - '0');
|
|
}
|
|
- *pnByte = (iVal * (i64)iMul);
|
|
+ *pnByte = ((i64)iVal * (i64)iMul);
|
|
}
|
|
}
|
|
|
|
@@ -174257,7 +179503,7 @@
|
|
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
|
|
}
|
|
if( rc!=SQLITE_OK ) goto finished;
|
|
- assert( pWriter || bIgnoreEmpty );
|
|
+ assert_fts3_nc( pWriter || bIgnoreEmpty );
|
|
|
|
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
|
|
rc = fts3DeleteSegdir(
|
|
@@ -174484,7 +179730,10 @@
|
|
int rc;
|
|
sqlite3_stmt *pAllLangid = 0;
|
|
|
|
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
|
+ rc = sqlite3Fts3PendingTermsFlush(p);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
|
|
+ }
|
|
if( rc==SQLITE_OK ){
|
|
int rc2;
|
|
sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
|
|
@@ -174505,7 +179754,6 @@
|
|
}
|
|
|
|
sqlite3Fts3SegmentsClose(p);
|
|
- sqlite3Fts3PendingTermsClear(p);
|
|
|
|
return (rc==SQLITE_OK && bReturnDone && bSeenDone) ? SQLITE_DONE : rc;
|
|
}
|
|
@@ -174799,14 +180047,14 @@
|
|
p->nNode = nNode;
|
|
|
|
/* Figure out if this is a leaf or an internal node. */
|
|
- if( p->aNode[0] ){
|
|
+ if( aNode && aNode[0] ){
|
|
/* An internal node. */
|
|
p->iOff = 1 + sqlite3Fts3GetVarint(&p->aNode[1], &p->iChild);
|
|
}else{
|
|
p->iOff = 1;
|
|
}
|
|
|
|
- return nodeReaderNext(p);
|
|
+ return aNode ? nodeReaderNext(p) : SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
@@ -174843,6 +180091,7 @@
|
|
** be added to. */
|
|
nPrefix = fts3PrefixCompress(pNode->key.a, pNode->key.n, zTerm, nTerm);
|
|
nSuffix = nTerm - nPrefix;
|
|
+ if(nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
|
nSpace = sqlite3Fts3VarintLen(nPrefix);
|
|
nSpace += sqlite3Fts3VarintLen(nSuffix) + nSuffix;
|
|
|
|
@@ -174943,6 +180192,7 @@
|
|
|
|
nPrefix = fts3PrefixCompress(pPrev->a, pPrev->n, zTerm, nTerm);
|
|
nSuffix = nTerm - nPrefix;
|
|
+ if( nSuffix<=0 ) return FTS_CORRUPT_VTAB;
|
|
memcpy(pPrev->a, zTerm, nTerm);
|
|
pPrev->n = nTerm;
|
|
|
|
@@ -175236,6 +180486,10 @@
|
|
pWriter->bNoLeafData = (pWriter->nLeafData==0);
|
|
nRoot = sqlite3_column_bytes(pSelect, 4);
|
|
aRoot = sqlite3_column_blob(pSelect, 4);
|
|
+ if( aRoot==0 ){
|
|
+ sqlite3_reset(pSelect);
|
|
+ return nRoot ? SQLITE_NOMEM : FTS_CORRUPT_VTAB;
|
|
+ }
|
|
}else{
|
|
return sqlite3_reset(pSelect);
|
|
}
|
|
@@ -175271,6 +180525,10 @@
|
|
int i;
|
|
int nHeight = (int)aRoot[0];
|
|
NodeWriter *pNode;
|
|
+ if( nHeight<1 || nHeight>FTS_MAX_APPENDABLE_HEIGHT ){
|
|
+ sqlite3_reset(pSelect);
|
|
+ return FTS_CORRUPT_VTAB;
|
|
+ }
|
|
|
|
pWriter->nLeafEst = (int)((iEnd - iStart) + 1)/FTS_MAX_APPENDABLE_HEIGHT;
|
|
pWriter->iStart = iStart;
|
|
@@ -175297,8 +180555,8 @@
|
|
NodeReader reader;
|
|
pNode = &pWriter->aNodeWriter[i];
|
|
|
|
- rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
|
|
- if( reader.aNode ){
|
|
+ if( pNode->block.a){
|
|
+ rc = nodeReaderInit(&reader, pNode->block.a, pNode->block.n);
|
|
while( reader.aNode && rc==SQLITE_OK ) rc = nodeReaderNext(&reader);
|
|
blobGrowBuffer(&pNode->key, reader.term.n, &rc);
|
|
if( rc==SQLITE_OK ){
|
|
@@ -175831,13 +181089,17 @@
|
|
const int nHint = pHint->n;
|
|
int i;
|
|
|
|
- i = pHint->n-2;
|
|
+ i = pHint->n-1;
|
|
+ if( (pHint->a[i] & 0x80) ) return FTS_CORRUPT_VTAB;
|
|
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
|
|
+ if( i==0 ) return FTS_CORRUPT_VTAB;
|
|
+ i--;
|
|
while( i>0 && (pHint->a[i-1] & 0x80) ) i--;
|
|
|
|
pHint->n = i;
|
|
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
|
|
i += fts3GetVarint32(&pHint->a[i], pnInput);
|
|
+ assert( i<=nHint );
|
|
if( i!=nHint ) return FTS_CORRUPT_VTAB;
|
|
|
|
return SQLITE_OK;
|
|
@@ -175907,8 +181169,14 @@
|
|
|
|
rc = fts3IncrmergeHintPop(&hint, &iHintAbsLevel, &nHintSeg);
|
|
if( nSeg<0 || (iAbsLevel % nMod) >= (iHintAbsLevel % nMod) ){
|
|
+ /* Based on the scan in the block above, it is known that there
|
|
+ ** are no levels with a relative level smaller than that of
|
|
+ ** iAbsLevel with more than nSeg segments, or if nSeg is -1,
|
|
+ ** no levels with more than nMin segments. Use this to limit the
|
|
+ ** value of nHintSeg to avoid a large memory allocation in case the
|
|
+ ** merge-hint is corrupt*/
|
|
iAbsLevel = iHintAbsLevel;
|
|
- nSeg = nHintSeg;
|
|
+ nSeg = MIN(MAX(nMin,nSeg), nHintSeg);
|
|
bUseHint = 1;
|
|
bDirtyHint = 1;
|
|
}else{
|
|
@@ -175921,7 +181189,13 @@
|
|
/* If nSeg is less that zero, then there is no level with at least
|
|
** nMin segments and no hint in the %_stat table. No work to do.
|
|
** Exit early in this case. */
|
|
- if( nSeg<0 ) break;
|
|
+ if( nSeg<=0 ) break;
|
|
+
|
|
+ assert( nMod<=0x7FFFFFFF );
|
|
+ if( iAbsLevel<0 || iAbsLevel>(nMod<<32) ){
|
|
+ rc = FTS_CORRUPT_VTAB;
|
|
+ break;
|
|
+ }
|
|
|
|
/* Open a cursor to iterate through the contents of the oldest nSeg
|
|
** indexes of absolute level iAbsLevel. If this cursor is opened using
|
|
@@ -175949,8 +181223,15 @@
|
|
}
|
|
if( SQLITE_OK==rc && pCsr->nSegment==nSeg
|
|
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
|
|
- && SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
|
|
){
|
|
+ int bEmpty = 0;
|
|
+ rc = sqlite3Fts3SegReaderStep(p, pCsr);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ bEmpty = 1;
|
|
+ }else if( rc!=SQLITE_ROW ){
|
|
+ sqlite3Fts3SegReaderFinish(pCsr);
|
|
+ break;
|
|
+ }
|
|
if( bUseHint && iIdx>0 ){
|
|
const char *zKey = pCsr->zTerm;
|
|
int nKey = pCsr->nTerm;
|
|
@@ -175961,11 +181242,13 @@
|
|
|
|
if( rc==SQLITE_OK && pWriter->nLeafEst ){
|
|
fts3LogMerge(nSeg, iAbsLevel);
|
|
- do {
|
|
- rc = fts3IncrmergeAppend(p, pWriter, pCsr);
|
|
- if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
|
|
- if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
|
|
- }while( rc==SQLITE_ROW );
|
|
+ if( bEmpty==0 ){
|
|
+ do {
|
|
+ rc = fts3IncrmergeAppend(p, pWriter, pCsr);
|
|
+ if( rc==SQLITE_OK ) rc = sqlite3Fts3SegReaderStep(p, pCsr);
|
|
+ if( pWriter->nWork>=nRem && rc==SQLITE_ROW ) rc = SQLITE_OK;
|
|
+ }while( rc==SQLITE_ROW );
|
|
+ }
|
|
|
|
/* Update or delete the input segments */
|
|
if( rc==SQLITE_OK ){
|
|
@@ -176030,7 +181313,7 @@
|
|
const char *zParam /* Nul-terminated string containing "A,B" */
|
|
){
|
|
int rc;
|
|
- int nMin = (FTS3_MERGE_COUNT / 2);
|
|
+ int nMin = (MergeCount(p) / 2);
|
|
int nMerge = 0;
|
|
const char *z = zParam;
|
|
|
|
@@ -176075,7 +181358,7 @@
|
|
int rc = SQLITE_OK;
|
|
sqlite3_stmt *pStmt = 0;
|
|
p->nAutoincrmerge = fts3Getint(&zParam);
|
|
- if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
|
|
+ if( p->nAutoincrmerge==1 || p->nAutoincrmerge>MergeCount(p) ){
|
|
p->nAutoincrmerge = 8;
|
|
}
|
|
if( !p->bHasStat ){
|
|
@@ -176158,12 +181441,12 @@
|
|
|
|
i64 iDocid = 0;
|
|
i64 iCol = 0;
|
|
- i64 iPos = 0;
|
|
+ u64 iPos = 0;
|
|
|
|
pCsr += sqlite3Fts3GetVarint(pCsr, &iDocid);
|
|
while( pCsr<pEnd ){
|
|
- i64 iVal = 0;
|
|
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
|
|
+ u64 iVal = 0;
|
|
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
|
|
if( pCsr<pEnd ){
|
|
if( iVal==0 || iVal==1 ){
|
|
iCol = 0;
|
|
@@ -176171,8 +181454,12 @@
|
|
if( iVal ){
|
|
pCsr += sqlite3Fts3GetVarint(pCsr, &iCol);
|
|
}else{
|
|
- pCsr += sqlite3Fts3GetVarint(pCsr, &iVal);
|
|
- iDocid += iVal;
|
|
+ pCsr += sqlite3Fts3GetVarintU(pCsr, &iVal);
|
|
+ if( p->bDescIdx ){
|
|
+ iDocid = (i64)((u64)iDocid - iVal);
|
|
+ }else{
|
|
+ iDocid = (i64)((u64)iDocid + iVal);
|
|
+ }
|
|
}
|
|
}else{
|
|
iPos += (iVal - 2);
|
|
@@ -176245,10 +181532,9 @@
|
|
for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
|
|
if( p->abNotindexed[iCol]==0 ){
|
|
const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
|
|
- int nText = sqlite3_column_bytes(pStmt, iCol+1);
|
|
sqlite3_tokenizer_cursor *pT = 0;
|
|
|
|
- rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
|
|
+ rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, -1, &pT);
|
|
while( rc==SQLITE_OK ){
|
|
char const *zToken; /* Buffer containing token */
|
|
int nToken = 0; /* Number of bytes in token */
|
|
@@ -176333,7 +181619,7 @@
|
|
** meaningful value to insert is the text 'optimize'.
|
|
*/
|
|
static int fts3SpecialInsert(Fts3Table *p, sqlite3_value *pVal){
|
|
- int rc; /* Return Code */
|
|
+ int rc = SQLITE_ERROR; /* Return Code */
|
|
const char *zVal = (const char *)sqlite3_value_text(pVal);
|
|
int nVal = sqlite3_value_bytes(pVal);
|
|
|
|
@@ -176349,21 +181635,27 @@
|
|
rc = fts3DoIncrmerge(p, &zVal[6]);
|
|
}else if( nVal>10 && 0==sqlite3_strnicmp(zVal, "automerge=", 10) ){
|
|
rc = fts3DoAutoincrmerge(p, &zVal[10]);
|
|
-#ifdef SQLITE_TEST
|
|
- }else if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
|
|
- p->nNodeSize = atoi(&zVal[9]);
|
|
- rc = SQLITE_OK;
|
|
- }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
|
|
- p->nMaxPendingData = atoi(&zVal[11]);
|
|
- rc = SQLITE_OK;
|
|
- }else if( nVal>21 && 0==sqlite3_strnicmp(zVal, "test-no-incr-doclist=", 21) ){
|
|
- p->bNoIncrDoclist = atoi(&zVal[21]);
|
|
- rc = SQLITE_OK;
|
|
-#endif
|
|
+#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
|
|
}else{
|
|
- rc = SQLITE_ERROR;
|
|
+ int v;
|
|
+ if( nVal>9 && 0==sqlite3_strnicmp(zVal, "nodesize=", 9) ){
|
|
+ v = atoi(&zVal[9]);
|
|
+ if( v>=24 && v<=p->nPgsz-35 ) p->nNodeSize = v;
|
|
+ rc = SQLITE_OK;
|
|
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal, "maxpending=", 9) ){
|
|
+ v = atoi(&zVal[11]);
|
|
+ if( v>=64 && v<=FTS3_MAX_PENDING_DATA ) p->nMaxPendingData = v;
|
|
+ rc = SQLITE_OK;
|
|
+ }else if( nVal>21 && 0==sqlite3_strnicmp(zVal,"test-no-incr-doclist=",21) ){
|
|
+ p->bNoIncrDoclist = atoi(&zVal[21]);
|
|
+ rc = SQLITE_OK;
|
|
+ }else if( nVal>11 && 0==sqlite3_strnicmp(zVal,"mergecount=",11) ){
|
|
+ v = atoi(&zVal[11]);
|
|
+ if( v>=4 && v<=FTS3_MERGE_COUNT && (v&1)==0 ) p->nMergeCount = v;
|
|
+ rc = SQLITE_OK;
|
|
+ }
|
|
+#endif
|
|
}
|
|
-
|
|
return rc;
|
|
}
|
|
|
|
@@ -177163,10 +182455,10 @@
|
|
|
|
while( iCsr<(iStart+pIter->nSnippet) && iCsr>=iStart ){
|
|
int j;
|
|
- u64 mPhrase = (u64)1 << i;
|
|
+ u64 mPhrase = (u64)1 << (i%64);
|
|
u64 mPos = (u64)1 << (iCsr - iStart);
|
|
assert( iCsr>=iStart && (iCsr - iStart)<=64 );
|
|
- assert( i>=0 && i<=64 );
|
|
+ assert( i>=0 );
|
|
if( (mCover|mCovered)&mPhrase ){
|
|
iScore++;
|
|
}else{
|
|
@@ -177290,7 +182582,7 @@
|
|
/* Set the *pmSeen output variable. */
|
|
for(i=0; i<nList; i++){
|
|
if( sIter.aPhrase[i].pHead ){
|
|
- *pmSeen |= (u64)1 << i;
|
|
+ *pmSeen |= (u64)1 << (i%64);
|
|
}
|
|
}
|
|
|
|
@@ -177606,7 +182898,7 @@
|
|
iStart = pExpr->iPhrase * ((p->nCol + 31) / 32);
|
|
}
|
|
|
|
- while( 1 ){
|
|
+ if( pIter ) while( 1 ){
|
|
int nHit = fts3ColumnlistCount(&pIter);
|
|
if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
|
|
if( p->flag==FTS3_MATCHINFO_LHITS ){
|
|
@@ -177768,11 +183060,15 @@
|
|
Fts3Table *pTab,
|
|
sqlite3_stmt **ppStmt,
|
|
sqlite3_int64 *pnDoc,
|
|
- const char **paLen
|
|
+ const char **paLen,
|
|
+ const char **ppEnd
|
|
){
|
|
sqlite3_stmt *pStmt;
|
|
const char *a;
|
|
+ const char *pEnd;
|
|
sqlite3_int64 nDoc;
|
|
+ int n;
|
|
+
|
|
|
|
if( !*ppStmt ){
|
|
int rc = sqlite3Fts3SelectDoctotal(pTab, ppStmt);
|
|
@@ -177781,12 +183077,20 @@
|
|
pStmt = *ppStmt;
|
|
assert( sqlite3_data_count(pStmt)==1 );
|
|
|
|
+ n = sqlite3_column_bytes(pStmt, 0);
|
|
a = sqlite3_column_blob(pStmt, 0);
|
|
- a += sqlite3Fts3GetVarint(a, &nDoc);
|
|
- if( nDoc==0 ) return FTS_CORRUPT_VTAB;
|
|
- *pnDoc = (u32)nDoc;
|
|
+ if( a==0 ){
|
|
+ return FTS_CORRUPT_VTAB;
|
|
+ }
|
|
+ pEnd = a + n;
|
|
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nDoc);
|
|
+ if( nDoc<=0 || a>pEnd ){
|
|
+ return FTS_CORRUPT_VTAB;
|
|
+ }
|
|
+ *pnDoc = nDoc;
|
|
|
|
if( paLen ) *paLen = a;
|
|
+ if( ppEnd ) *ppEnd = pEnd;
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
@@ -177967,7 +183271,7 @@
|
|
case FTS3_MATCHINFO_NDOC:
|
|
if( bGlobal ){
|
|
sqlite3_int64 nDoc = 0;
|
|
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0);
|
|
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, 0, 0);
|
|
pInfo->aMatchinfo[0] = (u32)nDoc;
|
|
}
|
|
break;
|
|
@@ -177976,14 +183280,19 @@
|
|
if( bGlobal ){
|
|
sqlite3_int64 nDoc; /* Number of rows in table */
|
|
const char *a; /* Aggregate column length array */
|
|
+ const char *pEnd; /* First byte past end of length array */
|
|
|
|
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a);
|
|
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &nDoc, &a, &pEnd);
|
|
if( rc==SQLITE_OK ){
|
|
int iCol;
|
|
for(iCol=0; iCol<pInfo->nCol; iCol++){
|
|
u32 iVal;
|
|
sqlite3_int64 nToken;
|
|
a += sqlite3Fts3GetVarint(a, &nToken);
|
|
+ if( a>pEnd ){
|
|
+ rc = SQLITE_CORRUPT_VTAB;
|
|
+ break;
|
|
+ }
|
|
iVal = (u32)(((u32)(nToken&0xffffffff)+nDoc/2)/nDoc);
|
|
pInfo->aMatchinfo[iCol] = iVal;
|
|
}
|
|
@@ -177997,9 +183306,14 @@
|
|
if( rc==SQLITE_OK ){
|
|
int iCol;
|
|
const char *a = sqlite3_column_blob(pSelectDocsize, 0);
|
|
+ const char *pEnd = a + sqlite3_column_bytes(pSelectDocsize, 0);
|
|
for(iCol=0; iCol<pInfo->nCol; iCol++){
|
|
sqlite3_int64 nToken;
|
|
- a += sqlite3Fts3GetVarint(a, &nToken);
|
|
+ a += sqlite3Fts3GetVarintBounded(a, pEnd, &nToken);
|
|
+ if( a>pEnd ){
|
|
+ rc = SQLITE_CORRUPT_VTAB;
|
|
+ break;
|
|
+ }
|
|
pInfo->aMatchinfo[iCol] = (u32)nToken;
|
|
}
|
|
}
|
|
@@ -178030,7 +183344,7 @@
|
|
if( rc!=SQLITE_OK ) break;
|
|
if( bGlobal ){
|
|
if( pCsr->pDeferred ){
|
|
- rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc, 0);
|
|
+ rc = fts3MatchinfoSelectDoctotal(pTab, &pSelect, &pInfo->nDoc,0,0);
|
|
if( rc!=SQLITE_OK ) break;
|
|
}
|
|
rc = fts3ExprIterate(pExpr, fts3ExprGlobalHitsCb,(void*)pInfo);
|
|
@@ -179498,6 +184812,7 @@
|
|
/* Append N bytes from zIn onto the end of the JsonString string.
|
|
*/
|
|
static void jsonAppendRaw(JsonString *p, const char *zIn, u32 N){
|
|
+ if( N==0 ) return;
|
|
if( (N+p->nUsed >= p->nAlloc) && jsonGrow(p,N)!=0 ) return;
|
|
memcpy(p->zBuf+p->nUsed, zIn, N);
|
|
p->nUsed += N;
|
|
@@ -179766,6 +185081,37 @@
|
|
sqlite3_result_subtype(pCtx, JSON_SUBTYPE);
|
|
}
|
|
|
|
+/*
|
|
+** Translate a single byte of Hex into an integer.
|
|
+** This routine only works if h really is a valid hexadecimal
|
|
+** character: 0..9a..fA..F
|
|
+*/
|
|
+static u8 jsonHexToInt(int h){
|
|
+ assert( (h>='0' && h<='9') || (h>='a' && h<='f') || (h>='A' && h<='F') );
|
|
+#ifdef SQLITE_EBCDIC
|
|
+ h += 9*(1&~(h>>4));
|
|
+#else
|
|
+ h += 9*(1&(h>>6));
|
|
+#endif
|
|
+ return (u8)(h & 0xf);
|
|
+}
|
|
+
|
|
+/*
|
|
+** Convert a 4-byte hex string into an integer
|
|
+*/
|
|
+static u32 jsonHexToInt4(const char *z){
|
|
+ u32 v;
|
|
+ assert( safe_isxdigit(z[0]) );
|
|
+ assert( safe_isxdigit(z[1]) );
|
|
+ assert( safe_isxdigit(z[2]) );
|
|
+ assert( safe_isxdigit(z[3]) );
|
|
+ v = (jsonHexToInt(z[0])<<12)
|
|
+ + (jsonHexToInt(z[1])<<8)
|
|
+ + (jsonHexToInt(z[2])<<4)
|
|
+ + jsonHexToInt(z[3]);
|
|
+ return v;
|
|
+}
|
|
+
|
|
/*
|
|
** Make the JsonNode the return value of the function.
|
|
*/
|
|
@@ -179859,15 +185205,8 @@
|
|
}else{
|
|
c = z[++i];
|
|
if( c=='u' ){
|
|
- u32 v = 0, k;
|
|
- for(k=0; k<4; i++, k++){
|
|
- assert( i<n-2 );
|
|
- c = z[i+1];
|
|
- assert( safe_isxdigit(c) );
|
|
- if( c<='9' ) v = v*16 + c - '0';
|
|
- else if( c<='F' ) v = v*16 + c - 'A' + 10;
|
|
- else v = v*16 + c - 'a' + 10;
|
|
- }
|
|
+ u32 v = jsonHexToInt4(z+i+1);
|
|
+ i += 4;
|
|
if( v==0 ) break;
|
|
if( v<=0x7f ){
|
|
zOut[j++] = (char)v;
|
|
@@ -179875,9 +185214,25 @@
|
|
zOut[j++] = (char)(0xc0 | (v>>6));
|
|
zOut[j++] = 0x80 | (v&0x3f);
|
|
}else{
|
|
- zOut[j++] = (char)(0xe0 | (v>>12));
|
|
- zOut[j++] = 0x80 | ((v>>6)&0x3f);
|
|
- zOut[j++] = 0x80 | (v&0x3f);
|
|
+ u32 vlo;
|
|
+ if( (v&0xfc00)==0xd800
|
|
+ && i<n-6
|
|
+ && z[i+1]=='\\'
|
|
+ && z[i+2]=='u'
|
|
+ && ((vlo = jsonHexToInt4(z+i+3))&0xfc00)==0xdc00
|
|
+ ){
|
|
+ /* We have a surrogate pair */
|
|
+ v = ((v&0x3ff)<<10) + (vlo&0x3ff) + 0x10000;
|
|
+ i += 6;
|
|
+ zOut[j++] = 0xf0 | (v>>18);
|
|
+ zOut[j++] = 0x80 | ((v>>12)&0x3f);
|
|
+ zOut[j++] = 0x80 | ((v>>6)&0x3f);
|
|
+ zOut[j++] = 0x80 | (v&0x3f);
|
|
+ }else{
|
|
+ zOut[j++] = 0xe0 | (v>>12);
|
|
+ zOut[j++] = 0x80 | ((v>>6)&0x3f);
|
|
+ zOut[j++] = 0x80 | (v&0x3f);
|
|
+ }
|
|
}
|
|
}else{
|
|
if( c=='b' ){
|
|
@@ -180327,6 +185682,7 @@
|
|
const char *zKey;
|
|
JsonNode *pRoot = &pParse->aNode[iRoot];
|
|
if( zPath[0]==0 ) return pRoot;
|
|
+ if( pRoot->jnFlags & JNODE_REPLACE ) return 0;
|
|
if( zPath[0]=='.' ){
|
|
if( pRoot->eType!=JSON_OBJECT ) return 0;
|
|
zPath++;
|
|
@@ -180379,18 +185735,49 @@
|
|
}
|
|
return pNode;
|
|
}
|
|
- }else if( zPath[0]=='[' && safe_isdigit(zPath[1]) ){
|
|
- if( pRoot->eType!=JSON_ARRAY ) return 0;
|
|
+ }else if( zPath[0]=='[' ){
|
|
i = 0;
|
|
j = 1;
|
|
while( safe_isdigit(zPath[j]) ){
|
|
i = i*10 + zPath[j] - '0';
|
|
j++;
|
|
}
|
|
- if( zPath[j]!=']' ){
|
|
- *pzErr = zPath;
|
|
- return 0;
|
|
+ if( j<2 || zPath[j]!=']' ){
|
|
+ if( zPath[1]=='#' ){
|
|
+ JsonNode *pBase = pRoot;
|
|
+ int iBase = iRoot;
|
|
+ if( pRoot->eType!=JSON_ARRAY ) return 0;
|
|
+ for(;;){
|
|
+ while( j<=pBase->n ){
|
|
+ if( (pBase[j].jnFlags & JNODE_REMOVE)==0 ) i++;
|
|
+ j += jsonNodeSize(&pBase[j]);
|
|
+ }
|
|
+ if( (pBase->jnFlags & JNODE_APPEND)==0 ) break;
|
|
+ iBase += pBase->u.iAppend;
|
|
+ pBase = &pParse->aNode[iBase];
|
|
+ j = 1;
|
|
+ }
|
|
+ j = 2;
|
|
+ if( zPath[2]=='-' && safe_isdigit(zPath[3]) ){
|
|
+ unsigned int x = 0;
|
|
+ j = 3;
|
|
+ do{
|
|
+ x = x*10 + zPath[j] - '0';
|
|
+ j++;
|
|
+ }while( safe_isdigit(zPath[j]) );
|
|
+ if( x>i ) return 0;
|
|
+ i -= x;
|
|
+ }
|
|
+ if( zPath[j]!=']' ){
|
|
+ *pzErr = zPath;
|
|
+ return 0;
|
|
+ }
|
|
+ }else{
|
|
+ *pzErr = zPath;
|
|
+ return 0;
|
|
+ }
|
|
}
|
|
+ if( pRoot->eType!=JSON_ARRAY ) return 0;
|
|
zPath += j + 1;
|
|
j = 1;
|
|
for(;;){
|
|
@@ -181063,7 +186450,7 @@
|
|
if( pStr->zBuf==0 ){
|
|
jsonInit(pStr, ctx);
|
|
jsonAppendChar(pStr, '[');
|
|
- }else{
|
|
+ }else if( pStr->nUsed>1 ){
|
|
jsonAppendChar(pStr, ',');
|
|
pStr->pCtx = ctx;
|
|
}
|
|
@@ -181111,9 +186498,11 @@
|
|
int argc,
|
|
sqlite3_value **argv
|
|
){
|
|
- int i;
|
|
+ unsigned int i;
|
|
int inStr = 0;
|
|
+ int nNest = 0;
|
|
char *z;
|
|
+ char c;
|
|
JsonString *pStr;
|
|
UNUSED_PARAM(argc);
|
|
UNUSED_PARAM(argv);
|
|
@@ -181124,12 +186513,18 @@
|
|
if( NEVER(!pStr) ) return;
|
|
#endif
|
|
z = pStr->zBuf;
|
|
- for(i=1; z[i]!=',' || inStr; i++){
|
|
- assert( i<pStr->nUsed );
|
|
- if( z[i]=='"' ){
|
|
+ for(i=1; (c = z[i])!=',' || inStr || nNest; i++){
|
|
+ if( i>=pStr->nUsed ){
|
|
+ pStr->nUsed = 1;
|
|
+ return;
|
|
+ }
|
|
+ if( c=='"' ){
|
|
inStr = !inStr;
|
|
- }else if( z[i]=='\\' ){
|
|
+ }else if( c=='\\' ){
|
|
i++;
|
|
+ }else if( !inStr ){
|
|
+ if( c=='{' || c=='[' ) nNest++;
|
|
+ if( c=='}' || c==']' ) nNest--;
|
|
}
|
|
}
|
|
pStr->nUsed -= i;
|
|
@@ -181159,7 +186554,7 @@
|
|
if( pStr->zBuf==0 ){
|
|
jsonInit(pStr, ctx);
|
|
jsonAppendChar(pStr, '{');
|
|
- }else{
|
|
+ }else if( pStr->nUsed>1 ){
|
|
jsonAppendChar(pStr, ',');
|
|
pStr->pCtx = ctx;
|
|
}
|
|
@@ -181255,6 +186650,7 @@
|
|
pNew = *ppVtab = sqlite3_malloc( sizeof(*pNew) );
|
|
if( pNew==0 ) return SQLITE_NOMEM;
|
|
memset(pNew, 0, sizeof(*pNew));
|
|
+ sqlite3_vtab_config(db, SQLITE_VTAB_INNOCUOUS);
|
|
}
|
|
return rc;
|
|
}
|
|
@@ -181745,16 +187141,19 @@
|
|
{ "json_tree", &jsonTreeModule },
|
|
};
|
|
#endif
|
|
+ static const int enc =
|
|
+ SQLITE_UTF8 |
|
|
+ SQLITE_DETERMINISTIC |
|
|
+ SQLITE_INNOCUOUS;
|
|
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
|
- rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
|
|
- SQLITE_UTF8 | SQLITE_DETERMINISTIC,
|
|
+ rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg, enc,
|
|
(void*)&aFunc[i].flag,
|
|
aFunc[i].xFunc, 0, 0);
|
|
}
|
|
#ifndef SQLITE_OMIT_WINDOWFUNC
|
|
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
|
|
rc = sqlite3_create_window_function(db, aAgg[i].zName, aAgg[i].nArg,
|
|
- SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
|
|
+ SQLITE_SUBTYPE | enc, 0,
|
|
aAgg[i].xStep, aAgg[i].xFinal,
|
|
aAgg[i].xValue, jsonGroupInverse, 0);
|
|
}
|
|
@@ -181850,6 +187249,7 @@
|
|
#else
|
|
/* #include "sqlite3.h" */
|
|
#endif
|
|
+SQLITE_PRIVATE int sqlite3GetToken(const unsigned char*,int*); /* In the SQLite core */
|
|
|
|
#ifndef SQLITE_AMALGAMATION
|
|
#include "sqlite3rtree.h"
|
|
@@ -182113,6 +187513,12 @@
|
|
#define RTREE_MATCH 0x46 /* F: Old-style sqlite3_rtree_geometry_callback() */
|
|
#define RTREE_QUERY 0x47 /* G: New-style sqlite3_rtree_query_callback() */
|
|
|
|
+/* Special operators available only on cursors. Needs to be consecutive
|
|
+** with the normal values above, but must be less than RTREE_MATCH. These
|
|
+** are used in the cursor for contraints such as x=NULL (RTREE_FALSE) or
|
|
+** x<'xyz' (RTREE_TRUE) */
|
|
+#define RTREE_TRUE 0x3f /* ? */
|
|
+#define RTREE_FALSE 0x40 /* @ */
|
|
|
|
/*
|
|
** An rtree structure node.
|
|
@@ -182457,7 +187863,6 @@
|
|
** increase its reference count and return it.
|
|
*/
|
|
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
|
|
- assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
|
|
if( pParent && !pNode->pParent ){
|
|
if( nodeInParentChain(pNode, pParent) ){
|
|
RTREE_IS_CORRUPT(pRtree);
|
|
@@ -182465,6 +187870,9 @@
|
|
}
|
|
pParent->nRef++;
|
|
pNode->pParent = pParent;
|
|
+ }else if( pParent && pNode->pParent && pParent!=pNode->pParent ){
|
|
+ RTREE_IS_CORRUPT(pRtree);
|
|
+ return SQLITE_CORRUPT_VTAB;
|
|
}
|
|
pNode->nRef++;
|
|
*ppNode = pNode;
|
|
@@ -182844,9 +188252,12 @@
|
|
|
|
|
|
/*
|
|
-** Free the RtreeCursor.aConstraint[] array and its contents.
|
|
+** Reset a cursor back to its initial state.
|
|
*/
|
|
-static void freeCursorConstraints(RtreeCursor *pCsr){
|
|
+static void resetCursor(RtreeCursor *pCsr){
|
|
+ Rtree *pRtree = (Rtree *)(pCsr->base.pVtab);
|
|
+ int ii;
|
|
+ sqlite3_stmt *pStmt;
|
|
if( pCsr->aConstraint ){
|
|
int i; /* Used to iterate through constraint array */
|
|
for(i=0; i<pCsr->nConstraint; i++){
|
|
@@ -182859,6 +188270,13 @@
|
|
sqlite3_free(pCsr->aConstraint);
|
|
pCsr->aConstraint = 0;
|
|
}
|
|
+ for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
|
|
+ sqlite3_free(pCsr->aPoint);
|
|
+ pStmt = pCsr->pReadAux;
|
|
+ memset(pCsr, 0, sizeof(RtreeCursor));
|
|
+ pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
|
|
+ pCsr->pReadAux = pStmt;
|
|
+
|
|
}
|
|
|
|
/*
|
|
@@ -182866,13 +188284,10 @@
|
|
*/
|
|
static int rtreeClose(sqlite3_vtab_cursor *cur){
|
|
Rtree *pRtree = (Rtree *)(cur->pVtab);
|
|
- int ii;
|
|
RtreeCursor *pCsr = (RtreeCursor *)cur;
|
|
assert( pRtree->nCursor>0 );
|
|
- freeCursorConstraints(pCsr);
|
|
+ resetCursor(pCsr);
|
|
sqlite3_finalize(pCsr->pReadAux);
|
|
- sqlite3_free(pCsr->aPoint);
|
|
- for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
|
|
sqlite3_free(pCsr);
|
|
pRtree->nCursor--;
|
|
nodeBlobReset(pRtree);
|
|
@@ -183030,9 +188445,12 @@
|
|
pCellData += 8 + 4*(p->iCoord&0xfe);
|
|
|
|
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|
|
- || p->op==RTREE_GT || p->op==RTREE_EQ );
|
|
+ || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
|
|
+ || p->op==RTREE_FALSE );
|
|
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
|
|
switch( p->op ){
|
|
+ case RTREE_TRUE: return; /* Always satisfied */
|
|
+ case RTREE_FALSE: break; /* Never satisfied */
|
|
case RTREE_LE:
|
|
case RTREE_LT:
|
|
case RTREE_EQ:
|
|
@@ -183070,16 +188488,19 @@
|
|
RtreeDValue xN; /* Coordinate value converted to a double */
|
|
|
|
assert(p->op==RTREE_LE || p->op==RTREE_LT || p->op==RTREE_GE
|
|
- || p->op==RTREE_GT || p->op==RTREE_EQ );
|
|
+ || p->op==RTREE_GT || p->op==RTREE_EQ || p->op==RTREE_TRUE
|
|
+ || p->op==RTREE_FALSE );
|
|
pCellData += 8 + p->iCoord*4;
|
|
assert( ((((char*)pCellData) - (char*)0)&3)==0 ); /* 4-byte aligned */
|
|
RTREE_DECODE_COORD(eInt, pCellData, xN);
|
|
switch( p->op ){
|
|
- case RTREE_LE: if( xN <= p->u.rValue ) return; break;
|
|
- case RTREE_LT: if( xN < p->u.rValue ) return; break;
|
|
- case RTREE_GE: if( xN >= p->u.rValue ) return; break;
|
|
- case RTREE_GT: if( xN > p->u.rValue ) return; break;
|
|
- default: if( xN == p->u.rValue ) return; break;
|
|
+ case RTREE_TRUE: return; /* Always satisfied */
|
|
+ case RTREE_FALSE: break; /* Never satisfied */
|
|
+ case RTREE_LE: if( xN <= p->u.rValue ) return; break;
|
|
+ case RTREE_LT: if( xN < p->u.rValue ) return; break;
|
|
+ case RTREE_GE: if( xN >= p->u.rValue ) return; break;
|
|
+ case RTREE_GT: if( xN > p->u.rValue ) return; break;
|
|
+ default: if( xN == p->u.rValue ) return; break;
|
|
}
|
|
*peWithin = NOT_WITHIN;
|
|
}
|
|
@@ -183352,13 +188773,14 @@
|
|
|
|
eInt = pRtree->eCoordType==RTREE_COORD_INT32;
|
|
while( (p = rtreeSearchPointFirst(pCur))!=0 && p->iLevel>0 ){
|
|
+ u8 *pCellData;
|
|
pNode = rtreeNodeOfFirstSearchPoint(pCur, &rc);
|
|
if( rc ) return rc;
|
|
nCell = NCELL(pNode);
|
|
assert( nCell<200 );
|
|
+ pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
|
|
while( p->iCell<nCell ){
|
|
sqlite3_rtree_dbl rScore = (sqlite3_rtree_dbl)-1;
|
|
- u8 *pCellData = pNode->zData + (4+pRtree->nBytesPerCell*p->iCell);
|
|
eWithin = FULLY_WITHIN;
|
|
for(ii=0; ii<nConstraint; ii++){
|
|
RtreeConstraint *pConstraint = pCur->aConstraint + ii;
|
|
@@ -183371,13 +188793,23 @@
|
|
}else{
|
|
rtreeNonleafConstraint(pConstraint, eInt, pCellData, &eWithin);
|
|
}
|
|
- if( eWithin==NOT_WITHIN ) break;
|
|
+ if( eWithin==NOT_WITHIN ){
|
|
+ p->iCell++;
|
|
+ pCellData += pRtree->nBytesPerCell;
|
|
+ break;
|
|
+ }
|
|
}
|
|
- p->iCell++;
|
|
if( eWithin==NOT_WITHIN ) continue;
|
|
+ p->iCell++;
|
|
x.iLevel = p->iLevel - 1;
|
|
if( x.iLevel ){
|
|
x.id = readInt64(pCellData);
|
|
+ for(ii=0; ii<pCur->nPoint; ii++){
|
|
+ if( pCur->aPoint[ii].id==x.id ){
|
|
+ RTREE_IS_CORRUPT(pRtree);
|
|
+ return SQLITE_CORRUPT_VTAB;
|
|
+ }
|
|
+ }
|
|
x.iCell = 0;
|
|
}else{
|
|
x.id = p->id;
|
|
@@ -183561,17 +188993,11 @@
|
|
int ii;
|
|
int rc = SQLITE_OK;
|
|
int iCell = 0;
|
|
- sqlite3_stmt *pStmt;
|
|
|
|
rtreeReference(pRtree);
|
|
|
|
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
|
|
- freeCursorConstraints(pCsr);
|
|
- sqlite3_free(pCsr->aPoint);
|
|
- pStmt = pCsr->pReadAux;
|
|
- memset(pCsr, 0, sizeof(RtreeCursor));
|
|
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
|
|
- pCsr->pReadAux = pStmt;
|
|
+ resetCursor(pCsr);
|
|
|
|
pCsr->iStrategy = idxNum;
|
|
if( idxNum==1 ){
|
|
@@ -183580,7 +189006,15 @@
|
|
RtreeSearchPoint *p; /* Search point for the leaf */
|
|
i64 iRowid = sqlite3_value_int64(argv[0]);
|
|
i64 iNode = 0;
|
|
- rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
|
|
+ int eType = sqlite3_value_numeric_type(argv[0]);
|
|
+ if( eType==SQLITE_INTEGER
|
|
+ || (eType==SQLITE_FLOAT && sqlite3_value_double(argv[0])==iRowid)
|
|
+ ){
|
|
+ rc = findLeafNode(pRtree, iRowid, &pLeaf, &iNode);
|
|
+ }else{
|
|
+ rc = SQLITE_OK;
|
|
+ pLeaf = 0;
|
|
+ }
|
|
if( rc==SQLITE_OK && pLeaf!=0 ){
|
|
p = rtreeSearchPointNew(pCsr, RTREE_ZERO, 0);
|
|
assert( p!=0 ); /* Always returns pCsr->sPoint */
|
|
@@ -183610,6 +189044,7 @@
|
|
|| (idxStr && (int)strlen(idxStr)==argc*2) );
|
|
for(ii=0; ii<argc; ii++){
|
|
RtreeConstraint *p = &pCsr->aConstraint[ii];
|
|
+ int eType = sqlite3_value_numeric_type(argv[ii]);
|
|
p->op = idxStr[ii*2];
|
|
p->iCoord = idxStr[ii*2+1]-'0';
|
|
if( p->op>=RTREE_MATCH ){
|
|
@@ -183624,12 +189059,21 @@
|
|
p->pInfo->nCoord = pRtree->nDim2;
|
|
p->pInfo->anQueue = pCsr->anQueue;
|
|
p->pInfo->mxLevel = pRtree->iDepth + 1;
|
|
- }else{
|
|
+ }else if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){
|
|
#ifdef SQLITE_RTREE_INT_ONLY
|
|
p->u.rValue = sqlite3_value_int64(argv[ii]);
|
|
#else
|
|
p->u.rValue = sqlite3_value_double(argv[ii]);
|
|
#endif
|
|
+ }else{
|
|
+ p->u.rValue = RTREE_ZERO;
|
|
+ if( eType==SQLITE_NULL ){
|
|
+ p->op = RTREE_FALSE;
|
|
+ }else if( p->op==RTREE_LT || p->op==RTREE_LE ){
|
|
+ p->op = RTREE_TRUE;
|
|
+ }else{
|
|
+ p->op = RTREE_FALSE;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -185406,6 +190850,14 @@
|
|
return rc;
|
|
}
|
|
|
|
+/*
|
|
+** Return the length of a token
|
|
+*/
|
|
+static int rtreeTokenLength(const char *z){
|
|
+ int dummy = 0;
|
|
+ return sqlite3GetToken((const unsigned char*)z,&dummy);
|
|
+}
|
|
+
|
|
/*
|
|
** This function is the implementation of both the xConnect and xCreate
|
|
** methods of the r-tree virtual table.
|
|
@@ -185442,8 +190894,8 @@
|
|
};
|
|
|
|
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
|
|
- if( argc>RTREE_MAX_AUX_COLUMN+3 ){
|
|
- *pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
|
|
+ if( argc<6 || argc>RTREE_MAX_AUX_COLUMN+3 ){
|
|
+ *pzErr = sqlite3_mprintf("%s", aErrMsg[2 + (argc>=6)]);
|
|
return SQLITE_ERROR;
|
|
}
|
|
|
|
@@ -185471,16 +190923,20 @@
|
|
** the r-tree table schema.
|
|
*/
|
|
pSql = sqlite3_str_new(db);
|
|
- sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
|
|
+ sqlite3_str_appendf(pSql, "CREATE TABLE x(%.*s INT",
|
|
+ rtreeTokenLength(argv[3]), argv[3]);
|
|
for(ii=4; ii<argc; ii++){
|
|
- if( argv[ii][0]=='+' ){
|
|
+ const char *zArg = argv[ii];
|
|
+ if( zArg[0]=='+' ){
|
|
pRtree->nAux++;
|
|
- sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
|
|
+ sqlite3_str_appendf(pSql, ",%.*s", rtreeTokenLength(zArg+1), zArg+1);
|
|
}else if( pRtree->nAux>0 ){
|
|
break;
|
|
}else{
|
|
+ static const char *azFormat[] = {",%.*s REAL", ",%.*s INT"};
|
|
pRtree->nDim2++;
|
|
- sqlite3_str_appendf(pSql, ",%s", argv[ii]);
|
|
+ sqlite3_str_appendf(pSql, azFormat[eCoordType],
|
|
+ rtreeTokenLength(zArg), zArg);
|
|
}
|
|
}
|
|
sqlite3_str_appendf(pSql, ");");
|
|
@@ -187428,17 +192884,11 @@
|
|
RtreeNode *pRoot = 0;
|
|
int rc = SQLITE_OK;
|
|
int iCell = 0;
|
|
- sqlite3_stmt *pStmt;
|
|
|
|
rtreeReference(pRtree);
|
|
|
|
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
|
|
- freeCursorConstraints(pCsr);
|
|
- sqlite3_free(pCsr->aPoint);
|
|
- pStmt = pCsr->pReadAux;
|
|
- memset(pCsr, 0, sizeof(RtreeCursor));
|
|
- pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
|
|
- pCsr->pReadAux = pStmt;
|
|
+ resetCursor(pCsr);
|
|
|
|
pCsr->iStrategy = idxNum;
|
|
if( idxNum==1 ){
|
|
@@ -187875,14 +193325,20 @@
|
|
};
|
|
int i;
|
|
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
|
|
- int enc = aFunc[i].bPure ? SQLITE_UTF8|SQLITE_DETERMINISTIC : SQLITE_UTF8;
|
|
+ int enc;
|
|
+ if( aFunc[i].bPure ){
|
|
+ enc = SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS;
|
|
+ }else{
|
|
+ enc = SQLITE_UTF8|SQLITE_DIRECTONLY;
|
|
+ }
|
|
rc = sqlite3_create_function(db, aFunc[i].zName, aFunc[i].nArg,
|
|
enc, 0,
|
|
aFunc[i].xFunc, 0, 0);
|
|
}
|
|
for(i=0; i<sizeof(aAgg)/sizeof(aAgg[0]) && rc==SQLITE_OK; i++){
|
|
- rc = sqlite3_create_function(db, aAgg[i].zName, 1, SQLITE_UTF8, 0,
|
|
- 0, aAgg[i].xStep, aAgg[i].xFinal);
|
|
+ rc = sqlite3_create_function(db, aAgg[i].zName, 1,
|
|
+ SQLITE_UTF8|SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS, 0,
|
|
+ 0, aAgg[i].xStep, aAgg[i].xFinal);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
rc = sqlite3_create_module_v2(db, "geopoly", &geopolyModule, 0, 0);
|
|
@@ -188216,7 +193672,7 @@
|
|
** 3. uPattern is an unescaped escape character, or
|
|
** 4. uPattern is to be handled as an ordinary character
|
|
*/
|
|
- if( !prevEscape && uPattern==MATCH_ALL ){
|
|
+ if( uPattern==MATCH_ALL && !prevEscape && uPattern!=(uint32_t)uEsc ){
|
|
/* Case 1. */
|
|
uint8_t c;
|
|
|
|
@@ -188242,12 +193698,12 @@
|
|
}
|
|
return 0;
|
|
|
|
- }else if( !prevEscape && uPattern==MATCH_ONE ){
|
|
+ }else if( uPattern==MATCH_ONE && !prevEscape && uPattern!=(uint32_t)uEsc ){
|
|
/* Case 2. */
|
|
if( *zString==0 ) return 0;
|
|
SQLITE_ICU_SKIP_UTF8(zString);
|
|
|
|
- }else if( !prevEscape && uPattern==(uint32_t)uEsc){
|
|
+ }else if( uPattern==(uint32_t)uEsc && !prevEscape ){
|
|
/* Case 3. */
|
|
prevEscape = 1;
|
|
|
|
@@ -188572,26 +194028,27 @@
|
|
** Register the ICU extension functions with database db.
|
|
*/
|
|
SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
|
|
+# define SQLITEICU_EXTRAFLAGS (SQLITE_DETERMINISTIC|SQLITE_INNOCUOUS)
|
|
static const struct IcuScalar {
|
|
const char *zName; /* Function name */
|
|
unsigned char nArg; /* Number of arguments */
|
|
- unsigned short enc; /* Optimal text encoding */
|
|
+ unsigned int enc; /* Optimal text encoding */
|
|
unsigned char iContext; /* sqlite3_user_data() context */
|
|
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
|
|
} scalars[] = {
|
|
- {"icu_load_collation", 2, SQLITE_UTF8, 1, icuLoadCollation},
|
|
+ {"icu_load_collation",2,SQLITE_UTF8|SQLITE_DIRECTONLY,1, icuLoadCollation},
|
|
#if !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU)
|
|
- {"regexp", 2, SQLITE_ANY|SQLITE_DETERMINISTIC, 0, icuRegexpFunc},
|
|
- {"lower", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
|
- {"lower", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
|
- {"upper", 1, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
|
- {"upper", 2, SQLITE_UTF16|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
|
- {"lower", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
|
- {"lower", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuCaseFunc16},
|
|
- {"upper", 1, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
|
- {"upper", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 1, icuCaseFunc16},
|
|
- {"like", 2, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
|
|
- {"like", 3, SQLITE_UTF8|SQLITE_DETERMINISTIC, 0, icuLikeFunc},
|
|
+ {"regexp", 2, SQLITE_ANY|SQLITEICU_EXTRAFLAGS, 0, icuRegexpFunc},
|
|
+ {"lower", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
|
+ {"lower", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
|
+ {"upper", 1, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
|
+ {"upper", 2, SQLITE_UTF16|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
|
+ {"lower", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
|
+ {"lower", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuCaseFunc16},
|
|
+ {"upper", 1, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
|
+ {"upper", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 1, icuCaseFunc16},
|
|
+ {"like", 2, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuLikeFunc},
|
|
+ {"like", 3, SQLITE_UTF8|SQLITEICU_EXTRAFLAGS, 0, icuLikeFunc},
|
|
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ICU) */
|
|
};
|
|
int rc = SQLITE_OK;
|
|
@@ -189685,6 +195142,7 @@
|
|
typedef struct RbuFrame RbuFrame;
|
|
typedef struct RbuObjIter RbuObjIter;
|
|
typedef struct RbuState RbuState;
|
|
+typedef struct RbuSpan RbuSpan;
|
|
typedef struct rbu_vfs rbu_vfs;
|
|
typedef struct rbu_file rbu_file;
|
|
typedef struct RbuUpdateStmt RbuUpdateStmt;
|
|
@@ -189729,6 +195187,11 @@
|
|
RbuUpdateStmt *pNext;
|
|
};
|
|
|
|
+struct RbuSpan {
|
|
+ const char *zSpan;
|
|
+ int nSpan;
|
|
+};
|
|
+
|
|
/*
|
|
** An iterator of this type is used to iterate through all objects in
|
|
** the target database that require updating. For each such table, the
|
|
@@ -189778,6 +195241,9 @@
|
|
sqlite3_stmt *pInsert; /* Statement for INSERT operations */
|
|
sqlite3_stmt *pDelete; /* Statement for DELETE ops */
|
|
sqlite3_stmt *pTmpInsert; /* Insert into rbu_tmp_$zDataTbl */
|
|
+ int nIdxCol;
|
|
+ RbuSpan *aIdxCol;
|
|
+ char *zIdxSql;
|
|
|
|
/* Last UPDATE used (for PK b-tree updates only), or NULL. */
|
|
RbuUpdateStmt *pRbuUpdate;
|
|
@@ -190312,6 +195778,8 @@
|
|
sqlite3_free(pUp);
|
|
pUp = pTmp;
|
|
}
|
|
+ sqlite3_free(pIter->aIdxCol);
|
|
+ sqlite3_free(pIter->zIdxSql);
|
|
|
|
pIter->pSelect = 0;
|
|
pIter->pInsert = 0;
|
|
@@ -190319,6 +195787,9 @@
|
|
pIter->pRbuUpdate = 0;
|
|
pIter->pTmpInsert = 0;
|
|
pIter->nCol = 0;
|
|
+ pIter->nIdxCol = 0;
|
|
+ pIter->aIdxCol = 0;
|
|
+ pIter->zIdxSql = 0;
|
|
}
|
|
|
|
/*
|
|
@@ -190433,8 +195904,8 @@
|
|
zIn = (const char*)sqlite3_value_text(argv[0]);
|
|
if( zIn ){
|
|
if( rbuIsVacuum(p) ){
|
|
- assert( argc==2 );
|
|
- if( 0==sqlite3_value_int(argv[1]) ){
|
|
+ assert( argc==2 || argc==1 );
|
|
+ if( argc==1 || 0==sqlite3_value_int(argv[1]) ){
|
|
sqlite3_result_text(pCtx, zIn, -1, SQLITE_STATIC);
|
|
}
|
|
}else{
|
|
@@ -190592,14 +196063,15 @@
|
|
static char *rbuStrndup(const char *zStr, int *pRc){
|
|
char *zRet = 0;
|
|
|
|
- assert( *pRc==SQLITE_OK );
|
|
- if( zStr ){
|
|
- size_t nCopy = strlen(zStr) + 1;
|
|
- zRet = (char*)sqlite3_malloc64(nCopy);
|
|
- if( zRet ){
|
|
- memcpy(zRet, zStr, nCopy);
|
|
- }else{
|
|
- *pRc = SQLITE_NOMEM;
|
|
+ if( *pRc==SQLITE_OK ){
|
|
+ if( zStr ){
|
|
+ size_t nCopy = strlen(zStr) + 1;
|
|
+ zRet = (char*)sqlite3_malloc64(nCopy);
|
|
+ if( zRet ){
|
|
+ memcpy(zRet, zStr, nCopy);
|
|
+ }else{
|
|
+ *pRc = SQLITE_NOMEM;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -190771,6 +196243,9 @@
|
|
while( p->rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pXInfo) ){
|
|
int iCid = sqlite3_column_int(pXInfo, 1);
|
|
if( iCid>=0 ) pIter->abIndexed[iCid] = 1;
|
|
+ if( iCid==-2 ){
|
|
+ memset(pIter->abIndexed, 0x01, sizeof(u8)*pIter->nTblCol);
|
|
+ }
|
|
}
|
|
rbuFinalize(p, pXInfo);
|
|
bIndex = 1;
|
|
@@ -191182,29 +196657,37 @@
|
|
int iCid = sqlite3_column_int(pXInfo, 1);
|
|
int bDesc = sqlite3_column_int(pXInfo, 3);
|
|
const char *zCollate = (const char*)sqlite3_column_text(pXInfo, 4);
|
|
- const char *zCol;
|
|
+ const char *zCol = 0;
|
|
const char *zType;
|
|
|
|
- if( iCid<0 ){
|
|
- /* An integer primary key. If the table has an explicit IPK, use
|
|
- ** its name. Otherwise, use "rbu_rowid". */
|
|
- if( pIter->eType==RBU_PK_IPK ){
|
|
- int i;
|
|
- for(i=0; pIter->abTblPk[i]==0; i++);
|
|
- assert( i<pIter->nTblCol );
|
|
- zCol = pIter->azTblCol[i];
|
|
- }else if( rbuIsVacuum(p) ){
|
|
- zCol = "_rowid_";
|
|
+ if( iCid==-2 ){
|
|
+ int iSeq = sqlite3_column_int(pXInfo, 0);
|
|
+ zRet = sqlite3_mprintf("%z%s(%.*s) COLLATE %Q", zRet, zCom,
|
|
+ pIter->aIdxCol[iSeq].nSpan, pIter->aIdxCol[iSeq].zSpan, zCollate
|
|
+ );
|
|
+ zType = "";
|
|
+ }else {
|
|
+ if( iCid<0 ){
|
|
+ /* An integer primary key. If the table has an explicit IPK, use
|
|
+ ** its name. Otherwise, use "rbu_rowid". */
|
|
+ if( pIter->eType==RBU_PK_IPK ){
|
|
+ int i;
|
|
+ for(i=0; pIter->abTblPk[i]==0; i++);
|
|
+ assert( i<pIter->nTblCol );
|
|
+ zCol = pIter->azTblCol[i];
|
|
+ }else if( rbuIsVacuum(p) ){
|
|
+ zCol = "_rowid_";
|
|
+ }else{
|
|
+ zCol = "rbu_rowid";
|
|
+ }
|
|
+ zType = "INTEGER";
|
|
}else{
|
|
- zCol = "rbu_rowid";
|
|
+ zCol = pIter->azTblCol[iCid];
|
|
+ zType = pIter->azTblType[iCid];
|
|
}
|
|
- zType = "INTEGER";
|
|
- }else{
|
|
- zCol = pIter->azTblCol[iCid];
|
|
- zType = pIter->azTblType[iCid];
|
|
+ zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom,zCol,zCollate);
|
|
}
|
|
|
|
- zRet = sqlite3_mprintf("%z%s\"%w\" COLLATE %Q", zRet, zCom, zCol, zCollate);
|
|
if( pIter->bUnique==0 || sqlite3_column_int(pXInfo, 5) ){
|
|
const char *zOrder = (bDesc ? " DESC" : "");
|
|
zImpPK = sqlite3_mprintf("%z%s\"rbu_imp_%d%w\"%s",
|
|
@@ -191684,6 +197167,8 @@
|
|
int rc = p->rc;
|
|
char *zRet = 0;
|
|
|
|
+ assert( pIter->zIdxSql==0 && pIter->nIdxCol==0 && pIter->aIdxCol==0 );
|
|
+
|
|
if( rc==SQLITE_OK ){
|
|
rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg,
|
|
"SELECT trim(sql) FROM sqlite_master WHERE type='index' AND name=?"
|
|
@@ -191693,21 +197178,50 @@
|
|
int rc2;
|
|
rc = sqlite3_bind_text(pStmt, 1, pIter->zIdx, -1, SQLITE_STATIC);
|
|
if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
|
|
- const char *zSql = (const char*)sqlite3_column_text(pStmt, 0);
|
|
+ char *zSql = (char*)sqlite3_column_text(pStmt, 0);
|
|
+ if( zSql ){
|
|
+ pIter->zIdxSql = zSql = rbuStrndup(zSql, &rc);
|
|
+ }
|
|
if( zSql ){
|
|
int nParen = 0; /* Number of open parenthesis */
|
|
int i;
|
|
+ int iIdxCol = 0;
|
|
+ int nIdxAlloc = 0;
|
|
for(i=0; zSql[i]; i++){
|
|
char c = zSql[i];
|
|
+
|
|
+ /* If necessary, grow the pIter->aIdxCol[] array */
|
|
+ if( iIdxCol==nIdxAlloc ){
|
|
+ RbuSpan *aIdxCol = (RbuSpan*)sqlite3_realloc(
|
|
+ pIter->aIdxCol, (nIdxAlloc+16)*sizeof(RbuSpan)
|
|
+ );
|
|
+ if( aIdxCol==0 ){
|
|
+ rc = SQLITE_NOMEM;
|
|
+ break;
|
|
+ }
|
|
+ pIter->aIdxCol = aIdxCol;
|
|
+ nIdxAlloc += 16;
|
|
+ }
|
|
+
|
|
if( c=='(' ){
|
|
+ if( nParen==0 ){
|
|
+ assert( iIdxCol==0 );
|
|
+ pIter->aIdxCol[0].zSpan = &zSql[i+1];
|
|
+ }
|
|
nParen++;
|
|
}
|
|
else if( c==')' ){
|
|
nParen--;
|
|
if( nParen==0 ){
|
|
+ int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
|
|
+ pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
|
|
i++;
|
|
break;
|
|
}
|
|
+ }else if( c==',' && nParen==1 ){
|
|
+ int nSpan = &zSql[i] - pIter->aIdxCol[iIdxCol].zSpan;
|
|
+ pIter->aIdxCol[iIdxCol++].nSpan = nSpan;
|
|
+ pIter->aIdxCol[iIdxCol].zSpan = &zSql[i+1];
|
|
}else if( c=='"' || c=='\'' || c=='`' ){
|
|
for(i++; 1; i++){
|
|
if( zSql[i]==c ){
|
|
@@ -191719,11 +197233,19 @@
|
|
for(i++; 1; i++){
|
|
if( zSql[i]==']' ) break;
|
|
}
|
|
+ }else if( c=='-' && zSql[i+1]=='-' ){
|
|
+ for(i=i+2; zSql[i] && zSql[i]!='\n'; i++);
|
|
+ if( zSql[i]=='\0' ) break;
|
|
+ }else if( c=='/' && zSql[i+1]=='*' ){
|
|
+ for(i=i+2; zSql[i] && (zSql[i]!='*' || zSql[i+1]!='/'); i++);
|
|
+ if( zSql[i]=='\0' ) break;
|
|
+ i++;
|
|
}
|
|
}
|
|
if( zSql[i] ){
|
|
zRet = rbuStrndup(&zSql[i], &rc);
|
|
}
|
|
+ pIter->nIdxCol = iIdxCol;
|
|
}
|
|
}
|
|
|
|
@@ -191768,11 +197290,11 @@
|
|
int nBind = 0;
|
|
|
|
assert( pIter->eType!=RBU_PK_VTAB );
|
|
+ zPart = rbuObjIterGetIndexWhere(p, pIter);
|
|
zCollist = rbuObjIterGetIndexCols(
|
|
p, pIter, &zImposterCols, &zImposterPK, &zWhere, &nBind
|
|
);
|
|
zBind = rbuObjIterGetBindlist(p, nBind);
|
|
- zPart = rbuObjIterGetIndexWhere(p, pIter);
|
|
|
|
/* Create the imposter table used to write to this index. */
|
|
sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, p->dbMain, "main", 0, 1);
|
|
@@ -193298,10 +198820,11 @@
|
|
sqlite3_stmt *pStmt = 0;
|
|
char *zErrmsg = 0;
|
|
int rc;
|
|
+ sqlite3 *db = (rbuIsVacuum(p) ? p->dbRbu : p->dbMain);
|
|
|
|
assert( nVal==1 );
|
|
|
|
- rc = prepareFreeAndCollectError(p->dbMain, &pStmt, &zErrmsg,
|
|
+ rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
|
|
sqlite3_mprintf("SELECT count(*) FROM sqlite_master "
|
|
"WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
|
|
);
|
|
@@ -193316,7 +198839,7 @@
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3_result_int(pCtx, nIndex);
|
|
}else{
|
|
- sqlite3_result_error(pCtx, sqlite3_errmsg(p->dbMain), -1);
|
|
+ sqlite3_result_error(pCtx, sqlite3_errmsg(db), -1);
|
|
}
|
|
}
|
|
|
|
@@ -194373,33 +199896,6 @@
|
|
return rc;
|
|
}
|
|
|
|
-/*
|
|
-** A main database named zName has just been opened. The following
|
|
-** function returns a pointer to a buffer owned by SQLite that contains
|
|
-** the name of the *-wal file this db connection will use. SQLite
|
|
-** happens to pass a pointer to this buffer when using xAccess()
|
|
-** or xOpen() to operate on the *-wal file.
|
|
-*/
|
|
-static const char *rbuMainToWal(const char *zName, int flags){
|
|
- int n = (int)strlen(zName);
|
|
- const char *z = &zName[n];
|
|
- if( flags & SQLITE_OPEN_URI ){
|
|
- int odd = 0;
|
|
- while( 1 ){
|
|
- if( z[0]==0 ){
|
|
- odd = 1 - odd;
|
|
- if( odd && z[1]==0 ) break;
|
|
- }
|
|
- z++;
|
|
- }
|
|
- z += 2;
|
|
- }else{
|
|
- while( *z==0 ) z++;
|
|
- }
|
|
- z += (n + 8 + 1);
|
|
- return z;
|
|
-}
|
|
-
|
|
/*
|
|
** Open an rbu file handle.
|
|
*/
|
|
@@ -194448,7 +199944,7 @@
|
|
** the name of the *-wal file this db connection will use. SQLite
|
|
** happens to pass a pointer to this buffer when using xAccess()
|
|
** or xOpen() to operate on the *-wal file. */
|
|
- pFd->zWal = rbuMainToWal(zName, flags);
|
|
+ pFd->zWal = sqlite3_filename_wal(zName);
|
|
}
|
|
else if( flags & SQLITE_OPEN_WAL ){
|
|
rbu_file *pDb = rbuFindMaindb(pRbuVfs, zName, 0);
|
|
@@ -194463,7 +199959,7 @@
|
|
char *zCopy;
|
|
if( rbuIsVacuum(pDb->pRbu) ){
|
|
zBase = sqlite3_db_filename(pDb->pRbu->dbRbu, "main");
|
|
- zBase = rbuMainToWal(zBase, SQLITE_OPEN_URI);
|
|
+ zBase = sqlite3_filename_wal(zBase);
|
|
}
|
|
nCopy = strlen(zBase);
|
|
zCopy = sqlite3_malloc64(nCopy+2);
|
|
@@ -194783,7 +200279,7 @@
|
|
**
|
|
** This file contains an implementation of the "dbstat" virtual table.
|
|
**
|
|
-** The dbstat virtual table is used to extract low-level formatting
|
|
+** The dbstat virtual table is used to extract low-level storage
|
|
** information from an SQLite database in order to implement the
|
|
** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script
|
|
** for an example implementation.
|
|
@@ -194827,27 +200323,30 @@
|
|
**
|
|
** '/1c2/000/' // Left-most child of 451st child of root
|
|
*/
|
|
-#define VTAB_SCHEMA \
|
|
- "CREATE TABLE xx( " \
|
|
- " name TEXT, /* Name of table or index */" \
|
|
- " path TEXT, /* Path to page from root */" \
|
|
- " pageno INTEGER, /* Page number */" \
|
|
- " pagetype TEXT, /* 'internal', 'leaf' or 'overflow' */" \
|
|
- " ncell INTEGER, /* Cells on page (0 for overflow) */" \
|
|
- " payload INTEGER, /* Bytes of payload on this page */" \
|
|
- " unused INTEGER, /* Bytes of unused space on this page */" \
|
|
- " mx_payload INTEGER, /* Largest payload size of all cells */" \
|
|
- " pgoffset INTEGER, /* Offset of page in file */" \
|
|
- " pgsize INTEGER, /* Size of the page */" \
|
|
- " schema TEXT HIDDEN /* Database schema being analyzed */" \
|
|
- ");"
|
|
-
|
|
-
|
|
+static const char zDbstatSchema[] =
|
|
+ "CREATE TABLE x("
|
|
+ " name TEXT," /* 0 Name of table or index */
|
|
+ " path TEXT," /* 1 Path to page from root (NULL for agg) */
|
|
+ " pageno INTEGER," /* 2 Page number (page count for aggregates) */
|
|
+ " pagetype TEXT," /* 3 'internal', 'leaf', 'overflow', or NULL */
|
|
+ " ncell INTEGER," /* 4 Cells on page (0 for overflow) */
|
|
+ " payload INTEGER," /* 5 Bytes of payload on this page */
|
|
+ " unused INTEGER," /* 6 Bytes of unused space on this page */
|
|
+ " mx_payload INTEGER," /* 7 Largest payload size of all cells */
|
|
+ " pgoffset INTEGER," /* 8 Offset of page in file (NULL for agg) */
|
|
+ " pgsize INTEGER," /* 9 Size of the page (sum for aggregate) */
|
|
+ " schema TEXT HIDDEN," /* 10 Database schema being analyzed */
|
|
+ " aggregate BOOLEAN HIDDEN" /* 11 aggregate info for each table */
|
|
+ ")"
|
|
+;
|
|
+
|
|
+/* Forward reference to data structured used in this module */
|
|
typedef struct StatTable StatTable;
|
|
typedef struct StatCursor StatCursor;
|
|
typedef struct StatPage StatPage;
|
|
typedef struct StatCell StatCell;
|
|
|
|
+/* Size information for a single cell within a btree page */
|
|
struct StatCell {
|
|
int nLocal; /* Bytes of local payload */
|
|
u32 iChildPg; /* Child node (or 0 if this is a leaf) */
|
|
@@ -194857,10 +200356,11 @@
|
|
int iOvfl; /* Iterates through aOvfl[] */
|
|
};
|
|
|
|
+/* Size information for a single btree page */
|
|
struct StatPage {
|
|
- u32 iPgno;
|
|
- DbPage *pPg;
|
|
- int iCell;
|
|
+ u32 iPgno; /* Page number */
|
|
+ DbPage *pPg; /* Page content */
|
|
+ int iCell; /* Current cell */
|
|
|
|
char *zPath; /* Path to this page */
|
|
|
|
@@ -194870,34 +200370,38 @@
|
|
int nUnused; /* Number of unused bytes on page */
|
|
StatCell *aCell; /* Array of parsed cells */
|
|
u32 iRightChildPg; /* Right-child page number (or 0) */
|
|
- int nMxPayload; /* Largest payload of any cell on this page */
|
|
+ int nMxPayload; /* Largest payload of any cell on the page */
|
|
};
|
|
|
|
+/* The cursor for scanning the dbstat virtual table */
|
|
struct StatCursor {
|
|
- sqlite3_vtab_cursor base;
|
|
+ sqlite3_vtab_cursor base; /* base class. MUST BE FIRST! */
|
|
sqlite3_stmt *pStmt; /* Iterates through set of root pages */
|
|
- int isEof; /* After pStmt has returned SQLITE_DONE */
|
|
+ u8 isEof; /* After pStmt has returned SQLITE_DONE */
|
|
+ u8 isAgg; /* Aggregate results for each table */
|
|
int iDb; /* Schema used for this query */
|
|
|
|
- StatPage aPage[32];
|
|
+ StatPage aPage[32]; /* Pages in path to current page */
|
|
int iPage; /* Current entry in aPage[] */
|
|
|
|
/* Values to return. */
|
|
+ u32 iPageno; /* Value of 'pageno' column */
|
|
char *zName; /* Value of 'name' column */
|
|
char *zPath; /* Value of 'path' column */
|
|
- u32 iPageno; /* Value of 'pageno' column */
|
|
char *zPagetype; /* Value of 'pagetype' column */
|
|
+ int nPage; /* Number of pages in current btree */
|
|
int nCell; /* Value of 'ncell' column */
|
|
- int nPayload; /* Value of 'payload' column */
|
|
- int nUnused; /* Value of 'unused' column */
|
|
int nMxPayload; /* Value of 'mx_payload' column */
|
|
+ i64 nUnused; /* Value of 'unused' column */
|
|
+ i64 nPayload; /* Value of 'payload' column */
|
|
i64 iOffset; /* Value of 'pgOffset' column */
|
|
- int szPage; /* Value of 'pgSize' column */
|
|
+ i64 szPage; /* Value of 'pgSize' column */
|
|
};
|
|
|
|
+/* An instance of the DBSTAT virtual table */
|
|
struct StatTable {
|
|
- sqlite3_vtab base;
|
|
- sqlite3 *db;
|
|
+ sqlite3_vtab base; /* base class. MUST BE FIRST! */
|
|
+ sqlite3 *db; /* Database connection that owns this vtab */
|
|
int iDb; /* Index of database to analyze */
|
|
};
|
|
|
|
@@ -194906,7 +200410,7 @@
|
|
#endif
|
|
|
|
/*
|
|
-** Connect to or create a statvfs virtual table.
|
|
+** Connect to or create a new DBSTAT virtual table.
|
|
*/
|
|
static int statConnect(
|
|
sqlite3 *db,
|
|
@@ -194930,7 +200434,8 @@
|
|
}else{
|
|
iDb = 0;
|
|
}
|
|
- rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
|
|
+ sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
|
|
+ rc = sqlite3_declare_vtab(db, zDbstatSchema);
|
|
if( rc==SQLITE_OK ){
|
|
pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
|
|
if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
@@ -194948,7 +200453,7 @@
|
|
}
|
|
|
|
/*
|
|
-** Disconnect from or destroy a statvfs virtual table.
|
|
+** Disconnect from or destroy the DBSTAT virtual table.
|
|
*/
|
|
static int statDisconnect(sqlite3_vtab *pVtab){
|
|
sqlite3_free(pVtab);
|
|
@@ -194956,14 +200461,20 @@
|
|
}
|
|
|
|
/*
|
|
-** There is no "best-index". This virtual table always does a linear
|
|
-** scan. However, a schema=? constraint should cause this table to
|
|
-** operate on a different database schema, so check for it.
|
|
+** Compute the best query strategy and return the result in idxNum.
|
|
**
|
|
-** idxNum is normally 0, but will be 1 if a schema=? constraint exists.
|
|
+** idxNum-Bit Meaning
|
|
+** ---------- ----------------------------------------------
|
|
+** 0x01 There is a schema=? term in the WHERE clause
|
|
+** 0x02 There is a name=? term in the WHERE clause
|
|
+** 0x04 There is an aggregate=? term in the WHERE clause
|
|
+** 0x08 Output should be ordered by name and path
|
|
*/
|
|
static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
|
int i;
|
|
+ int iSchema = -1;
|
|
+ int iName = -1;
|
|
+ int iAgg = -1;
|
|
|
|
/* Look for a valid schema=? constraint. If found, change the idxNum to
|
|
** 1 and request the value of that constraint be sent to xFilter. And
|
|
@@ -194971,16 +200482,41 @@
|
|
** used.
|
|
*/
|
|
for(i=0; i<pIdxInfo->nConstraint; i++){
|
|
- if( pIdxInfo->aConstraint[i].iColumn!=10 ) continue;
|
|
- if( pIdxInfo->aConstraint[i].usable==0 ) return SQLITE_CONSTRAINT;
|
|
if( pIdxInfo->aConstraint[i].op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
|
|
- pIdxInfo->idxNum = 1;
|
|
- pIdxInfo->estimatedCost = 1.0;
|
|
- pIdxInfo->aConstraintUsage[i].argvIndex = 1;
|
|
- pIdxInfo->aConstraintUsage[i].omit = 1;
|
|
- break;
|
|
+ if( pIdxInfo->aConstraint[i].usable==0 ){
|
|
+ /* Force DBSTAT table should always be the right-most table in a join */
|
|
+ return SQLITE_CONSTRAINT;
|
|
+ }
|
|
+ switch( pIdxInfo->aConstraint[i].iColumn ){
|
|
+ case 0: { /* name */
|
|
+ iName = i;
|
|
+ break;
|
|
+ }
|
|
+ case 10: { /* schema */
|
|
+ iSchema = i;
|
|
+ break;
|
|
+ }
|
|
+ case 11: { /* aggregate */
|
|
+ iAgg = i;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
}
|
|
-
|
|
+ i = 0;
|
|
+ if( iSchema>=0 ){
|
|
+ pIdxInfo->aConstraintUsage[iSchema].argvIndex = ++i;
|
|
+ pIdxInfo->aConstraintUsage[iSchema].omit = 1;
|
|
+ pIdxInfo->idxNum |= 0x01;
|
|
+ }
|
|
+ if( iName>=0 ){
|
|
+ pIdxInfo->aConstraintUsage[iName].argvIndex = ++i;
|
|
+ pIdxInfo->idxNum |= 0x02;
|
|
+ }
|
|
+ if( iAgg>=0 ){
|
|
+ pIdxInfo->aConstraintUsage[iAgg].argvIndex = ++i;
|
|
+ pIdxInfo->idxNum |= 0x04;
|
|
+ }
|
|
+ pIdxInfo->estimatedCost = 1.0;
|
|
|
|
/* Records are always returned in ascending order of (name, path).
|
|
** If this will satisfy the client, set the orderByConsumed flag so that
|
|
@@ -194998,13 +200534,14 @@
|
|
)
|
|
){
|
|
pIdxInfo->orderByConsumed = 1;
|
|
+ pIdxInfo->idxNum |= 0x08;
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
/*
|
|
-** Open a new statvfs cursor.
|
|
+** Open a new DBSTAT cursor.
|
|
*/
|
|
static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
|
StatTable *pTab = (StatTable *)pVTab;
|
|
@@ -195054,8 +200591,18 @@
|
|
pCsr->isEof = 0;
|
|
}
|
|
|
|
+/* Resize the space-used counters inside of the cursor */
|
|
+static void statResetCounts(StatCursor *pCsr){
|
|
+ pCsr->nCell = 0;
|
|
+ pCsr->nMxPayload = 0;
|
|
+ pCsr->nUnused = 0;
|
|
+ pCsr->nPayload = 0;
|
|
+ pCsr->szPage = 0;
|
|
+ pCsr->nPage = 0;
|
|
+}
|
|
+
|
|
/*
|
|
-** Close a statvfs cursor.
|
|
+** Close a DBSTAT cursor.
|
|
*/
|
|
static int statClose(sqlite3_vtab_cursor *pCursor){
|
|
StatCursor *pCsr = (StatCursor *)pCursor;
|
|
@@ -195065,11 +200612,15 @@
|
|
return SQLITE_OK;
|
|
}
|
|
|
|
-static void getLocalPayload(
|
|
+/*
|
|
+** For a single cell on a btree page, compute the number of bytes of
|
|
+** content (payload) stored on that page. That is to say, compute the
|
|
+** number of bytes of content not found on overflow pages.
|
|
+*/
|
|
+static int getLocalPayload(
|
|
int nUsable, /* Usable bytes per page */
|
|
u8 flags, /* Page flags */
|
|
- int nTotal, /* Total record (payload) size */
|
|
- int *pnLocal /* OUT: Bytes stored locally */
|
|
+ int nTotal /* Total record (payload) size */
|
|
){
|
|
int nLocal;
|
|
int nMinLocal;
|
|
@@ -195085,9 +200636,12 @@
|
|
|
|
nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4);
|
|
if( nLocal>nMaxLocal ) nLocal = nMinLocal;
|
|
- *pnLocal = nLocal;
|
|
+ return nLocal;
|
|
}
|
|
|
|
+/* Populate the StatPage object with information about the all
|
|
+** cells found on the page currently under analysis.
|
|
+*/
|
|
static int statDecodePage(Btree *pBt, StatPage *p){
|
|
int nUnused;
|
|
int iOff;
|
|
@@ -195158,7 +200712,7 @@
|
|
iOff += sqlite3GetVarint(&aData[iOff], &dummy);
|
|
}
|
|
if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
|
|
- getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
|
|
+ nLocal = getLocalPayload(nUsable, p->flags, nPayload);
|
|
if( nLocal<0 ) goto statPageIsCorrupt;
|
|
pCell->nLocal = nLocal;
|
|
assert( nPayload>=(u32)nLocal );
|
|
@@ -195166,7 +200720,9 @@
|
|
if( nPayload>(u32)nLocal ){
|
|
int j;
|
|
int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
|
|
- if( iOff+nLocal>nUsable ) goto statPageIsCorrupt;
|
|
+ if( iOff+nLocal>nUsable || nPayload>0x7fffffff ){
|
|
+ goto statPageIsCorrupt;
|
|
+ }
|
|
pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
|
|
pCell->nOvfl = nOvfl;
|
|
pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
|
|
@@ -195208,23 +200764,25 @@
|
|
sqlite3_file *fd;
|
|
sqlite3_int64 x[2];
|
|
|
|
- /* The default page size and offset */
|
|
- pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
|
|
- pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
|
|
-
|
|
- /* If connected to a ZIPVFS backend, override the page size and
|
|
- ** offset with actual values obtained from ZIPVFS.
|
|
+ /* If connected to a ZIPVFS backend, find the page size and
|
|
+ ** offset from ZIPVFS.
|
|
*/
|
|
fd = sqlite3PagerFile(pPager);
|
|
x[0] = pCsr->iPageno;
|
|
if( sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
|
|
pCsr->iOffset = x[0];
|
|
- pCsr->szPage = (int)x[1];
|
|
+ pCsr->szPage += x[1];
|
|
+ }else{
|
|
+ /* Not ZIPVFS: The default page size and offset */
|
|
+ pCsr->szPage += sqlite3BtreeGetPageSize(pBt);
|
|
+ pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
-** Move a statvfs cursor to the next entry in the file.
|
|
+** Move a DBSTAT cursor to the next entry. Normally, the next
|
|
+** entry will be the next page, but in aggregated mode (pCsr->isAgg!=0),
|
|
+** the next entry is the next btree.
|
|
*/
|
|
static int statNext(sqlite3_vtab_cursor *pCursor){
|
|
int rc;
|
|
@@ -195240,6 +200798,8 @@
|
|
|
|
statNextRestart:
|
|
if( pCsr->aPage[0].pPg==0 ){
|
|
+ /* Start measuring space on the next btree */
|
|
+ statResetCounts(pCsr);
|
|
rc = sqlite3_step(pCsr->pStmt);
|
|
if( rc==SQLITE_ROW ){
|
|
int nPage;
|
|
@@ -195252,44 +200812,47 @@
|
|
rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg, 0);
|
|
pCsr->aPage[0].iPgno = iRoot;
|
|
pCsr->aPage[0].iCell = 0;
|
|
- pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
|
|
+ if( !pCsr->isAgg ){
|
|
+ pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
|
|
+ if( z==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
+ }
|
|
pCsr->iPage = 0;
|
|
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
+ pCsr->nPage = 1;
|
|
}else{
|
|
pCsr->isEof = 1;
|
|
return sqlite3_reset(pCsr->pStmt);
|
|
}
|
|
}else{
|
|
-
|
|
- /* Page p itself has already been visited. */
|
|
+ /* Continue analyzing the btree previously started */
|
|
StatPage *p = &pCsr->aPage[pCsr->iPage];
|
|
-
|
|
+ if( !pCsr->isAgg ) statResetCounts(pCsr);
|
|
while( p->iCell<p->nCell ){
|
|
StatCell *pCell = &p->aCell[p->iCell];
|
|
- if( pCell->iOvfl<pCell->nOvfl ){
|
|
- int nUsable;
|
|
+ while( pCell->iOvfl<pCell->nOvfl ){
|
|
+ int nUsable, iOvfl;
|
|
sqlite3BtreeEnter(pBt);
|
|
nUsable = sqlite3BtreeGetPageSize(pBt) -
|
|
sqlite3BtreeGetReserveNoMutex(pBt);
|
|
sqlite3BtreeLeave(pBt);
|
|
- pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
|
|
- pCsr->iPageno = pCell->aOvfl[pCell->iOvfl];
|
|
- pCsr->zPagetype = "overflow";
|
|
- pCsr->nCell = 0;
|
|
- pCsr->nMxPayload = 0;
|
|
- pCsr->zPath = z = sqlite3_mprintf(
|
|
- "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
|
|
- );
|
|
+ pCsr->nPage++;
|
|
+ statSizeAndOffset(pCsr);
|
|
if( pCell->iOvfl<pCell->nOvfl-1 ){
|
|
- pCsr->nUnused = 0;
|
|
- pCsr->nPayload = nUsable - 4;
|
|
+ pCsr->nPayload += nUsable - 4;
|
|
}else{
|
|
- pCsr->nPayload = pCell->nLastOvfl;
|
|
- pCsr->nUnused = nUsable - 4 - pCsr->nPayload;
|
|
+ pCsr->nPayload += pCell->nLastOvfl;
|
|
+ pCsr->nUnused += nUsable - 4 - pCell->nLastOvfl;
|
|
}
|
|
+ iOvfl = pCell->iOvfl;
|
|
pCell->iOvfl++;
|
|
- statSizeAndOffset(pCsr);
|
|
- return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
|
|
+ if( !pCsr->isAgg ){
|
|
+ pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
|
|
+ pCsr->iPageno = pCell->aOvfl[iOvfl];
|
|
+ pCsr->zPagetype = "overflow";
|
|
+ pCsr->zPath = z = sqlite3_mprintf(
|
|
+ "%s%.3x+%.6x", p->zPath, p->iCell, iOvfl
|
|
+ );
|
|
+ return z==0 ? SQLITE_NOMEM_BKPT : SQLITE_OK;
|
|
+ }
|
|
}
|
|
if( p->iRightChildPg ) break;
|
|
p->iCell++;
|
|
@@ -195297,8 +200860,13 @@
|
|
|
|
if( !p->iRightChildPg || p->iCell>p->nCell ){
|
|
statClearPage(p);
|
|
- if( pCsr->iPage==0 ) return statNext(pCursor);
|
|
- pCsr->iPage--;
|
|
+ if( pCsr->iPage>0 ){
|
|
+ pCsr->iPage--;
|
|
+ }else if( pCsr->isAgg ){
|
|
+ /* label-statNext-done: When computing aggregate space usage over
|
|
+ ** an entire btree, this is the exit point from this function */
|
|
+ return SQLITE_OK;
|
|
+ }
|
|
goto statNextRestart; /* Tail recursion */
|
|
}
|
|
pCsr->iPage++;
|
|
@@ -195314,10 +200882,13 @@
|
|
p[1].iPgno = p->aCell[p->iCell].iChildPg;
|
|
}
|
|
rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg, 0);
|
|
+ pCsr->nPage++;
|
|
p[1].iCell = 0;
|
|
- p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
|
|
+ if( !pCsr->isAgg ){
|
|
+ p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
|
|
+ if( z==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
+ }
|
|
p->iCell++;
|
|
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
}
|
|
|
|
|
|
@@ -195347,16 +200918,23 @@
|
|
pCsr->zPagetype = "corrupted";
|
|
break;
|
|
}
|
|
- pCsr->nCell = p->nCell;
|
|
- pCsr->nUnused = p->nUnused;
|
|
- pCsr->nMxPayload = p->nMxPayload;
|
|
- pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
|
|
- if( z==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
+ pCsr->nCell += p->nCell;
|
|
+ pCsr->nUnused += p->nUnused;
|
|
+ if( p->nMxPayload>pCsr->nMxPayload ) pCsr->nMxPayload = p->nMxPayload;
|
|
+ if( !pCsr->isAgg ){
|
|
+ pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
|
|
+ if( z==0 ) rc = SQLITE_NOMEM_BKPT;
|
|
+ }
|
|
nPayload = 0;
|
|
for(i=0; i<p->nCell; i++){
|
|
nPayload += p->aCell[i].nLocal;
|
|
}
|
|
- pCsr->nPayload = nPayload;
|
|
+ pCsr->nPayload += nPayload;
|
|
+
|
|
+ /* If computing aggregate space usage by btree, continue with the
|
|
+ ** next page. The loop will exit via the return at label-statNext-done
|
|
+ */
|
|
+ if( pCsr->isAgg ) goto statNextRestart;
|
|
}
|
|
}
|
|
|
|
@@ -195368,6 +200946,10 @@
|
|
return pCsr->isEof;
|
|
}
|
|
|
|
+/* Initialize a cursor according to the query plan idxNum using the
|
|
+** arguments in argv[0]. See statBestIndex() for a description of the
|
|
+** meaning of the bits in idxNum.
|
|
+*/
|
|
static int statFilter(
|
|
sqlite3_vtab_cursor *pCursor,
|
|
int idxNum, const char *idxStr,
|
|
@@ -195375,29 +200957,52 @@
|
|
){
|
|
StatCursor *pCsr = (StatCursor *)pCursor;
|
|
StatTable *pTab = (StatTable*)(pCursor->pVtab);
|
|
- char *zSql;
|
|
- int rc = SQLITE_OK;
|
|
+ sqlite3_str *pSql; /* Query of btrees to analyze */
|
|
+ char *zSql; /* String value of pSql */
|
|
+ int iArg = 0; /* Count of argv[] parameters used so far */
|
|
+ int rc = SQLITE_OK; /* Result of this operation */
|
|
+ const char *zName = 0; /* Only provide analysis of this table */
|
|
|
|
- if( idxNum==1 ){
|
|
- const char *zDbase = (const char*)sqlite3_value_text(argv[0]);
|
|
+ statResetCsr(pCsr);
|
|
+ sqlite3_finalize(pCsr->pStmt);
|
|
+ pCsr->pStmt = 0;
|
|
+ if( idxNum & 0x01 ){
|
|
+ /* schema=? constraint is present. Get its value */
|
|
+ const char *zDbase = (const char*)sqlite3_value_text(argv[iArg++]);
|
|
pCsr->iDb = sqlite3FindDbName(pTab->db, zDbase);
|
|
if( pCsr->iDb<0 ){
|
|
- sqlite3_free(pCursor->pVtab->zErrMsg);
|
|
- pCursor->pVtab->zErrMsg = sqlite3_mprintf("no such schema: %s", zDbase);
|
|
- return pCursor->pVtab->zErrMsg ? SQLITE_ERROR : SQLITE_NOMEM_BKPT;
|
|
+ pCsr->iDb = 0;
|
|
+ pCsr->isEof = 1;
|
|
+ return SQLITE_OK;
|
|
}
|
|
}else{
|
|
pCsr->iDb = pTab->iDb;
|
|
}
|
|
- statResetCsr(pCsr);
|
|
- sqlite3_finalize(pCsr->pStmt);
|
|
- pCsr->pStmt = 0;
|
|
- zSql = sqlite3_mprintf(
|
|
- "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
|
|
- " UNION ALL "
|
|
- "SELECT name, rootpage, type"
|
|
- " FROM \"%w\".sqlite_master WHERE rootpage!=0"
|
|
- " ORDER BY name", pTab->db->aDb[pCsr->iDb].zDbSName);
|
|
+ if( idxNum & 0x02 ){
|
|
+ /* name=? constraint is present */
|
|
+ zName = (const char*)sqlite3_value_text(argv[iArg++]);
|
|
+ }
|
|
+ if( idxNum & 0x04 ){
|
|
+ /* aggregate=? constraint is present */
|
|
+ pCsr->isAgg = sqlite3_value_double(argv[iArg++])!=0.0;
|
|
+ }else{
|
|
+ pCsr->isAgg = 0;
|
|
+ }
|
|
+ pSql = sqlite3_str_new(pTab->db);
|
|
+ sqlite3_str_appendf(pSql,
|
|
+ "SELECT * FROM ("
|
|
+ "SELECT 'sqlite_master' AS name,1 AS rootpage,'table' AS type"
|
|
+ " UNION ALL "
|
|
+ "SELECT name,rootpage,type"
|
|
+ " FROM \"%w\".sqlite_master WHERE rootpage!=0)",
|
|
+ pTab->db->aDb[pCsr->iDb].zDbSName);
|
|
+ if( zName ){
|
|
+ sqlite3_str_appendf(pSql, "WHERE name=%Q", zName);
|
|
+ }
|
|
+ if( idxNum & 0x08 ){
|
|
+ sqlite3_str_appendf(pSql, " ORDER BY name");
|
|
+ }
|
|
+ zSql = sqlite3_str_finish(pSql);
|
|
if( zSql==0 ){
|
|
return SQLITE_NOMEM_BKPT;
|
|
}else{
|
|
@@ -195422,13 +201027,21 @@
|
|
sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
|
|
break;
|
|
case 1: /* path */
|
|
- sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
|
|
+ if( !pCsr->isAgg ){
|
|
+ sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
|
|
+ }
|
|
break;
|
|
case 2: /* pageno */
|
|
- sqlite3_result_int64(ctx, pCsr->iPageno);
|
|
+ if( pCsr->isAgg ){
|
|
+ sqlite3_result_int64(ctx, pCsr->nPage);
|
|
+ }else{
|
|
+ sqlite3_result_int64(ctx, pCsr->iPageno);
|
|
+ }
|
|
break;
|
|
case 3: /* pagetype */
|
|
- sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
|
|
+ if( !pCsr->isAgg ){
|
|
+ sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
|
|
+ }
|
|
break;
|
|
case 4: /* ncell */
|
|
sqlite3_result_int(ctx, pCsr->nCell);
|
|
@@ -195443,17 +201056,23 @@
|
|
sqlite3_result_int(ctx, pCsr->nMxPayload);
|
|
break;
|
|
case 8: /* pgoffset */
|
|
- sqlite3_result_int64(ctx, pCsr->iOffset);
|
|
+ if( !pCsr->isAgg ){
|
|
+ sqlite3_result_int64(ctx, pCsr->iOffset);
|
|
+ }
|
|
break;
|
|
case 9: /* pgsize */
|
|
sqlite3_result_int(ctx, pCsr->szPage);
|
|
break;
|
|
- default: { /* schema */
|
|
+ case 10: { /* schema */
|
|
sqlite3 *db = sqlite3_context_db_handle(ctx);
|
|
int iDb = pCsr->iDb;
|
|
sqlite3_result_text(ctx, db->aDb[iDb].zDbSName, -1, SQLITE_STATIC);
|
|
break;
|
|
}
|
|
+ default: { /* aggregate */
|
|
+ sqlite3_result_int(ctx, pCsr->isAgg);
|
|
+ break;
|
|
+ }
|
|
}
|
|
return SQLITE_OK;
|
|
}
|
|
@@ -195577,6 +201196,7 @@
|
|
DbpageTable *pTab = 0;
|
|
int rc = SQLITE_OK;
|
|
|
|
+ sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
|
|
rc = sqlite3_declare_vtab(db,
|
|
"CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
|
|
if( rc==SQLITE_OK ){
|
|
@@ -197759,7 +203379,7 @@
|
|
i64 nNew = p->nAlloc ? p->nAlloc : 128;
|
|
do {
|
|
nNew = nNew*2;
|
|
- }while( (nNew-p->nBuf)<nByte );
|
|
+ }while( (size_t)(nNew-p->nBuf)<nByte );
|
|
|
|
aNew = (u8 *)sqlite3_realloc64(p->aBuf, nNew);
|
|
if( 0==aNew ){
|
|
@@ -199435,7 +205055,7 @@
|
|
SessionBuffer buf = {0, 0, 0};
|
|
int nPk = 0;
|
|
|
|
- sessionAppendStr(&buf, "DELETE FROM ", &rc);
|
|
+ sessionAppendStr(&buf, "DELETE FROM main.", &rc);
|
|
sessionAppendIdent(&buf, zTab, &rc);
|
|
sessionAppendStr(&buf, " WHERE ", &rc);
|
|
|
|
@@ -199518,7 +205138,7 @@
|
|
SessionBuffer buf = {0, 0, 0};
|
|
|
|
/* Append "UPDATE tbl SET " */
|
|
- sessionAppendStr(&buf, "UPDATE ", &rc);
|
|
+ sessionAppendStr(&buf, "UPDATE main.", &rc);
|
|
sessionAppendIdent(&buf, zTab, &rc);
|
|
sessionAppendStr(&buf, " SET ", &rc);
|
|
|
|
@@ -201565,7 +207185,7 @@
|
|
**
|
|
** xSetAuxdata(pFts5, pAux, xDelete)
|
|
**
|
|
-** Save the pointer passed as the second argument as the extension functions
|
|
+** Save the pointer passed as the second argument as the extension function's
|
|
** "auxiliary data". The pointer may then be retrieved by the current or any
|
|
** future invocation of the same fts5 extension function made as part of
|
|
** the same MATCH query using the xGetAuxdata() API.
|
|
@@ -201807,8 +207427,8 @@
|
|
**
|
|
** There are several ways to approach this in FTS5:
|
|
**
|
|
-** <ol><li> By mapping all synonyms to a single token. In this case, the
|
|
-** In the above example, this means that the tokenizer returns the
|
|
+** <ol><li> By mapping all synonyms to a single token. In this case, using
|
|
+** the above example, this means that the tokenizer returns the
|
|
** same token for inputs "first" and "1st". Say that token is in
|
|
** fact "first", so that when the user inserts the document "I won
|
|
** 1st place" entries are added to the index for tokens "i", "won",
|
|
@@ -202043,6 +207663,11 @@
|
|
*/
|
|
#define FTS5_MAX_PREFIX_INDEXES 31
|
|
|
|
+/*
|
|
+** Maximum segments permitted in a single index
|
|
+*/
|
|
+#define FTS5_MAX_SEGMENT 2000
|
|
+
|
|
#define FTS5_DEFAULT_NEARDIST 10
|
|
#define FTS5_DEFAULT_RANK "bm25"
|
|
|
|
@@ -202160,6 +207785,7 @@
|
|
char *zContentExprlist;
|
|
Fts5Tokenizer *pTok;
|
|
fts5_tokenizer *pTokApi;
|
|
+ int bLock; /* True when table is preparing statement */
|
|
|
|
/* Values loaded from the %_config table */
|
|
int iCookie; /* Incremented when %_config is modified */
|
|
@@ -202398,6 +208024,11 @@
|
|
*/
|
|
static void sqlite3Fts5IterClose(Fts5IndexIter*);
|
|
|
|
+/*
|
|
+** Close the reader blob handle, if it is open.
|
|
+*/
|
|
+static void sqlite3Fts5IndexCloseReader(Fts5Index*);
|
|
+
|
|
/*
|
|
** This interface is used by the fts5vocab module.
|
|
*/
|
|
@@ -202676,6 +208307,7 @@
|
|
static i64 sqlite3Fts5ExprRowid(Fts5Expr*);
|
|
|
|
static void sqlite3Fts5ExprFree(Fts5Expr*);
|
|
+static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2);
|
|
|
|
/* Called during startup to register a UDF with SQLite */
|
|
static int sqlite3Fts5ExprInit(Fts5Global*, sqlite3*);
|
|
@@ -202957,6 +208589,7 @@
|
|
#define sqlite3Fts5ParserCTX_STORE
|
|
#define fts5YYNSTATE 35
|
|
#define fts5YYNRULE 28
|
|
+#define fts5YYNRULE_WITH_ACTION 28
|
|
#define fts5YYNFTS5TOKEN 16
|
|
#define fts5YY_MAX_SHIFT 34
|
|
#define fts5YY_MIN_SHIFTREDUCE 52
|
|
@@ -203527,15 +209160,18 @@
|
|
do{
|
|
i = fts5yy_shift_ofst[stateno];
|
|
assert( i>=0 );
|
|
- /* assert( i+fts5YYNFTS5TOKEN<=(int)fts5YY_NLOOKAHEAD ); */
|
|
+ assert( i<=fts5YY_ACTTAB_COUNT );
|
|
+ assert( i+fts5YYNFTS5TOKEN<=(int)fts5YY_NLOOKAHEAD );
|
|
assert( iLookAhead!=fts5YYNOCODE );
|
|
assert( iLookAhead < fts5YYNFTS5TOKEN );
|
|
i += iLookAhead;
|
|
- if( i>=fts5YY_NLOOKAHEAD || fts5yy_lookahead[i]!=iLookAhead ){
|
|
+ assert( i<(int)fts5YY_NLOOKAHEAD );
|
|
+ if( fts5yy_lookahead[i]!=iLookAhead ){
|
|
#ifdef fts5YYFALLBACK
|
|
fts5YYCODETYPE iFallback; /* Fallback token */
|
|
- if( iLookAhead<sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])
|
|
- && (iFallback = fts5yyFallback[iLookAhead])!=0 ){
|
|
+ assert( iLookAhead<sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0]) );
|
|
+ iFallback = fts5yyFallback[iLookAhead];
|
|
+ if( iFallback!=0 ){
|
|
#ifndef NDEBUG
|
|
if( fts5yyTraceFILE ){
|
|
fprintf(fts5yyTraceFILE, "%sFALLBACK %s => %s\n",
|
|
@@ -203550,16 +209186,8 @@
|
|
#ifdef fts5YYWILDCARD
|
|
{
|
|
int j = i - iLookAhead + fts5YYWILDCARD;
|
|
- if(
|
|
-#if fts5YY_SHIFT_MIN+fts5YYWILDCARD<0
|
|
- j>=0 &&
|
|
-#endif
|
|
-#if fts5YY_SHIFT_MAX+fts5YYWILDCARD>=fts5YY_ACTTAB_COUNT
|
|
- j<fts5YY_ACTTAB_COUNT &&
|
|
-#endif
|
|
- j<(int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])) &&
|
|
- fts5yy_lookahead[j]==fts5YYWILDCARD && iLookAhead>0
|
|
- ){
|
|
+ assert( j<(int)(sizeof(fts5yy_lookahead)/sizeof(fts5yy_lookahead[0])) );
|
|
+ if( fts5yy_lookahead[j]==fts5YYWILDCARD && iLookAhead>0 ){
|
|
#ifndef NDEBUG
|
|
if( fts5yyTraceFILE ){
|
|
fprintf(fts5yyTraceFILE, "%sWILDCARD %s => %s\n",
|
|
@@ -203573,6 +209201,7 @@
|
|
#endif /* fts5YYWILDCARD */
|
|
return fts5yy_default[stateno];
|
|
}else{
|
|
+ assert( i>=0 && i<sizeof(fts5yy_action)/sizeof(fts5yy_action[0]) );
|
|
return fts5yy_action[i];
|
|
}
|
|
}while(1);
|
|
@@ -203790,12 +209419,15 @@
|
|
if( fts5yyTraceFILE && fts5yyruleno<(int)(sizeof(fts5yyRuleName)/sizeof(fts5yyRuleName[0])) ){
|
|
fts5yysize = fts5yyRuleInfoNRhs[fts5yyruleno];
|
|
if( fts5yysize ){
|
|
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
|
|
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
|
|
fts5yyTracePrompt,
|
|
- fts5yyruleno, fts5yyRuleName[fts5yyruleno], fts5yymsp[fts5yysize].stateno);
|
|
+ fts5yyruleno, fts5yyRuleName[fts5yyruleno],
|
|
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action",
|
|
+ fts5yymsp[fts5yysize].stateno);
|
|
}else{
|
|
- fprintf(fts5yyTraceFILE, "%sReduce %d [%s].\n",
|
|
- fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno]);
|
|
+ fprintf(fts5yyTraceFILE, "%sReduce %d [%s]%s.\n",
|
|
+ fts5yyTracePrompt, fts5yyruleno, fts5yyRuleName[fts5yyruleno],
|
|
+ fts5yyruleno<fts5YYNRULE_WITH_ACTION ? "" : " without external action");
|
|
}
|
|
}
|
|
#endif /* NDEBUG */
|
|
@@ -204273,13 +209905,12 @@
|
|
*/
|
|
static int sqlite3Fts5ParserFallback(int iToken){
|
|
#ifdef fts5YYFALLBACK
|
|
- if( iToken<(int)(sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])) ){
|
|
- return fts5yyFallback[iToken];
|
|
- }
|
|
+ assert( iToken<(int)(sizeof(fts5yyFallback)/sizeof(fts5yyFallback[0])) );
|
|
+ return fts5yyFallback[iToken];
|
|
#else
|
|
(void)iToken;
|
|
-#endif
|
|
return 0;
|
|
+#endif
|
|
}
|
|
|
|
/*
|
|
@@ -205428,7 +211059,7 @@
|
|
#define FTS5_DEFAULT_HASHSIZE (1024*1024)
|
|
|
|
/* Maximum allowed page size */
|
|
-#define FTS5_MAX_PAGE_SIZE (128*1024)
|
|
+#define FTS5_MAX_PAGE_SIZE (64*1024)
|
|
|
|
static int fts5_iswhitespace(char x){
|
|
return (x==' ');
|
|
@@ -205555,7 +211186,7 @@
|
|
assert( q=='[' || q=='\'' || q=='"' || q=='`' );
|
|
if( q=='[' ) q = ']';
|
|
|
|
- while( ALWAYS(z[iIn]) ){
|
|
+ while( z[iIn] ){
|
|
if( z[iIn]==q ){
|
|
if( z[iIn+1]!=q ){
|
|
/* Character iIn was the close quote. */
|
|
@@ -206088,7 +211719,7 @@
|
|
rc = sqlite3_declare_vtab(pConfig->db, zSql);
|
|
sqlite3_free(zSql);
|
|
}
|
|
-
|
|
+
|
|
return rc;
|
|
}
|
|
|
|
@@ -206233,7 +211864,7 @@
|
|
if( SQLITE_INTEGER==sqlite3_value_numeric_type(pVal) ){
|
|
pgsz = sqlite3_value_int(pVal);
|
|
}
|
|
- if( pgsz<=0 || pgsz>FTS5_MAX_PAGE_SIZE ){
|
|
+ if( pgsz<32 || pgsz>FTS5_MAX_PAGE_SIZE ){
|
|
*pbBadkey = 1;
|
|
}else{
|
|
pConfig->pgsz = pgsz;
|
|
@@ -206286,6 +211917,7 @@
|
|
*pbBadkey = 1;
|
|
}else{
|
|
if( nCrisisMerge<=1 ) nCrisisMerge = FTS5_DEFAULT_CRISISMERGE;
|
|
+ if( nCrisisMerge>=FTS5_MAX_SEGMENT ) nCrisisMerge = FTS5_MAX_SEGMENT-1;
|
|
pConfig->nCrisisMerge = nCrisisMerge;
|
|
}
|
|
}
|
|
@@ -206676,6 +212308,42 @@
|
|
}
|
|
}
|
|
|
|
+static int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){
|
|
+ Fts5Parse sParse;
|
|
+ memset(&sParse, 0, sizeof(sParse));
|
|
+
|
|
+ if( *pp1 ){
|
|
+ Fts5Expr *p1 = *pp1;
|
|
+ int nPhrase = p1->nPhrase + p2->nPhrase;
|
|
+
|
|
+ p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0);
|
|
+ p2->pRoot = 0;
|
|
+
|
|
+ if( sParse.rc==SQLITE_OK ){
|
|
+ Fts5ExprPhrase **ap = (Fts5ExprPhrase**)sqlite3_realloc(
|
|
+ p1->apExprPhrase, nPhrase * sizeof(Fts5ExprPhrase*)
|
|
+ );
|
|
+ if( ap==0 ){
|
|
+ sParse.rc = SQLITE_NOMEM;
|
|
+ }else{
|
|
+ int i;
|
|
+ memmove(&ap[p2->nPhrase], ap, p1->nPhrase*sizeof(Fts5ExprPhrase*));
|
|
+ for(i=0; i<p2->nPhrase; i++){
|
|
+ ap[i] = p2->apExprPhrase[i];
|
|
+ }
|
|
+ p1->nPhrase = nPhrase;
|
|
+ p1->apExprPhrase = ap;
|
|
+ }
|
|
+ }
|
|
+ sqlite3_free(p2->apExprPhrase);
|
|
+ sqlite3_free(p2);
|
|
+ }else{
|
|
+ *pp1 = p2;
|
|
+ }
|
|
+
|
|
+ return sParse.rc;
|
|
+}
|
|
+
|
|
/*
|
|
** Argument pTerm must be a synonym iterator. Return the current rowid
|
|
** that it points to.
|
|
@@ -208847,10 +214515,12 @@
|
|
azConfig[1] = "main";
|
|
azConfig[2] = "tbl";
|
|
for(i=3; iArg<nArg; iArg++){
|
|
- azConfig[i++] = (const char*)sqlite3_value_text(apVal[iArg]);
|
|
+ const char *z = (const char*)sqlite3_value_text(apVal[iArg]);
|
|
+ azConfig[i++] = (z ? z : "");
|
|
}
|
|
|
|
zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
|
+ if( zExpr==0 ) zExpr = "";
|
|
|
|
rc = sqlite3Fts5ConfigParse(pGlobal, db, nConfig, azConfig, &pConfig, &zErr);
|
|
if( rc==SQLITE_OK ){
|
|
@@ -210021,11 +215691,6 @@
|
|
#define FTS5_SEGMENT_ROWID(segid, pgno) fts5_dri(segid, 0, 0, pgno)
|
|
#define FTS5_DLIDX_ROWID(segid, height, pgno) fts5_dri(segid, 1, height, pgno)
|
|
|
|
-/*
|
|
-** Maximum segments permitted in a single index
|
|
-*/
|
|
-#define FTS5_MAX_SEGMENT 2000
|
|
-
|
|
#ifdef SQLITE_DEBUG
|
|
static int sqlite3Fts5Corrupt() { return SQLITE_CORRUPT_VTAB; }
|
|
#endif
|
|
@@ -210401,7 +216066,7 @@
|
|
/*
|
|
** Close the read-only blob handle, if it is open.
|
|
*/
|
|
-static void fts5CloseReader(Fts5Index *p){
|
|
+static void sqlite3Fts5IndexCloseReader(Fts5Index *p){
|
|
if( p->pReader ){
|
|
sqlite3_blob *pReader = p->pReader;
|
|
p->pReader = 0;
|
|
@@ -210430,7 +216095,7 @@
|
|
assert( p->pReader==0 );
|
|
p->pReader = pBlob;
|
|
if( rc!=SQLITE_OK ){
|
|
- fts5CloseReader(p);
|
|
+ sqlite3Fts5IndexCloseReader(p);
|
|
}
|
|
if( rc==SQLITE_ABORT ) rc = SQLITE_OK;
|
|
}
|
|
@@ -210472,6 +216137,7 @@
|
|
}else{
|
|
/* TODO1: Fix this */
|
|
pRet->p[nByte] = 0x00;
|
|
+ pRet->p[nByte+1] = 0x00;
|
|
pRet->szLeaf = fts5GetU16(&pRet->p[2]);
|
|
}
|
|
}
|
|
@@ -210494,7 +216160,7 @@
|
|
static Fts5Data *fts5LeafRead(Fts5Index *p, i64 iRowid){
|
|
Fts5Data *pRet = fts5DataRead(p, iRowid);
|
|
if( pRet ){
|
|
- if( pRet->szLeaf>pRet->nn ){
|
|
+ if( pRet->nn<4 || pRet->szLeaf>pRet->nn ){
|
|
p->rc = FTS5_CORRUPT;
|
|
fts5DataRelease(pRet);
|
|
pRet = 0;
|
|
@@ -214778,9 +220444,12 @@
|
|
Fts5PoslistWriter writer;
|
|
memset(&writer, 0, sizeof(writer));
|
|
|
|
+ /* See the earlier comment in this function for an explanation of why
|
|
+ ** corrupt input position lists might cause the output to consume
|
|
+ ** at most 20 bytes of unexpected space. */
|
|
fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
|
|
fts5BufferZero(&tmp);
|
|
- sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist);
|
|
+ sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
|
|
if( p->rc ) break;
|
|
|
|
sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
|
|
@@ -214828,6 +220497,12 @@
|
|
}
|
|
|
|
/* WRITEPOSLISTSIZE */
|
|
+ assert_nc( tmp.n<=i1.nPoslist+i2.nPoslist );
|
|
+ assert( tmp.n<=i1.nPoslist+i2.nPoslist+10+10 );
|
|
+ if( tmp.n>i1.nPoslist+i2.nPoslist ){
|
|
+ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT;
|
|
+ break;
|
|
+ }
|
|
fts5BufferSafeAppendVarint(&out, tmp.n * 2);
|
|
fts5BufferSafeAppendBlob(&out, tmp.p, tmp.n);
|
|
fts5DoclistIterNext(&i1);
|
|
@@ -214981,7 +220656,7 @@
|
|
static int sqlite3Fts5IndexSync(Fts5Index *p){
|
|
assert( p->rc==SQLITE_OK );
|
|
fts5IndexFlush(p);
|
|
- fts5CloseReader(p);
|
|
+ sqlite3Fts5IndexCloseReader(p);
|
|
return fts5IndexReturn(p);
|
|
}
|
|
|
|
@@ -214992,7 +220667,7 @@
|
|
** records must be invalidated.
|
|
*/
|
|
static int sqlite3Fts5IndexRollback(Fts5Index *p){
|
|
- fts5CloseReader(p);
|
|
+ sqlite3Fts5IndexCloseReader(p);
|
|
fts5IndexDiscardData(p);
|
|
fts5StructureInvalidate(p);
|
|
/* assert( p->rc==SQLITE_OK ); */
|
|
@@ -215007,6 +220682,7 @@
|
|
static int sqlite3Fts5IndexReinit(Fts5Index *p){
|
|
Fts5Structure s;
|
|
fts5StructureInvalidate(p);
|
|
+ fts5IndexDiscardData(p);
|
|
memset(&s, 0, sizeof(Fts5Structure));
|
|
fts5DataWrite(p, FTS5_AVERAGES_ROWID, (const u8*)"", 0);
|
|
fts5StructureWrite(p, &s);
|
|
@@ -215094,9 +220770,13 @@
|
|
for(i=0; i<nChar; i++){
|
|
if( n>=nByte ) return 0; /* Input contains fewer than nChar chars */
|
|
if( (unsigned char)p[n++]>=0xc0 ){
|
|
+ if( n>=nByte ) return 0;
|
|
while( (p[n] & 0xc0)==0x80 ){
|
|
n++;
|
|
- if( n>=nByte ) break;
|
|
+ if( n>=nByte ){
|
|
+ if( i+1==nChar ) break;
|
|
+ return 0;
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
@@ -215232,7 +220912,7 @@
|
|
if( p->rc ){
|
|
sqlite3Fts5IterClose((Fts5IndexIter*)pRet);
|
|
pRet = 0;
|
|
- fts5CloseReader(p);
|
|
+ sqlite3Fts5IndexCloseReader(p);
|
|
}
|
|
|
|
*ppIter = (Fts5IndexIter*)pRet;
|
|
@@ -215305,7 +220985,7 @@
|
|
Fts5Iter *pIter = (Fts5Iter*)pIndexIter;
|
|
Fts5Index *pIndex = pIter->pIndex;
|
|
fts5MultiIterFree(pIter);
|
|
- fts5CloseReader(pIndex);
|
|
+ sqlite3Fts5IndexCloseReader(pIndex);
|
|
}
|
|
}
|
|
|
|
@@ -215498,6 +221178,37 @@
|
|
return rc;
|
|
}
|
|
|
|
+/*
|
|
+** Check if buffer z[], size n bytes, contains as series of valid utf-8
|
|
+** encoded codepoints. If so, return 0. Otherwise, if the buffer does not
|
|
+** contain valid utf-8, return non-zero.
|
|
+*/
|
|
+static int fts5TestUtf8(const char *z, int n){
|
|
+ int i = 0;
|
|
+ assert_nc( n>0 );
|
|
+ while( i<n ){
|
|
+ if( (z[i] & 0x80)==0x00 ){
|
|
+ i++;
|
|
+ }else
|
|
+ if( (z[i] & 0xE0)==0xC0 ){
|
|
+ if( i+1>=n || (z[i+1] & 0xC0)!=0x80 ) return 1;
|
|
+ i += 2;
|
|
+ }else
|
|
+ if( (z[i] & 0xF0)==0xE0 ){
|
|
+ if( i+2>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
|
|
+ i += 3;
|
|
+ }else
|
|
+ if( (z[i] & 0xF8)==0xF0 ){
|
|
+ if( i+3>=n || (z[i+1] & 0xC0)!=0x80 || (z[i+2] & 0xC0)!=0x80 ) return 1;
|
|
+ if( (z[i+2] & 0xC0)!=0x80 ) return 1;
|
|
+ i += 3;
|
|
+ }else{
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
|
|
/*
|
|
** This function is also purely an internal test. It does not contribute to
|
|
@@ -215538,8 +221249,14 @@
|
|
** This check may only be performed if the hash table is empty. This
|
|
** is because the hash table only supports a single scan query at
|
|
** a time, and the multi-iter loop from which this function is called
|
|
- ** is already performing such a scan. */
|
|
- if( p->nPendingData==0 ){
|
|
+ ** is already performing such a scan.
|
|
+ **
|
|
+ ** Also only do this if buffer zTerm contains nTerm bytes of valid
|
|
+ ** utf-8. Otherwise, the last part of the buffer contents might contain
|
|
+ ** a non-utf-8 sequence that happens to be a prefix of a valid utf-8
|
|
+ ** character stored in the main fts index, which will cause the
|
|
+ ** test to fail. */
|
|
+ if( p->nPendingData==0 && 0==fts5TestUtf8(zTerm, nTerm) ){
|
|
if( iIdx>0 && rc==SQLITE_OK ){
|
|
int f = flags|FTS5INDEX_QUERY_TEST_NOIDX;
|
|
ck2 = 0;
|
|
@@ -215662,7 +221379,8 @@
|
|
if( pSeg->pgnoFirst==0 ) return;
|
|
|
|
fts5IndexPrepareStmt(p, &pStmt, sqlite3_mprintf(
|
|
- "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d",
|
|
+ "SELECT segid, term, (pgno>>1), (pgno&1) FROM %Q.'%q_idx' WHERE segid=%d "
|
|
+ "ORDER BY 1, 2",
|
|
pConfig->zDb, pConfig->zName, pSeg->iSegid
|
|
));
|
|
|
|
@@ -215671,8 +221389,8 @@
|
|
i64 iRow; /* Rowid for this leaf */
|
|
Fts5Data *pLeaf; /* Data for this leaf */
|
|
|
|
+ const char *zIdxTerm = (const char*)sqlite3_column_blob(pStmt, 1);
|
|
int nIdxTerm = sqlite3_column_bytes(pStmt, 1);
|
|
- const char *zIdxTerm = (const char*)sqlite3_column_text(pStmt, 1);
|
|
int iIdxLeaf = sqlite3_column_int(pStmt, 2);
|
|
int bIdxDlidx = sqlite3_column_int(pStmt, 3);
|
|
|
|
@@ -216653,7 +222371,10 @@
|
|
case FTS5_ROLLBACKTO:
|
|
assert( p->ts.eState==1 );
|
|
assert( iSavepoint>=-1 );
|
|
- assert( iSavepoint<=p->ts.iSavepoint );
|
|
+ /* The following assert() can fail if another vtab strikes an error
|
|
+ ** within an xSavepoint() call then SQLite calls xRollbackTo() - without
|
|
+ ** having called xSavepoint() on this vtab. */
|
|
+ /* assert( iSavepoint<=p->ts.iSavepoint ); */
|
|
p->ts.iSavepoint = iSavepoint;
|
|
break;
|
|
}
|
|
@@ -216829,17 +222550,39 @@
|
|
** Implementation of the xBestIndex method for FTS5 tables. Within the
|
|
** WHERE constraint, it searches for the following:
|
|
**
|
|
-** 1. A MATCH constraint against the special column.
|
|
+** 1. A MATCH constraint against the table column.
|
|
** 2. A MATCH constraint against the "rank" column.
|
|
-** 3. An == constraint against the rowid column.
|
|
-** 4. A < or <= constraint against the rowid column.
|
|
-** 5. A > or >= constraint against the rowid column.
|
|
+** 3. A MATCH constraint against some other column.
|
|
+** 4. An == constraint against the rowid column.
|
|
+** 5. A < or <= constraint against the rowid column.
|
|
+** 6. A > or >= constraint against the rowid column.
|
|
**
|
|
-** Within the ORDER BY, either:
|
|
+** Within the ORDER BY, the following are supported:
|
|
**
|
|
** 5. ORDER BY rank [ASC|DESC]
|
|
** 6. ORDER BY rowid [ASC|DESC]
|
|
**
|
|
+** Information for the xFilter call is passed via both the idxNum and
|
|
+** idxStr variables. Specifically, idxNum is a bitmask of the following
|
|
+** flags used to encode the ORDER BY clause:
|
|
+**
|
|
+** FTS5_BI_ORDER_RANK
|
|
+** FTS5_BI_ORDER_ROWID
|
|
+** FTS5_BI_ORDER_DESC
|
|
+**
|
|
+** idxStr is used to encode data from the WHERE clause. For each argument
|
|
+** passed to the xFilter method, the following is appended to idxStr:
|
|
+**
|
|
+** Match against table column: "m"
|
|
+** Match against rank column: "r"
|
|
+** Match against other column: "<column-number>"
|
|
+** Equality constraint against the rowid: "="
|
|
+** A < or <= against the rowid: "<"
|
|
+** A > or >= against the rowid: ">"
|
|
+**
|
|
+** This function ensures that there is at most one "r" or "=". And that if
|
|
+** there exists an "=" then there is no "<" or ">".
|
|
+**
|
|
** Costs are assigned as follows:
|
|
**
|
|
** a) If an unusable MATCH operator is present in the WHERE clause, the
|
|
@@ -216867,32 +222610,18 @@
|
|
Fts5Config *pConfig = pTab->pConfig;
|
|
const int nCol = pConfig->nCol;
|
|
int idxFlags = 0; /* Parameter passed through to xFilter() */
|
|
- int bHasMatch;
|
|
- int iNext;
|
|
int i;
|
|
|
|
- struct Constraint {
|
|
- int op; /* Mask against sqlite3_index_constraint.op */
|
|
- int fts5op; /* FTS5 mask for idxFlags */
|
|
- int iCol; /* 0==rowid, 1==tbl, 2==rank */
|
|
- int omit; /* True to omit this if found */
|
|
- int iConsIndex; /* Index in pInfo->aConstraint[] */
|
|
- } aConstraint[] = {
|
|
- {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
|
|
- FTS5_BI_MATCH, 1, 1, -1},
|
|
- {SQLITE_INDEX_CONSTRAINT_MATCH|SQLITE_INDEX_CONSTRAINT_EQ,
|
|
- FTS5_BI_RANK, 2, 1, -1},
|
|
- {SQLITE_INDEX_CONSTRAINT_EQ, FTS5_BI_ROWID_EQ, 0, 0, -1},
|
|
- {SQLITE_INDEX_CONSTRAINT_LT|SQLITE_INDEX_CONSTRAINT_LE,
|
|
- FTS5_BI_ROWID_LE, 0, 0, -1},
|
|
- {SQLITE_INDEX_CONSTRAINT_GT|SQLITE_INDEX_CONSTRAINT_GE,
|
|
- FTS5_BI_ROWID_GE, 0, 0, -1},
|
|
- };
|
|
+ char *idxStr;
|
|
+ int iIdxStr = 0;
|
|
+ int iCons = 0;
|
|
+
|
|
+ int bSeenEq = 0;
|
|
+ int bSeenGt = 0;
|
|
+ int bSeenLt = 0;
|
|
+ int bSeenMatch = 0;
|
|
+ int bSeenRank = 0;
|
|
|
|
- int aColMap[3];
|
|
- aColMap[0] = -1;
|
|
- aColMap[1] = nCol;
|
|
- aColMap[2] = nCol+1;
|
|
|
|
assert( SQLITE_INDEX_CONSTRAINT_EQ<SQLITE_INDEX_CONSTRAINT_MATCH );
|
|
assert( SQLITE_INDEX_CONSTRAINT_GT<SQLITE_INDEX_CONSTRAINT_MATCH );
|
|
@@ -216900,40 +222629,85 @@
|
|
assert( SQLITE_INDEX_CONSTRAINT_GE<SQLITE_INDEX_CONSTRAINT_MATCH );
|
|
assert( SQLITE_INDEX_CONSTRAINT_LE<SQLITE_INDEX_CONSTRAINT_MATCH );
|
|
|
|
- /* Set idxFlags flags for all WHERE clause terms that will be used. */
|
|
+ if( pConfig->bLock ){
|
|
+ pTab->base.zErrMsg = sqlite3_mprintf(
|
|
+ "recursively defined fts5 content table"
|
|
+ );
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
+
|
|
+ idxStr = (char*)sqlite3_malloc(pInfo->nConstraint * 6 + 1);
|
|
+ if( idxStr==0 ) return SQLITE_NOMEM;
|
|
+ pInfo->idxStr = idxStr;
|
|
+ pInfo->needToFreeIdxStr = 1;
|
|
+
|
|
for(i=0; i<pInfo->nConstraint; i++){
|
|
struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
|
int iCol = p->iColumn;
|
|
-
|
|
- if( (p->op==SQLITE_INDEX_CONSTRAINT_MATCH && iCol>=0 && iCol<=nCol)
|
|
- || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol==nCol)
|
|
+ if( p->op==SQLITE_INDEX_CONSTRAINT_MATCH
|
|
+ || (p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol>=nCol)
|
|
){
|
|
/* A MATCH operator or equivalent */
|
|
- if( p->usable ){
|
|
- idxFlags = (idxFlags & 0xFFFF) | FTS5_BI_MATCH | (iCol << 16);
|
|
- aConstraint[0].iConsIndex = i;
|
|
- }else{
|
|
+ if( p->usable==0 || iCol<0 ){
|
|
/* As there exists an unusable MATCH constraint this is an
|
|
** unusable plan. Set a prohibitively high cost. */
|
|
pInfo->estimatedCost = 1e50;
|
|
+ assert( iIdxStr < pInfo->nConstraint*6 + 1 );
|
|
+ idxStr[iIdxStr] = 0;
|
|
return SQLITE_OK;
|
|
+ }else{
|
|
+ if( iCol==nCol+1 ){
|
|
+ if( bSeenRank ) continue;
|
|
+ idxStr[iIdxStr++] = 'r';
|
|
+ bSeenRank = 1;
|
|
+ }else{
|
|
+ bSeenMatch = 1;
|
|
+ idxStr[iIdxStr++] = 'm';
|
|
+ if( iCol<nCol ){
|
|
+ sqlite3_snprintf(6, &idxStr[iIdxStr], "%d", iCol);
|
|
+ idxStr += strlen(&idxStr[iIdxStr]);
|
|
+ assert( idxStr[iIdxStr]=='\0' );
|
|
+ }
|
|
+ }
|
|
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
|
+ pInfo->aConstraintUsage[i].omit = 1;
|
|
}
|
|
- }else if( p->op<=SQLITE_INDEX_CONSTRAINT_MATCH ){
|
|
- int j;
|
|
- for(j=1; j<ArraySize(aConstraint); j++){
|
|
- struct Constraint *pC = &aConstraint[j];
|
|
- if( iCol==aColMap[pC->iCol] && (p->op & pC->op) && p->usable ){
|
|
- pC->iConsIndex = i;
|
|
- idxFlags |= pC->fts5op;
|
|
+ }
|
|
+ else if( p->usable && bSeenEq==0
|
|
+ && p->op==SQLITE_INDEX_CONSTRAINT_EQ && iCol<0
|
|
+ ){
|
|
+ idxStr[iIdxStr++] = '=';
|
|
+ bSeenEq = 1;
|
|
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if( bSeenEq==0 ){
|
|
+ for(i=0; i<pInfo->nConstraint; i++){
|
|
+ struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
|
|
+ if( p->iColumn<0 && p->usable ){
|
|
+ int op = p->op;
|
|
+ if( op==SQLITE_INDEX_CONSTRAINT_LT || op==SQLITE_INDEX_CONSTRAINT_LE ){
|
|
+ if( bSeenLt ) continue;
|
|
+ idxStr[iIdxStr++] = '<';
|
|
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
|
+ bSeenLt = 1;
|
|
+ }else
|
|
+ if( op==SQLITE_INDEX_CONSTRAINT_GT || op==SQLITE_INDEX_CONSTRAINT_GE ){
|
|
+ if( bSeenGt ) continue;
|
|
+ idxStr[iIdxStr++] = '>';
|
|
+ pInfo->aConstraintUsage[i].argvIndex = ++iCons;
|
|
+ bSeenGt = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
+ idxStr[iIdxStr] = '\0';
|
|
|
|
/* Set idxFlags flags for the ORDER BY clause */
|
|
if( pInfo->nOrderBy==1 ){
|
|
int iSort = pInfo->aOrderBy[0].iColumn;
|
|
- if( iSort==(pConfig->nCol+1) && BitFlagTest(idxFlags, FTS5_BI_MATCH) ){
|
|
+ if( iSort==(pConfig->nCol+1) && bSeenMatch ){
|
|
idxFlags |= FTS5_BI_ORDER_RANK;
|
|
}else if( iSort==-1 ){
|
|
idxFlags |= FTS5_BI_ORDER_ROWID;
|
|
@@ -216947,26 +222721,15 @@
|
|
}
|
|
|
|
/* Calculate the estimated cost based on the flags set in idxFlags. */
|
|
- bHasMatch = BitFlagTest(idxFlags, FTS5_BI_MATCH);
|
|
- if( BitFlagTest(idxFlags, FTS5_BI_ROWID_EQ) ){
|
|
- pInfo->estimatedCost = bHasMatch ? 100.0 : 10.0;
|
|
- if( bHasMatch==0 ) fts5SetUniqueFlag(pInfo);
|
|
- }else if( BitFlagAllTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
|
|
- pInfo->estimatedCost = bHasMatch ? 500.0 : 250000.0;
|
|
- }else if( BitFlagTest(idxFlags, FTS5_BI_ROWID_LE|FTS5_BI_ROWID_GE) ){
|
|
- pInfo->estimatedCost = bHasMatch ? 750.0 : 750000.0;
|
|
+ if( bSeenEq ){
|
|
+ pInfo->estimatedCost = bSeenMatch ? 100.0 : 10.0;
|
|
+ if( bSeenMatch==0 ) fts5SetUniqueFlag(pInfo);
|
|
+ }else if( bSeenLt && bSeenGt ){
|
|
+ pInfo->estimatedCost = bSeenMatch ? 500.0 : 250000.0;
|
|
+ }else if( bSeenLt || bSeenGt ){
|
|
+ pInfo->estimatedCost = bSeenMatch ? 750.0 : 750000.0;
|
|
}else{
|
|
- pInfo->estimatedCost = bHasMatch ? 1000.0 : 1000000.0;
|
|
- }
|
|
-
|
|
- /* Assign argvIndex values to each constraint in use. */
|
|
- iNext = 1;
|
|
- for(i=0; i<ArraySize(aConstraint); i++){
|
|
- struct Constraint *pC = &aConstraint[i];
|
|
- if( pC->iConsIndex>=0 ){
|
|
- pInfo->aConstraintUsage[pC->iConsIndex].argvIndex = iNext++;
|
|
- pInfo->aConstraintUsage[pC->iConsIndex].omit = (unsigned char)pC->omit;
|
|
- }
|
|
+ pInfo->estimatedCost = bSeenMatch ? 1000.0 : 1000000.0;
|
|
}
|
|
|
|
pInfo->idxNum = idxFlags;
|
|
@@ -217066,6 +222829,7 @@
|
|
sqlite3_free(pCsr->zRankArgs);
|
|
}
|
|
|
|
+ sqlite3Fts5IndexCloseReader(pTab->p.pIndex);
|
|
memset(&pCsr->ePlan, 0, sizeof(Fts5Cursor) - ((u8*)&pCsr->ePlan - (u8*)pCsr));
|
|
}
|
|
|
|
@@ -217216,15 +222980,24 @@
|
|
break;
|
|
}
|
|
|
|
- default:
|
|
+ default: {
|
|
+ Fts5Config *pConfig = ((Fts5Table*)pCursor->pVtab)->pConfig;
|
|
+ pConfig->bLock++;
|
|
rc = sqlite3_step(pCsr->pStmt);
|
|
+ pConfig->bLock--;
|
|
if( rc!=SQLITE_ROW ){
|
|
CsrFlagSet(pCsr, FTS5CSR_EOF);
|
|
rc = sqlite3_reset(pCsr->pStmt);
|
|
+ if( rc!=SQLITE_OK ){
|
|
+ pCursor->pVtab->zErrMsg = sqlite3_mprintf(
|
|
+ "%s", sqlite3_errmsg(pConfig->db)
|
|
+ );
|
|
+ }
|
|
}else{
|
|
rc = SQLITE_OK;
|
|
}
|
|
break;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -217289,7 +223062,7 @@
|
|
**
|
|
** If SQLite a built-in statement cache, this wouldn't be a problem. */
|
|
rc = fts5PrepareStatement(&pSorter->pStmt, pConfig,
|
|
- "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(%s%s%s) %s",
|
|
+ "SELECT rowid, rank FROM %Q.%Q ORDER BY %s(\"%w\"%s%s) %s",
|
|
pConfig->zDb, pConfig->zName, zRank, pConfig->zName,
|
|
(zRankArgs ? ", " : ""),
|
|
(zRankArgs ? zRankArgs : ""),
|
|
@@ -217345,10 +223118,10 @@
|
|
assert( pTab->p.base.zErrMsg==0 );
|
|
pCsr->ePlan = FTS5_PLAN_SPECIAL;
|
|
|
|
- if( 0==sqlite3_strnicmp("reads", z, n) ){
|
|
+ if( n==5 && 0==sqlite3_strnicmp("reads", z, n) ){
|
|
pCsr->iSpecial = sqlite3Fts5IndexReads(pTab->p.pIndex);
|
|
}
|
|
- else if( 0==sqlite3_strnicmp("id", z, n) ){
|
|
+ else if( n==2 && 0==sqlite3_strnicmp("id", z, n) ){
|
|
pCsr->iSpecial = pCsr->iCsrId;
|
|
}
|
|
else{
|
|
@@ -217489,7 +223262,7 @@
|
|
static int fts5FilterMethod(
|
|
sqlite3_vtab_cursor *pCursor, /* The cursor used for this query */
|
|
int idxNum, /* Strategy index */
|
|
- const char *zUnused, /* Unused */
|
|
+ const char *idxStr, /* Unused */
|
|
int nVal, /* Number of elements in apVal */
|
|
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
|
){
|
|
@@ -217497,19 +223270,24 @@
|
|
Fts5Config *pConfig = pTab->p.pConfig;
|
|
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
|
int rc = SQLITE_OK; /* Error code */
|
|
- int iVal = 0; /* Counter for apVal[] */
|
|
int bDesc; /* True if ORDER BY [rank|rowid] DESC */
|
|
int bOrderByRank; /* True if ORDER BY rank */
|
|
- sqlite3_value *pMatch = 0; /* <tbl> MATCH ? expression (or NULL) */
|
|
sqlite3_value *pRank = 0; /* rank MATCH ? expression (or NULL) */
|
|
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
|
|
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
|
|
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
|
int iCol; /* Column on LHS of MATCH operator */
|
|
char **pzErrmsg = pConfig->pzErrmsg;
|
|
+ int i;
|
|
+ int iIdxStr = 0;
|
|
+ Fts5Expr *pExpr = 0;
|
|
|
|
- UNUSED_PARAM(zUnused);
|
|
- UNUSED_PARAM(nVal);
|
|
+ if( pConfig->bLock ){
|
|
+ pTab->p.base.zErrMsg = sqlite3_mprintf(
|
|
+ "recursively defined fts5 content table"
|
|
+ );
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
|
|
if( pCsr->ePlan ){
|
|
fts5FreeCursorComponents(pCsr);
|
|
@@ -217522,23 +223300,60 @@
|
|
assert( pCsr->pRank==0 );
|
|
assert( pCsr->zRank==0 );
|
|
assert( pCsr->zRankArgs==0 );
|
|
+ assert( pTab->pSortCsr==0 || nVal==0 );
|
|
|
|
assert( pzErrmsg==0 || pzErrmsg==&pTab->p.base.zErrMsg );
|
|
pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
|
|
|
|
- /* Decode the arguments passed through to this function.
|
|
- **
|
|
- ** Note: The following set of if(...) statements must be in the same
|
|
- ** order as the corresponding entries in the struct at the top of
|
|
- ** fts5BestIndexMethod(). */
|
|
- if( BitFlagTest(idxNum, FTS5_BI_MATCH) ) pMatch = apVal[iVal++];
|
|
- if( BitFlagTest(idxNum, FTS5_BI_RANK) ) pRank = apVal[iVal++];
|
|
- if( BitFlagTest(idxNum, FTS5_BI_ROWID_EQ) ) pRowidEq = apVal[iVal++];
|
|
- if( BitFlagTest(idxNum, FTS5_BI_ROWID_LE) ) pRowidLe = apVal[iVal++];
|
|
- if( BitFlagTest(idxNum, FTS5_BI_ROWID_GE) ) pRowidGe = apVal[iVal++];
|
|
- iCol = (idxNum>>16);
|
|
- assert( iCol>=0 && iCol<=pConfig->nCol );
|
|
- assert( iVal==nVal );
|
|
+ /* Decode the arguments passed through to this function. */
|
|
+ for(i=0; i<nVal; i++){
|
|
+ switch( idxStr[iIdxStr++] ){
|
|
+ case 'r':
|
|
+ pRank = apVal[i];
|
|
+ break;
|
|
+ case 'm': {
|
|
+ const char *zText = (const char*)sqlite3_value_text(apVal[i]);
|
|
+ if( zText==0 ) zText = "";
|
|
+
|
|
+ if( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' ){
|
|
+ iCol = 0;
|
|
+ do{
|
|
+ iCol = iCol*10 + (idxStr[iIdxStr]-'0');
|
|
+ iIdxStr++;
|
|
+ }while( idxStr[iIdxStr]>='0' && idxStr[iIdxStr]<='9' );
|
|
+ }else{
|
|
+ iCol = pConfig->nCol;
|
|
+ }
|
|
+
|
|
+ if( zText[0]=='*' ){
|
|
+ /* The user has issued a query of the form "MATCH '*...'". This
|
|
+ ** indicates that the MATCH expression is not a full text query,
|
|
+ ** but a request for an internal parameter. */
|
|
+ rc = fts5SpecialMatch(pTab, pCsr, &zText[1]);
|
|
+ goto filter_out;
|
|
+ }else{
|
|
+ char **pzErr = &pTab->p.base.zErrMsg;
|
|
+ rc = sqlite3Fts5ExprNew(pConfig, iCol, zText, &pExpr, pzErr);
|
|
+ if( rc==SQLITE_OK ){
|
|
+ rc = sqlite3Fts5ExprAnd(&pCsr->pExpr, pExpr);
|
|
+ pExpr = 0;
|
|
+ }
|
|
+ if( rc!=SQLITE_OK ) goto filter_out;
|
|
+ }
|
|
+
|
|
+ break;
|
|
+ }
|
|
+ case '=':
|
|
+ pRowidEq = apVal[i];
|
|
+ break;
|
|
+ case '<':
|
|
+ pRowidLe = apVal[i];
|
|
+ break;
|
|
+ default: assert( idxStr[iIdxStr-1]=='>' );
|
|
+ pRowidGe = apVal[i];
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
bOrderByRank = ((idxNum & FTS5_BI_ORDER_RANK) ? 1 : 0);
|
|
pCsr->bDesc = bDesc = ((idxNum & FTS5_BI_ORDER_DESC) ? 1 : 0);
|
|
|
|
@@ -217565,7 +223380,7 @@
|
|
** (pCursor) is used to execute the query issued by function
|
|
** fts5CursorFirstSorted() above. */
|
|
assert( pRowidEq==0 && pRowidLe==0 && pRowidGe==0 && pRank==0 );
|
|
- assert( nVal==0 && pMatch==0 && bOrderByRank==0 && bDesc==0 );
|
|
+ assert( nVal==0 && bOrderByRank==0 && bDesc==0 );
|
|
assert( pCsr->iLastRowid==LARGEST_INT64 );
|
|
assert( pCsr->iFirstRowid==SMALLEST_INT64 );
|
|
if( pTab->pSortCsr->bDesc ){
|
|
@@ -217578,29 +223393,15 @@
|
|
pCsr->ePlan = FTS5_PLAN_SOURCE;
|
|
pCsr->pExpr = pTab->pSortCsr->pExpr;
|
|
rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
|
- }else if( pMatch ){
|
|
- const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
|
- if( zExpr==0 ) zExpr = "";
|
|
-
|
|
+ }else if( pCsr->pExpr ){
|
|
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
|
|
if( rc==SQLITE_OK ){
|
|
- if( zExpr[0]=='*' ){
|
|
- /* The user has issued a query of the form "MATCH '*...'". This
|
|
- ** indicates that the MATCH expression is not a full text query,
|
|
- ** but a request for an internal parameter. */
|
|
- rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
|
|
+ if( bOrderByRank ){
|
|
+ pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
|
+ rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
|
|
}else{
|
|
- char **pzErr = &pTab->p.base.zErrMsg;
|
|
- rc = sqlite3Fts5ExprNew(pConfig, iCol, zExpr, &pCsr->pExpr, pzErr);
|
|
- if( rc==SQLITE_OK ){
|
|
- if( bOrderByRank ){
|
|
- pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
|
- rc = fts5CursorFirstSorted(pTab, pCsr, bDesc);
|
|
- }else{
|
|
- pCsr->ePlan = FTS5_PLAN_MATCH;
|
|
- rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
|
- }
|
|
- }
|
|
+ pCsr->ePlan = FTS5_PLAN_MATCH;
|
|
+ rc = fts5CursorFirst(pTab, pCsr, bDesc);
|
|
}
|
|
}
|
|
}else if( pConfig->zContent==0 ){
|
|
@@ -217617,7 +223418,7 @@
|
|
);
|
|
if( rc==SQLITE_OK ){
|
|
if( pCsr->ePlan==FTS5_PLAN_ROWID ){
|
|
- sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
|
|
+ sqlite3_bind_value(pCsr->pStmt, 1, pRowidEq);
|
|
}else{
|
|
sqlite3_bind_int64(pCsr->pStmt, 1, pCsr->iFirstRowid);
|
|
sqlite3_bind_int64(pCsr->pStmt, 2, pCsr->iLastRowid);
|
|
@@ -217626,6 +223427,8 @@
|
|
}
|
|
}
|
|
|
|
+ filter_out:
|
|
+ sqlite3Fts5ExprFree(pExpr);
|
|
pConfig->pzErrmsg = pzErrmsg;
|
|
return rc;
|
|
}
|
|
@@ -217706,10 +223509,13 @@
|
|
}
|
|
|
|
if( rc==SQLITE_OK && CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) ){
|
|
+ Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
|
|
assert( pCsr->pExpr );
|
|
sqlite3_reset(pCsr->pStmt);
|
|
sqlite3_bind_int64(pCsr->pStmt, 1, fts5CursorRowid(pCsr));
|
|
+ pTab->pConfig->bLock++;
|
|
rc = sqlite3_step(pCsr->pStmt);
|
|
+ pTab->pConfig->bLock--;
|
|
if( rc==SQLITE_ROW ){
|
|
rc = SQLITE_OK;
|
|
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_CONTENT);
|
|
@@ -217717,6 +223523,10 @@
|
|
rc = sqlite3_reset(pCsr->pStmt);
|
|
if( rc==SQLITE_OK ){
|
|
rc = FTS5_CORRUPT;
|
|
+ }else if( pTab->pConfig->pzErrmsg ){
|
|
+ *pTab->pConfig->pzErrmsg = sqlite3_mprintf(
|
|
+ "%s", sqlite3_errmsg(pTab->pConfig->db)
|
|
+ );
|
|
}
|
|
}
|
|
}
|
|
@@ -218596,7 +224406,7 @@
|
|
iCsrId = sqlite3_value_int64(argv[0]);
|
|
|
|
pCsr = fts5CursorFromCsrid(pAux->pGlobal, iCsrId);
|
|
- if( pCsr==0 ){
|
|
+ if( pCsr==0 || pCsr->ePlan==0 ){
|
|
char *zErr = sqlite3_mprintf("no such cursor: %lld", iCsrId);
|
|
sqlite3_result_error(context, zErr, -1);
|
|
sqlite3_free(zErr);
|
|
@@ -218732,10 +224542,12 @@
|
|
}
|
|
}
|
|
}else if( !fts5IsContentless(pTab) ){
|
|
+ pConfig->pzErrmsg = &pTab->p.base.zErrMsg;
|
|
rc = fts5SeekCursor(pCsr, 1);
|
|
if( rc==SQLITE_OK ){
|
|
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
|
}
|
|
+ pConfig->pzErrmsg = 0;
|
|
}
|
|
return rc;
|
|
}
|
|
@@ -219012,7 +224824,7 @@
|
|
){
|
|
assert( nArg==0 );
|
|
UNUSED_PARAM2(nArg, apUnused);
|
|
- sqlite3_result_text(pCtx, "fts5: 2019-07-10 17:32:03 fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6", -1, SQLITE_TRANSIENT);
|
|
+ sqlite3_result_text(pCtx, "fts5: 2020-06-04 12:58:43 ec02243ea6ce33b090870ae55ab8aa2534b54d216d45c4aa2fdbb00e86861e8c", -1, SQLITE_TRANSIENT);
|
|
}
|
|
|
|
/*
|
|
@@ -219284,7 +225096,9 @@
|
|
}else{
|
|
int f = SQLITE_PREPARE_PERSISTENT;
|
|
if( eStmt>FTS5_STMT_LOOKUP ) f |= SQLITE_PREPARE_NO_VTAB;
|
|
+ p->pConfig->bLock++;
|
|
rc = sqlite3_prepare_v3(pC->db, zSql, -1, f, &p->aStmt[eStmt], 0);
|
|
+ p->pConfig->bLock--;
|
|
sqlite3_free(zSql);
|
|
if( rc!=SQLITE_OK && pzErrMsg ){
|
|
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
|
|
@@ -219704,6 +225518,8 @@
|
|
Fts5Config *pConfig = p->pConfig;
|
|
int rc;
|
|
|
|
+ p->bTotalsValid = 0;
|
|
+
|
|
/* Delete the contents of the %_data and %_docsize tables. */
|
|
rc = fts5ExecPrintf(pConfig->db, 0,
|
|
"DELETE FROM %Q.'%q_data';"
|
|
@@ -219755,10 +225571,11 @@
|
|
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
|
ctx.szCol = 0;
|
|
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
|
+ const char *zText = (const char*)sqlite3_column_text(pScan, ctx.iCol+1);
|
|
+ int nText = sqlite3_column_bytes(pScan, ctx.iCol+1);
|
|
rc = sqlite3Fts5Tokenize(pConfig,
|
|
FTS5_TOKENIZE_DOCUMENT,
|
|
- (const char*)sqlite3_column_text(pScan, ctx.iCol+1),
|
|
- sqlite3_column_bytes(pScan, ctx.iCol+1),
|
|
+ zText, nText,
|
|
(void*)&ctx,
|
|
fts5StorageInsertCallback
|
|
);
|
|
@@ -219880,10 +225697,11 @@
|
|
for(ctx.iCol=0; rc==SQLITE_OK && ctx.iCol<pConfig->nCol; ctx.iCol++){
|
|
ctx.szCol = 0;
|
|
if( pConfig->abUnindexed[ctx.iCol]==0 ){
|
|
+ const char *zText = (const char*)sqlite3_value_text(apVal[ctx.iCol+2]);
|
|
+ int nText = sqlite3_value_bytes(apVal[ctx.iCol+2]);
|
|
rc = sqlite3Fts5Tokenize(pConfig,
|
|
FTS5_TOKENIZE_DOCUMENT,
|
|
- (const char*)sqlite3_value_text(apVal[ctx.iCol+2]),
|
|
- sqlite3_value_bytes(apVal[ctx.iCol+2]),
|
|
+ zText, nText,
|
|
(void*)&ctx,
|
|
fts5StorageInsertCallback
|
|
);
|
|
@@ -220052,10 +225870,11 @@
|
|
rc = sqlite3Fts5TermsetNew(&ctx.pTermset);
|
|
}
|
|
if( rc==SQLITE_OK ){
|
|
+ const char *zText = (const char*)sqlite3_column_text(pScan, i+1);
|
|
+ int nText = sqlite3_column_bytes(pScan, i+1);
|
|
rc = sqlite3Fts5Tokenize(pConfig,
|
|
FTS5_TOKENIZE_DOCUMENT,
|
|
- (const char*)sqlite3_column_text(pScan, i+1),
|
|
- sqlite3_column_bytes(pScan, i+1),
|
|
+ zText, nText,
|
|
(void*)&ctx,
|
|
fts5StorageIntegrityCallback
|
|
);
|
|
@@ -222748,6 +228567,7 @@
|
|
sqlite3 *db; /* Database handle */
|
|
Fts5Global *pGlobal; /* FTS5 global object for this database */
|
|
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
|
|
+ unsigned bBusy; /* True if busy */
|
|
};
|
|
|
|
struct Fts5VocabCursor {
|
|
@@ -223030,6 +228850,12 @@
|
|
sqlite3_stmt *pStmt = 0;
|
|
char *zSql = 0;
|
|
|
|
+ if( pTab->bBusy ){
|
|
+ pVTab->zErrMsg = sqlite3_mprintf(
|
|
+ "recursive definition for %s.%s", pTab->zFts5Db, pTab->zFts5Tbl
|
|
+ );
|
|
+ return SQLITE_ERROR;
|
|
+ }
|
|
zSql = sqlite3Fts5Mprintf(&rc,
|
|
"SELECT t.%Q FROM %Q.%Q AS t WHERE t.%Q MATCH '*id'",
|
|
pTab->zFts5Tbl, pTab->zFts5Db, pTab->zFts5Tbl, pTab->zFts5Tbl
|
|
@@ -223041,10 +228867,12 @@
|
|
assert( rc==SQLITE_OK || pStmt==0 );
|
|
if( rc==SQLITE_ERROR ) rc = SQLITE_OK;
|
|
|
|
+ pTab->bBusy = 1;
|
|
if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
|
|
i64 iId = sqlite3_column_int64(pStmt, 0);
|
|
pFts5 = sqlite3Fts5TableFromCsrid(pTab->pGlobal, iId);
|
|
}
|
|
+ pTab->bBusy = 0;
|
|
|
|
if( rc==SQLITE_OK ){
|
|
if( pFts5==0 ){
|
|
@@ -223647,7 +229475,8 @@
|
|
sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
|
|
break;
|
|
}
|
|
- case STMT_COLUMN_MEM: {
|
|
+ default: {
|
|
+ assert( i==STMT_COLUMN_MEM );
|
|
i = SQLITE_STMTSTATUS_MEMUSED +
|
|
STMT_COLUMN_NSCAN - SQLITE_STMTSTATUS_FULLSCAN_STEP;
|
|
/* Fall thru */
|
|
@@ -223778,9 +229607,9 @@
|
|
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_STMTVTAB) */
|
|
|
|
/************** End of stmt.c ************************************************/
|
|
-#if __LINE__!=223781
|
|
+#if __LINE__!=229610
|
|
#undef SQLITE_SOURCE_ID
|
|
-#define SQLITE_SOURCE_ID "2019-07-10 17:32:03 fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88alt2"
|
|
+#define SQLITE_SOURCE_ID "2020-06-04 12:58:43 ec02243ea6ce33b090870ae55ab8aa2534b54d216d45c4aa2fdbb00e8686alt2"
|
|
#endif
|
|
/* Return the source-id for this library */
|
|
SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
|
|
--- contrib/sqlite3/sqlite3.h.orig
|
|
+++ contrib/sqlite3/sqlite3.h
|
|
@@ -123,9 +123,9 @@
|
|
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
|
|
** [sqlite_version()] and [sqlite_source_id()].
|
|
*/
|
|
-#define SQLITE_VERSION "3.29.0"
|
|
-#define SQLITE_VERSION_NUMBER 3029000
|
|
-#define SQLITE_SOURCE_ID "2019-07-10 17:32:03 fc82b73eaac8b36950e527f12c4b5dc1e147e6f4ad2217ae43ad82882a88bfa6"
|
|
+#define SQLITE_VERSION "3.32.2"
|
|
+#define SQLITE_VERSION_NUMBER 3032002
|
|
+#define SQLITE_SOURCE_ID "2020-06-04 12:58:43 ec02243ea6ce33b090870ae55ab8aa2534b54d216d45c4aa2fdbb00e86861e8c"
|
|
|
|
/*
|
|
** CAPI3REF: Run-Time Library Version Numbers
|
|
@@ -299,26 +299,22 @@
|
|
** the [sqlite3] object is successfully destroyed and all associated
|
|
** resources are deallocated.
|
|
**
|
|
-** ^If the database connection is associated with unfinalized prepared
|
|
-** statements or unfinished sqlite3_backup objects then sqlite3_close()
|
|
-** will leave the database connection open and return [SQLITE_BUSY].
|
|
-** ^If sqlite3_close_v2() is called with unfinalized prepared statements
|
|
-** and/or unfinished sqlite3_backups, then the database connection becomes
|
|
-** an unusable "zombie" which will automatically be deallocated when the
|
|
-** last prepared statement is finalized or the last sqlite3_backup is
|
|
-** finished. The sqlite3_close_v2() interface is intended for use with
|
|
-** host languages that are garbage collected, and where the order in which
|
|
-** destructors are called is arbitrary.
|
|
-**
|
|
-** Applications should [sqlite3_finalize | finalize] all [prepared statements],
|
|
-** [sqlite3_blob_close | close] all [BLOB handles], and
|
|
+** Ideally, applications should [sqlite3_finalize | finalize] all
|
|
+** [prepared statements], [sqlite3_blob_close | close] all [BLOB handles], and
|
|
** [sqlite3_backup_finish | finish] all [sqlite3_backup] objects associated
|
|
-** with the [sqlite3] object prior to attempting to close the object. ^If
|
|
-** sqlite3_close_v2() is called on a [database connection] that still has
|
|
-** outstanding [prepared statements], [BLOB handles], and/or
|
|
-** [sqlite3_backup] objects then it returns [SQLITE_OK] and the deallocation
|
|
-** of resources is deferred until all [prepared statements], [BLOB handles],
|
|
-** and [sqlite3_backup] objects are also destroyed.
|
|
+** with the [sqlite3] object prior to attempting to close the object.
|
|
+** ^If the database connection is associated with unfinalized prepared
|
|
+** statements, BLOB handlers, and/or unfinished sqlite3_backup objects then
|
|
+** sqlite3_close() will leave the database connection open and return
|
|
+** [SQLITE_BUSY]. ^If sqlite3_close_v2() is called with unfinalized prepared
|
|
+** statements, unclosed BLOB handlers, and/or unfinished sqlite3_backups,
|
|
+** it returns [SQLITE_OK] regardless, but instead of deallocating the database
|
|
+** connection immediately, it marks the database connection as an unusable
|
|
+** "zombie" and makes arrangements to automatically deallocate the database
|
|
+** connection after all prepared statements are finalized, all BLOB handles
|
|
+** are closed, and all backups have finished. The sqlite3_close_v2() interface
|
|
+** is intended for use with host languages that are garbage collected, and
|
|
+** where the order in which destructors are called is arbitrary.
|
|
**
|
|
** ^If an [sqlite3] object is destroyed while a transaction is open,
|
|
** the transaction is automatically rolled back.
|
|
@@ -507,17 +503,21 @@
|
|
#define SQLITE_IOERR_BEGIN_ATOMIC (SQLITE_IOERR | (29<<8))
|
|
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
|
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
|
+#define SQLITE_IOERR_DATA (SQLITE_IOERR | (32<<8))
|
|
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
|
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
|
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
|
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
|
+#define SQLITE_BUSY_TIMEOUT (SQLITE_BUSY | (3<<8))
|
|
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
|
#define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8))
|
|
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
|
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
|
#define SQLITE_CANTOPEN_DIRTYWAL (SQLITE_CANTOPEN | (5<<8)) /* Not Used */
|
|
+#define SQLITE_CANTOPEN_SYMLINK (SQLITE_CANTOPEN | (6<<8))
|
|
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
|
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
|
+#define SQLITE_CORRUPT_INDEX (SQLITE_CORRUPT | (3<<8))
|
|
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
|
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
|
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
|
@@ -535,11 +535,13 @@
|
|
#define SQLITE_CONSTRAINT_UNIQUE (SQLITE_CONSTRAINT | (8<<8))
|
|
#define SQLITE_CONSTRAINT_VTAB (SQLITE_CONSTRAINT | (9<<8))
|
|
#define SQLITE_CONSTRAINT_ROWID (SQLITE_CONSTRAINT |(10<<8))
|
|
+#define SQLITE_CONSTRAINT_PINNED (SQLITE_CONSTRAINT |(11<<8))
|
|
#define SQLITE_NOTICE_RECOVER_WAL (SQLITE_NOTICE | (1<<8))
|
|
#define SQLITE_NOTICE_RECOVER_ROLLBACK (SQLITE_NOTICE | (2<<8))
|
|
#define SQLITE_WARNING_AUTOINDEX (SQLITE_WARNING | (1<<8))
|
|
#define SQLITE_AUTH_USER (SQLITE_AUTH | (1<<8))
|
|
#define SQLITE_OK_LOAD_PERMANENTLY (SQLITE_OK | (1<<8))
|
|
+#define SQLITE_OK_SYMLINK (SQLITE_OK | (2<<8))
|
|
|
|
/*
|
|
** CAPI3REF: Flags For File Open Operations
|
|
@@ -568,6 +570,7 @@
|
|
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_PRIVATECACHE 0x00040000 /* Ok for sqlite3_open_v2() */
|
|
#define SQLITE_OPEN_WAL 0x00080000 /* VFS only */
|
|
+#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
|
|
|
|
/* Reserved: 0x00F00000 */
|
|
|
|
@@ -979,16 +982,16 @@
|
|
** ^The [SQLITE_FCNTL_BUSYHANDLER]
|
|
** file-control may be invoked by SQLite on the database file handle
|
|
** shortly after it is opened in order to provide a custom VFS with access
|
|
-** to the connections busy-handler callback. The argument is of type (void **)
|
|
+** to the connection's busy-handler callback. The argument is of type (void**)
|
|
** - an array of two (void *) values. The first (void *) actually points
|
|
-** to a function of type (int (*)(void *)). In order to invoke the connections
|
|
+** to a function of type (int (*)(void *)). In order to invoke the connection's
|
|
** busy-handler, this function should be invoked with the second (void *) in
|
|
** the array as the only argument. If it returns non-zero, then the operation
|
|
** should be retried. If it returns zero, the custom VFS should abandon the
|
|
** current operation.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_TEMPFILENAME]]
|
|
-** ^Application can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
|
|
+** ^Applications can invoke the [SQLITE_FCNTL_TEMPFILENAME] file-control
|
|
** to have SQLite generate a
|
|
** temporary filename using the same algorithm that is followed to generate
|
|
** temporary filenames for TEMP tables and other internal uses. The
|
|
@@ -1083,10 +1086,12 @@
|
|
** a prior successful call to [SQLITE_FCNTL_BEGIN_ATOMIC_WRITE].
|
|
**
|
|
** <li>[[SQLITE_FCNTL_LOCK_TIMEOUT]]
|
|
-** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode causes attempts to obtain
|
|
-** a file lock using the xLock or xShmLock methods of the VFS to wait
|
|
-** for up to M milliseconds before failing, where M is the single
|
|
-** unsigned integer parameter.
|
|
+** The [SQLITE_FCNTL_LOCK_TIMEOUT] opcode is used to configure a VFS
|
|
+** to block for up to M milliseconds before failing when attempting to
|
|
+** obtain a file lock using the xLock or xShmLock methods of the VFS.
|
|
+** The parameter is a pointer to a 32-bit signed integer that contains
|
|
+** the value that M is to be set to. Before returning, the 32-bit signed
|
|
+** integer is overwritten with the previous value of M.
|
|
**
|
|
** <li>[[SQLITE_FCNTL_DATA_VERSION]]
|
|
** The [SQLITE_FCNTL_DATA_VERSION] opcode is used to detect changes to
|
|
@@ -1101,12 +1106,23 @@
|
|
** not provide a mechanism to detect changes to MAIN only. Also, the
|
|
** [sqlite3_total_changes()] interface responds to internal changes only and
|
|
** omits changes made by other database connections. The
|
|
-** [PRAGMA data_version] command provide a mechanism to detect changes to
|
|
+** [PRAGMA data_version] command provides a mechanism to detect changes to
|
|
** a single attached database that occur due to other database connections,
|
|
** but omits changes implemented by the database connection on which it is
|
|
** called. This file control is the only mechanism to detect changes that
|
|
** happen either internally or externally and that are associated with
|
|
** a particular attached database.
|
|
+**
|
|
+** <li>[[SQLITE_FCNTL_CKPT_START]]
|
|
+** The [SQLITE_FCNTL_CKPT_START] opcode is invoked from within a checkpoint
|
|
+** in wal mode before the client starts to copy pages from the wal
|
|
+** file to the database file.
|
|
+**
|
|
+** <li>[[SQLITE_FCNTL_CKPT_DONE]]
|
|
+** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint
|
|
+** in wal mode after the client has finished copying pages from the wal
|
|
+** file to the database file, but before the *-shm file is updated to
|
|
+** record the fact that the pages have been checkpointed.
|
|
** </ul>
|
|
*/
|
|
#define SQLITE_FCNTL_LOCKSTATE 1
|
|
@@ -1144,6 +1160,9 @@
|
|
#define SQLITE_FCNTL_LOCK_TIMEOUT 34
|
|
#define SQLITE_FCNTL_DATA_VERSION 35
|
|
#define SQLITE_FCNTL_SIZE_LIMIT 36
|
|
+#define SQLITE_FCNTL_CKPT_DONE 37
|
|
+#define SQLITE_FCNTL_RESERVE_BYTES 38
|
|
+#define SQLITE_FCNTL_CKPT_START 39
|
|
|
|
/* deprecated names */
|
|
#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
|
|
@@ -1189,10 +1208,10 @@
|
|
** to 3 with SQLite [version 3.7.6] on [dateof:3.7.6]. Additional fields
|
|
** may be appended to the sqlite3_vfs object and the iVersion value
|
|
** may increase again in future versions of SQLite.
|
|
-** Note that the structure
|
|
-** of the sqlite3_vfs object changes in the transition from
|
|
+** Note that due to an oversight, the structure
|
|
+** of the sqlite3_vfs object changed in the transition from
|
|
** SQLite [version 3.5.9] to [version 3.6.0] on [dateof:3.6.0]
|
|
-** and yet the iVersion field was not modified.
|
|
+** and yet the iVersion field was not increased.
|
|
**
|
|
** The szOsFile field is the size of the subclassed [sqlite3_file]
|
|
** structure used by this VFS. mxPathname is the maximum length of
|
|
@@ -1283,7 +1302,7 @@
|
|
** for exclusive access.
|
|
**
|
|
** ^At least szOsFile bytes of memory are allocated by SQLite
|
|
-** to hold the [sqlite3_file] structure passed as the third
|
|
+** to hold the [sqlite3_file] structure passed as the third
|
|
** argument to xOpen. The xOpen method does not have to
|
|
** allocate the structure; it should just fill it in. Note that
|
|
** the xOpen method must set the sqlite3_file.pMethods to either
|
|
@@ -1620,7 +1639,7 @@
|
|
** that causes the corresponding memory allocation to fail.
|
|
**
|
|
** The xInit method initializes the memory allocator. For example,
|
|
-** it might allocate any require mutexes or initialize internal data
|
|
+** it might allocate any required mutexes or initialize internal data
|
|
** structures. The xShutdown method is invoked (indirectly) by
|
|
** [sqlite3_shutdown()] and should deallocate any resources acquired
|
|
** by xInit. The pAppData pointer is used as the only parameter to
|
|
@@ -1742,6 +1761,7 @@
|
|
** memory allocation statistics. ^(When memory allocation statistics are
|
|
** disabled, the following SQLite interfaces become non-operational:
|
|
** <ul>
|
|
+** <li> [sqlite3_hard_heap_limit64()]
|
|
** <li> [sqlite3_memory_used()]
|
|
** <li> [sqlite3_memory_highwater()]
|
|
** <li> [sqlite3_soft_heap_limit64()]
|
|
@@ -1760,7 +1780,7 @@
|
|
** <dd> ^The SQLITE_CONFIG_PAGECACHE option specifies a memory pool
|
|
** that SQLite can use for the database page cache with the default page
|
|
** cache implementation.
|
|
-** This configuration option is a no-op if an application-define page
|
|
+** This configuration option is a no-op if an application-defined page
|
|
** cache implementation is loaded using the [SQLITE_CONFIG_PCACHE2].
|
|
** ^There are three arguments to SQLITE_CONFIG_PAGECACHE: A pointer to
|
|
** 8-byte aligned memory (pMem), the size of each page cache line (sz),
|
|
@@ -2093,6 +2113,17 @@
|
|
** following this call. The second parameter may be a NULL pointer, in
|
|
** which case the trigger setting is not reported back. </dd>
|
|
**
|
|
+** [[SQLITE_DBCONFIG_ENABLE_VIEW]]
|
|
+** <dt>SQLITE_DBCONFIG_ENABLE_VIEW</dt>
|
|
+** <dd> ^This option is used to enable or disable [CREATE VIEW | views].
|
|
+** There should be two additional arguments.
|
|
+** The first argument is an integer which is 0 to disable views,
|
|
+** positive to enable views or negative to leave the setting unchanged.
|
|
+** The second parameter is a pointer to an integer into which
|
|
+** is written 0 or 1 to indicate whether views are disabled or enabled
|
|
+** following this call. The second parameter may be a NULL pointer, in
|
|
+** which case the view setting is not reported back. </dd>
|
|
+**
|
|
** [[SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER]]
|
|
** <dt>SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER</dt>
|
|
** <dd> ^This option is used to enable or disable the
|
|
@@ -2234,7 +2265,7 @@
|
|
** [[SQLITE_DBCONFIG_DQS_DML]]
|
|
** <dt>SQLITE_DBCONFIG_DQS_DML</td>
|
|
** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates
|
|
-** the legacy [double-quoted string literal] misfeature for DML statement
|
|
+** the legacy [double-quoted string literal] misfeature for DML statements
|
|
** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The
|
|
** default value of this setting is determined by the [-DSQLITE_DQS]
|
|
** compile-time option.
|
|
@@ -2248,6 +2279,49 @@
|
|
** default value of this setting is determined by the [-DSQLITE_DQS]
|
|
** compile-time option.
|
|
** </dd>
|
|
+**
|
|
+** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
|
|
+** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
|
|
+** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
|
|
+** assume that database schemas (the contents of the [sqlite_master] tables)
|
|
+** are untainted by malicious content.
|
|
+** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
|
|
+** takes additional defensive steps to protect the application from harm
|
|
+** including:
|
|
+** <ul>
|
|
+** <li> Prohibit the use of SQL functions inside triggers, views,
|
|
+** CHECK constraints, DEFAULT clauses, expression indexes,
|
|
+** partial indexes, or generated columns
|
|
+** unless those functions are tagged with [SQLITE_INNOCUOUS].
|
|
+** <li> Prohibit the use of virtual tables inside of triggers or views
|
|
+** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS].
|
|
+** </ul>
|
|
+** This setting defaults to "on" for legacy compatibility, however
|
|
+** all applications are advised to turn it off if possible. This setting
|
|
+** can also be controlled using the [PRAGMA trusted_schema] statement.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]]
|
|
+** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td>
|
|
+** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates
|
|
+** the legacy file format flag. When activated, this flag causes all newly
|
|
+** created database file to have a schema format version number (the 4-byte
|
|
+** integer found at offset 44 into the database header) of 1. This in turn
|
|
+** means that the resulting database file will be readable and writable by
|
|
+** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting,
|
|
+** newly created databases are generally not understandable by SQLite versions
|
|
+** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there
|
|
+** is now scarcely any need to generated database files that are compatible
|
|
+** all the way back to version 3.0.0, and so this setting is of little
|
|
+** practical use, but is provided so that SQLite can continue to claim the
|
|
+** ability to generate new database files that are compatible with version
|
|
+** 3.0.0.
|
|
+** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on,
|
|
+** the [VACUUM] command will fail with an obscure error when attempting to
|
|
+** process a table with generated columns and a descending index. This is
|
|
+** not considered a bug since SQLite versions 3.3.0 and earlier do not support
|
|
+** either generated columns or decending indexes.
|
|
+** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
|
@@ -2265,7 +2339,10 @@
|
|
#define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */
|
|
#define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */
|
|
#define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */
|
|
-#define SQLITE_DBCONFIG_MAX 1014 /* Largest DBCONFIG */
|
|
+#define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */
|
|
+#define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */
|
|
+#define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */
|
|
+#define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */
|
|
|
|
/*
|
|
** CAPI3REF: Enable Or Disable Extended Result Codes
|
|
@@ -2471,7 +2548,7 @@
|
|
** ^The sqlite3_interrupt(D) call is in effect until all currently running
|
|
** SQL statements on [database connection] D complete. ^Any new SQL statements
|
|
** that are started after the sqlite3_interrupt() call and before the
|
|
-** running statements reaches zero are interrupted as if they had been
|
|
+** running statement count reaches zero are interrupted as if they had been
|
|
** running prior to the sqlite3_interrupt() call. ^New SQL statements
|
|
** that are started after the running statement count reaches zero are
|
|
** not effected by the sqlite3_interrupt().
|
|
@@ -2639,9 +2716,9 @@
|
|
** Cindy | 21
|
|
** </pre></blockquote>
|
|
**
|
|
-** There are two column (M==2) and three rows (N==3). Thus the
|
|
+** There are two columns (M==2) and three rows (N==3). Thus the
|
|
** result table has 8 entries. Suppose the result table is stored
|
|
-** in an array names azResult. Then azResult holds this content:
|
|
+** in an array named azResult. Then azResult holds this content:
|
|
**
|
|
** <blockquote><pre>
|
|
** azResult[0] = "Name";
|
|
@@ -2734,7 +2811,7 @@
|
|
**
|
|
** The SQLite core uses these three routines for all of its own
|
|
** internal memory allocation needs. "Core" in the previous sentence
|
|
-** does not include operating-system specific VFS implementation. The
|
|
+** does not include operating-system specific [VFS] implementation. The
|
|
** Windows VFS uses native malloc() and free() for some operations.
|
|
**
|
|
** ^The sqlite3_malloc() routine returns a pointer to a block
|
|
@@ -2795,19 +2872,6 @@
|
|
** 4 byte boundary if the [SQLITE_4_BYTE_ALIGNED_MALLOC] compile-time
|
|
** option is used.
|
|
**
|
|
-** In SQLite version 3.5.0 and 3.5.1, it was possible to define
|
|
-** the SQLITE_OMIT_MEMORY_ALLOCATION which would cause the built-in
|
|
-** implementation of these routines to be omitted. That capability
|
|
-** is no longer provided. Only built-in memory allocators can be used.
|
|
-**
|
|
-** Prior to SQLite version 3.7.10, the Windows OS interface layer called
|
|
-** the system malloc() and free() directly when converting
|
|
-** filenames between the UTF-8 encoding used by SQLite
|
|
-** and whatever filename encoding is used by the particular Windows
|
|
-** installation. Memory allocation errors were detected, but
|
|
-** they were reported back as [SQLITE_CANTOPEN] or
|
|
-** [SQLITE_IOERR] rather than [SQLITE_NOMEM].
|
|
-**
|
|
** The pointer arguments to [sqlite3_free()] and [sqlite3_realloc()]
|
|
** must be either NULL or else pointers obtained from a prior
|
|
** invocation of [sqlite3_malloc()] or [sqlite3_realloc()] that have
|
|
@@ -2856,7 +2920,7 @@
|
|
** SQLite contains a high-quality pseudo-random number generator (PRNG) used to
|
|
** select random [ROWID | ROWIDs] when inserting new records into a table that
|
|
** already uses the largest possible [ROWID]. The PRNG is also used for
|
|
-** the build-in random() and randomblob() SQL functions. This interface allows
|
|
+** the built-in random() and randomblob() SQL functions. This interface allows
|
|
** applications to access the same PRNG for other purposes.
|
|
**
|
|
** ^A call to this routine stores N bytes of randomness into buffer P.
|
|
@@ -3230,10 +3294,8 @@
|
|
** The sqlite3_open_v2() interface works like sqlite3_open()
|
|
** except that it accepts two additional parameters for additional control
|
|
** over the new database connection. ^(The flags parameter to
|
|
-** sqlite3_open_v2() can take one of
|
|
-** the following three values, optionally combined with the
|
|
-** [SQLITE_OPEN_NOMUTEX], [SQLITE_OPEN_FULLMUTEX], [SQLITE_OPEN_SHAREDCACHE],
|
|
-** [SQLITE_OPEN_PRIVATECACHE], and/or [SQLITE_OPEN_URI] flags:)^
|
|
+** sqlite3_open_v2() must include, at a minimum, one of the following
|
|
+** three flag combinations:)^
|
|
**
|
|
** <dl>
|
|
** ^(<dt>[SQLITE_OPEN_READONLY]</dt>
|
|
@@ -3251,23 +3313,51 @@
|
|
** sqlite3_open() and sqlite3_open16().</dd>)^
|
|
** </dl>
|
|
**
|
|
+** In addition to the required flags, the following optional flags are
|
|
+** also supported:
|
|
+**
|
|
+** <dl>
|
|
+** ^(<dt>[SQLITE_OPEN_URI]</dt>
|
|
+** <dd>The filename can be interpreted as a URI if this flag is set.</dd>)^
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_MEMORY]</dt>
|
|
+** <dd>The database will be opened as an in-memory database. The database
|
|
+** is named by the "filename" argument for the purposes of cache-sharing,
|
|
+** if shared cache mode is enabled, but the "filename" is otherwise ignored.
|
|
+** </dd>)^
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_NOMUTEX]</dt>
|
|
+** <dd>The new database connection will use the "multi-thread"
|
|
+** [threading mode].)^ This means that separate threads are allowed
|
|
+** to use SQLite at the same time, as long as each thread is using
|
|
+** a different [database connection].
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_FULLMUTEX]</dt>
|
|
+** <dd>The new database connection will use the "serialized"
|
|
+** [threading mode].)^ This means the multiple threads can safely
|
|
+** attempt to use the same database connection at the same time.
|
|
+** (Mutexes will block any actual concurrency, but in this mode
|
|
+** there is no harm in trying.)
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_SHAREDCACHE]</dt>
|
|
+** <dd>The database is opened [shared cache] enabled, overriding
|
|
+** the default shared cache setting provided by
|
|
+** [sqlite3_enable_shared_cache()].)^
|
|
+**
|
|
+** ^(<dt>[SQLITE_OPEN_PRIVATECACHE]</dt>
|
|
+** <dd>The database is opened [shared cache] disabled, overriding
|
|
+** the default shared cache setting provided by
|
|
+** [sqlite3_enable_shared_cache()].)^
|
|
+**
|
|
+** [[OPEN_NOFOLLOW]] ^(<dt>[SQLITE_OPEN_NOFOLLOW]</dt>
|
|
+** <dd>The database filename is not allowed to be a symbolic link</dd>
|
|
+** </dl>)^
|
|
+**
|
|
** If the 3rd parameter to sqlite3_open_v2() is not one of the
|
|
-** combinations shown above optionally combined with other
|
|
+** required combinations shown above optionally combined with other
|
|
** [SQLITE_OPEN_READONLY | SQLITE_OPEN_* bits]
|
|
** then the behavior is undefined.
|
|
**
|
|
-** ^If the [SQLITE_OPEN_NOMUTEX] flag is set, then the database connection
|
|
-** opens in the multi-thread [threading mode] as long as the single-thread
|
|
-** mode has not been set at compile-time or start-time. ^If the
|
|
-** [SQLITE_OPEN_FULLMUTEX] flag is set then the database connection opens
|
|
-** in the serialized [threading mode] unless single-thread was
|
|
-** previously selected at compile-time or start-time.
|
|
-** ^The [SQLITE_OPEN_SHAREDCACHE] flag causes the database connection to be
|
|
-** eligible to use [shared cache mode], regardless of whether or not shared
|
|
-** cache is enabled using [sqlite3_enable_shared_cache()]. ^The
|
|
-** [SQLITE_OPEN_PRIVATECACHE] flag causes the database connection to not
|
|
-** participate in [shared cache mode] even if it is enabled.
|
|
-**
|
|
** ^The fourth parameter to sqlite3_open_v2() is the name of the
|
|
** [sqlite3_vfs] object that defines the operating system interface that
|
|
** the new database connection should use. ^If the fourth parameter is
|
|
@@ -3447,17 +3537,27 @@
|
|
/*
|
|
** CAPI3REF: Obtain Values For URI Parameters
|
|
**
|
|
-** These are utility routines, useful to VFS implementations, that check
|
|
-** to see if a database file was a URI that contained a specific query
|
|
+** These are utility routines, useful to [VFS|custom VFS implementations],
|
|
+** that check if a database file was a URI that contained a specific query
|
|
** parameter, and if so obtains the value of that query parameter.
|
|
**
|
|
-** If F is the database filename pointer passed into the xOpen() method of
|
|
-** a VFS implementation when the flags parameter to xOpen() has one or
|
|
-** more of the [SQLITE_OPEN_URI] or [SQLITE_OPEN_MAIN_DB] bits set and
|
|
-** P is the name of the query parameter, then
|
|
+** The first parameter to these interfaces (hereafter referred to
|
|
+** as F) must be one of:
|
|
+** <ul>
|
|
+** <li> A database filename pointer created by the SQLite core and
|
|
+** passed into the xOpen() method of a VFS implemention, or
|
|
+** <li> A filename obtained from [sqlite3_db_filename()], or
|
|
+** <li> A new filename constructed using [sqlite3_create_filename()].
|
|
+** </ul>
|
|
+** If the F parameter is not one of the above, then the behavior is
|
|
+** undefined and probably undesirable. Older versions of SQLite were
|
|
+** more tolerant of invalid F parameters than newer versions.
|
|
+**
|
|
+** If F is a suitable filename (as described in the previous paragraph)
|
|
+** and if P is the name of the query parameter, then
|
|
** sqlite3_uri_parameter(F,P) returns the value of the P
|
|
** parameter if it exists or a NULL pointer if P does not appear as a
|
|
-** query parameter on F. If P is a query parameter of F
|
|
+** query parameter on F. If P is a query parameter of F and it
|
|
** has no explicit value, then sqlite3_uri_parameter(F,P) returns
|
|
** a pointer to an empty string.
|
|
**
|
|
@@ -3469,26 +3569,145 @@
|
|
** sqlite3_uri_boolean(F,P,B) routines returns false (0) if the value of
|
|
** query parameter P is one of "no", "false", or "off" in any case or
|
|
** if the value begins with a numeric zero. If P is not a query
|
|
-** parameter on F or if the value of P is does not match any of the
|
|
+** parameter on F or if the value of P does not match any of the
|
|
** above, then sqlite3_uri_boolean(F,P,B) returns (B!=0).
|
|
**
|
|
** The sqlite3_uri_int64(F,P,D) routine converts the value of P into a
|
|
** 64-bit signed integer and returns that integer, or D if P does not
|
|
** exist. If the value of P is something other than an integer, then
|
|
** zero is returned.
|
|
+**
|
|
+** The sqlite3_uri_key(F,N) returns a pointer to the name (not
|
|
+** the value) of the N-th query parameter for filename F, or a NULL
|
|
+** pointer if N is less than zero or greater than the number of query
|
|
+** parameters minus 1. The N value is zero-based so N should be 0 to obtain
|
|
+** the name of the first query parameter, 1 for the second parameter, and
|
|
+** so forth.
|
|
**
|
|
** If F is a NULL pointer, then sqlite3_uri_parameter(F,P) returns NULL and
|
|
** sqlite3_uri_boolean(F,P,B) returns B. If F is not a NULL pointer and
|
|
-** is not a database file pathname pointer that SQLite passed into the xOpen
|
|
-** VFS method, then the behavior of this routine is undefined and probably
|
|
-** undesirable.
|
|
+** is not a database file pathname pointer that the SQLite core passed
|
|
+** into the xOpen VFS method, then the behavior of this routine is undefined
|
|
+** and probably undesirable.
|
|
+**
|
|
+** Beginning with SQLite [version 3.31.0] ([dateof:3.31.0]) the input F
|
|
+** parameter can also be the name of a rollback journal file or WAL file
|
|
+** in addition to the main database file. Prior to version 3.31.0, these
|
|
+** routines would only work if F was the name of the main database file.
|
|
+** When the F parameter is the name of the rollback journal or WAL file,
|
|
+** it has access to all the same query parameters as were found on the
|
|
+** main database file.
|
|
**
|
|
** See the [URI filename] documentation for additional information.
|
|
*/
|
|
SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
|
|
SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
|
|
SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
|
|
+SQLITE_API const char *sqlite3_uri_key(const char *zFilename, int N);
|
|
+
|
|
+/*
|
|
+** CAPI3REF: Translate filenames
|
|
+**
|
|
+** These routines are available to [VFS|custom VFS implementations] for
|
|
+** translating filenames between the main database file, the journal file,
|
|
+** and the WAL file.
|
|
+**
|
|
+** If F is the name of an sqlite database file, journal file, or WAL file
|
|
+** passed by the SQLite core into the VFS, then sqlite3_filename_database(F)
|
|
+** returns the name of the corresponding database file.
|
|
+**
|
|
+** If F is the name of an sqlite database file, journal file, or WAL file
|
|
+** passed by the SQLite core into the VFS, or if F is a database filename
|
|
+** obtained from [sqlite3_db_filename()], then sqlite3_filename_journal(F)
|
|
+** returns the name of the corresponding rollback journal file.
|
|
+**
|
|
+** If F is the name of an sqlite database file, journal file, or WAL file
|
|
+** that was passed by the SQLite core into the VFS, or if F is a database
|
|
+** filename obtained from [sqlite3_db_filename()], then
|
|
+** sqlite3_filename_wal(F) returns the name of the corresponding
|
|
+** WAL file.
|
|
+**
|
|
+** In all of the above, if F is not the name of a database, journal or WAL
|
|
+** filename passed into the VFS from the SQLite core and F is not the
|
|
+** return value from [sqlite3_db_filename()], then the result is
|
|
+** undefined and is likely a memory access violation.
|
|
+*/
|
|
+SQLITE_API const char *sqlite3_filename_database(const char*);
|
|
+SQLITE_API const char *sqlite3_filename_journal(const char*);
|
|
+SQLITE_API const char *sqlite3_filename_wal(const char*);
|
|
+
|
|
+/*
|
|
+** CAPI3REF: Database File Corresponding To A Journal
|
|
+**
|
|
+** ^If X is the name of a rollback or WAL-mode journal file that is
|
|
+** passed into the xOpen method of [sqlite3_vfs], then
|
|
+** sqlite3_database_file_object(X) returns a pointer to the [sqlite3_file]
|
|
+** object that represents the main database file.
|
|
+**
|
|
+** This routine is intended for use in custom [VFS] implementations
|
|
+** only. It is not a general-purpose interface.
|
|
+** The argument sqlite3_file_object(X) must be a filename pointer that
|
|
+** has been passed into [sqlite3_vfs].xOpen method where the
|
|
+** flags parameter to xOpen contains one of the bits
|
|
+** [SQLITE_OPEN_MAIN_JOURNAL] or [SQLITE_OPEN_WAL]. Any other use
|
|
+** of this routine results in undefined and probably undesirable
|
|
+** behavior.
|
|
+*/
|
|
+SQLITE_API sqlite3_file *sqlite3_database_file_object(const char*);
|
|
|
|
+/*
|
|
+** CAPI3REF: Create and Destroy VFS Filenames
|
|
+**
|
|
+** These interfces are provided for use by [VFS shim] implementations and
|
|
+** are not useful outside of that context.
|
|
+**
|
|
+** The sqlite3_create_filename(D,J,W,N,P) allocates memory to hold a version of
|
|
+** database filename D with corresponding journal file J and WAL file W and
|
|
+** with N URI parameters key/values pairs in the array P. The result from
|
|
+** sqlite3_create_filename(D,J,W,N,P) is a pointer to a database filename that
|
|
+** is safe to pass to routines like:
|
|
+** <ul>
|
|
+** <li> [sqlite3_uri_parameter()],
|
|
+** <li> [sqlite3_uri_boolean()],
|
|
+** <li> [sqlite3_uri_int64()],
|
|
+** <li> [sqlite3_uri_key()],
|
|
+** <li> [sqlite3_filename_database()],
|
|
+** <li> [sqlite3_filename_journal()], or
|
|
+** <li> [sqlite3_filename_wal()].
|
|
+** </ul>
|
|
+** If a memory allocation error occurs, sqlite3_create_filename() might
|
|
+** return a NULL pointer. The memory obtained from sqlite3_create_filename(X)
|
|
+** must be released by a corresponding call to sqlite3_free_filename(Y).
|
|
+**
|
|
+** The P parameter in sqlite3_create_filename(D,J,W,N,P) should be an array
|
|
+** of 2*N pointers to strings. Each pair of pointers in this array corresponds
|
|
+** to a key and value for a query parameter. The P parameter may be a NULL
|
|
+** pointer if N is zero. None of the 2*N pointers in the P array may be
|
|
+** NULL pointers and key pointers should not be empty strings.
|
|
+** None of the D, J, or W parameters to sqlite3_create_filename(D,J,W,N,P) may
|
|
+** be NULL pointers, though they can be empty strings.
|
|
+**
|
|
+** The sqlite3_free_filename(Y) routine releases a memory allocation
|
|
+** previously obtained from sqlite3_create_filename(). Invoking
|
|
+** sqlite3_free_filename(Y) where Y is a NULL pointer is a harmless no-op.
|
|
+**
|
|
+** If the Y parameter to sqlite3_free_filename(Y) is anything other
|
|
+** than a NULL pointer or a pointer previously acquired from
|
|
+** sqlite3_create_filename(), then bad things such as heap
|
|
+** corruption or segfaults may occur. The value Y should be
|
|
+** used again after sqlite3_free_filename(Y) has been called. This means
|
|
+** that if the [sqlite3_vfs.xOpen()] method of a VFS has been called using Y,
|
|
+** then the corresponding [sqlite3_module.xClose() method should also be
|
|
+** invoked prior to calling sqlite3_free_filename(Y).
|
|
+*/
|
|
+SQLITE_API char *sqlite3_create_filename(
|
|
+ const char *zDatabase,
|
|
+ const char *zJournal,
|
|
+ const char *zWal,
|
|
+ int nParam,
|
|
+ const char **azParam
|
|
+);
|
|
+SQLITE_API void sqlite3_free_filename(char*);
|
|
|
|
/*
|
|
** CAPI3REF: Error Codes And Messages
|
|
@@ -3806,15 +4025,15 @@
|
|
** </li>
|
|
**
|
|
** <li>
|
|
-** ^If the specific value bound to [parameter | host parameter] in the
|
|
+** ^If the specific value bound to a [parameter | host parameter] in the
|
|
** WHERE clause might influence the choice of query plan for a statement,
|
|
** then the statement will be automatically recompiled, as if there had been
|
|
-** a schema change, on the first [sqlite3_step()] call following any change
|
|
+** a schema change, on the first [sqlite3_step()] call following any change
|
|
** to the [sqlite3_bind_text | bindings] of that [parameter].
|
|
-** ^The specific value of WHERE-clause [parameter] might influence the
|
|
+** ^The specific value of a WHERE-clause [parameter] might influence the
|
|
** choice of query plan if the parameter is the left-hand side of a [LIKE]
|
|
** or [GLOB] operator or if the parameter is compared to an indexed column
|
|
-** and the [SQLITE_ENABLE_STAT3] compile-time option is enabled.
|
|
+** and the [SQLITE_ENABLE_STAT4] compile-time option is enabled.
|
|
** </li>
|
|
** </ol>
|
|
**
|
|
@@ -4071,12 +4290,30 @@
|
|
** [sqlite3_bind_parameter_index()] API if desired. ^The index
|
|
** for "?NNN" parameters is the value of NNN.
|
|
** ^The NNN value must be between 1 and the [sqlite3_limit()]
|
|
-** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 999).
|
|
+** parameter [SQLITE_LIMIT_VARIABLE_NUMBER] (default value: 32766).
|
|
**
|
|
** ^The third argument is the value to bind to the parameter.
|
|
** ^If the third parameter to sqlite3_bind_text() or sqlite3_bind_text16()
|
|
** or sqlite3_bind_blob() is a NULL pointer then the fourth parameter
|
|
** is ignored and the end result is the same as sqlite3_bind_null().
|
|
+** ^If the third parameter to sqlite3_bind_text() is not NULL, then
|
|
+** it should be a pointer to well-formed UTF8 text.
|
|
+** ^If the third parameter to sqlite3_bind_text16() is not NULL, then
|
|
+** it should be a pointer to well-formed UTF16 text.
|
|
+** ^If the third parameter to sqlite3_bind_text64() is not NULL, then
|
|
+** it should be a pointer to a well-formed unicode string that is
|
|
+** either UTF8 if the sixth parameter is SQLITE_UTF8, or UTF16
|
|
+** otherwise.
|
|
+**
|
|
+** [[byte-order determination rules]] ^The byte-order of
|
|
+** UTF16 input text is determined by the byte-order mark (BOM, U+FEFF)
|
|
+** found in first character, which is removed, or in the absence of a BOM
|
|
+** the byte order is the native byte order of the host
|
|
+** machine for sqlite3_bind_text16() or the byte order specified in
|
|
+** the 6th parameter for sqlite3_bind_text64().)^
|
|
+** ^If UTF16 input text contains invalid unicode
|
|
+** characters, then SQLite might change those invalid characters
|
|
+** into the unicode replacement character: U+FFFD.
|
|
**
|
|
** ^(In those routines that have a fourth argument, its value is the
|
|
** number of bytes in the parameter. To be clear: the value is the
|
|
@@ -4090,7 +4327,7 @@
|
|
** or sqlite3_bind_text16() or sqlite3_bind_text64() then
|
|
** that parameter must be the byte offset
|
|
** where the NUL terminator would occur assuming the string were NUL
|
|
-** terminated. If any NUL characters occur at byte offsets less than
|
|
+** terminated. If any NUL characters occurs at byte offsets less than
|
|
** the value of the fourth parameter then the resulting string value will
|
|
** contain embedded NULs. The result of expressions involving strings
|
|
** with embedded NULs is undefined.
|
|
@@ -4320,7 +4557,7 @@
|
|
**
|
|
** ^If the Nth column returned by the statement is an expression or
|
|
** subquery and is not a column value, then all of these functions return
|
|
-** NULL. ^These routine might also return NULL if a memory allocation error
|
|
+** NULL. ^These routines might also return NULL if a memory allocation error
|
|
** occurs. ^Otherwise, they return the name of the attached database, table,
|
|
** or column that query result column was extracted from.
|
|
**
|
|
@@ -4330,10 +4567,6 @@
|
|
** ^These APIs are only available if the library was compiled with the
|
|
** [SQLITE_ENABLE_COLUMN_METADATA] C-preprocessor symbol.
|
|
**
|
|
-** If two or more threads call one or more of these routines against the same
|
|
-** prepared statement and column at the same time then the results are
|
|
-** undefined.
|
|
-**
|
|
** If two or more threads call one or more
|
|
** [sqlite3_column_database_name | column metadata interfaces]
|
|
** for the same [prepared statement] and result column
|
|
@@ -4470,7 +4703,7 @@
|
|
** ^The sqlite3_data_count(P) interface returns the number of columns in the
|
|
** current row of the result set of [prepared statement] P.
|
|
** ^If prepared statement P does not have results ready to return
|
|
-** (via calls to the [sqlite3_column_int | sqlite3_column_*()] of
|
|
+** (via calls to the [sqlite3_column_int | sqlite3_column()] family of
|
|
** interfaces) then sqlite3_data_count(P) returns 0.
|
|
** ^The sqlite3_data_count(P) routine also returns 0 if P is a NULL pointer.
|
|
** ^The sqlite3_data_count(P) routine returns 0 if the previous call to
|
|
@@ -4794,8 +5027,6 @@
|
|
/*
|
|
** CAPI3REF: Create Or Redefine SQL Functions
|
|
** KEYWORDS: {function creation routines}
|
|
-** KEYWORDS: {application-defined SQL function}
|
|
-** KEYWORDS: {application-defined SQL functions}
|
|
** METHOD: sqlite3
|
|
**
|
|
** ^These functions (collectively known as "function creation routines")
|
|
@@ -4849,6 +5080,23 @@
|
|
** perform additional optimizations on deterministic functions, so use
|
|
** of the [SQLITE_DETERMINISTIC] flag is recommended where possible.
|
|
**
|
|
+** ^The fourth parameter may also optionally include the [SQLITE_DIRECTONLY]
|
|
+** flag, which if present prevents the function from being invoked from
|
|
+** within VIEWs, TRIGGERs, CHECK constraints, generated column expressions,
|
|
+** index expressions, or the WHERE clause of partial indexes.
|
|
+**
|
|
+** <span style="background-color:#ffff90;">
|
|
+** For best security, the [SQLITE_DIRECTONLY] flag is recommended for
|
|
+** all application-defined SQL functions that do not need to be
|
|
+** used inside of triggers, view, CHECK constraints, or other elements of
|
|
+** the database schema. This flags is especially recommended for SQL
|
|
+** functions that have side effects or reveal internal application state.
|
|
+** Without this flag, an attacker might be able to modify the schema of
|
|
+** a database file to include invocations of the function with parameters
|
|
+** chosen by the attacker, which the application will then execute when
|
|
+** the database file is opened and read.
|
|
+** </span>
|
|
+**
|
|
** ^(The fifth parameter is an arbitrary pointer. The implementation of the
|
|
** function can gain access to this pointer using [sqlite3_user_data()].)^
|
|
**
|
|
@@ -4965,8 +5213,68 @@
|
|
** [SQLITE_UTF8 | preferred text encoding] as the fourth argument
|
|
** to [sqlite3_create_function()], [sqlite3_create_function16()], or
|
|
** [sqlite3_create_function_v2()].
|
|
+**
|
|
+** <dl>
|
|
+** [[SQLITE_DETERMINISTIC]] <dt>SQLITE_DETERMINISTIC</dt><dd>
|
|
+** The SQLITE_DETERMINISTIC flag means that the new function always gives
|
|
+** the same output when the input parameters are the same.
|
|
+** The [abs|abs() function] is deterministic, for example, but
|
|
+** [randomblob|randomblob()] is not. Functions must
|
|
+** be deterministic in order to be used in certain contexts such as
|
|
+** with the WHERE clause of [partial indexes] or in [generated columns].
|
|
+** SQLite might also optimize deterministic functions by factoring them
|
|
+** out of inner loops.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_DIRECTONLY]] <dt>SQLITE_DIRECTONLY</dt><dd>
|
|
+** The SQLITE_DIRECTONLY flag means that the function may only be invoked
|
|
+** from top-level SQL, and cannot be used in VIEWs or TRIGGERs nor in
|
|
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
|
+** [expression indexes], [partial indexes], or [generated columns].
|
|
+** The SQLITE_DIRECTONLY flags is a security feature which is recommended
|
|
+** for all [application-defined SQL functions], and especially for functions
|
|
+** that have side-effects or that could potentially leak sensitive
|
|
+** information.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_INNOCUOUS]] <dt>SQLITE_INNOCUOUS</dt><dd>
|
|
+** The SQLITE_INNOCUOUS flag means that the function is unlikely
|
|
+** to cause problems even if misused. An innocuous function should have
|
|
+** no side effects and should not depend on any values other than its
|
|
+** input parameters. The [abs|abs() function] is an example of an
|
|
+** innocuous function.
|
|
+** The [load_extension() SQL function] is not innocuous because of its
|
|
+** side effects.
|
|
+** <p> SQLITE_INNOCUOUS is similar to SQLITE_DETERMINISTIC, but is not
|
|
+** exactly the same. The [random|random() function] is an example of a
|
|
+** function that is innocuous but not deterministic.
|
|
+** <p>Some heightened security settings
|
|
+** ([SQLITE_DBCONFIG_TRUSTED_SCHEMA] and [PRAGMA trusted_schema=OFF])
|
|
+** disable the use of SQL functions inside views and triggers and in
|
|
+** schema structures such as [CHECK constraints], [DEFAULT clauses],
|
|
+** [expression indexes], [partial indexes], and [generated columns] unless
|
|
+** the function is tagged with SQLITE_INNOCUOUS. Most built-in functions
|
|
+** are innocuous. Developers are advised to avoid using the
|
|
+** SQLITE_INNOCUOUS flag for application-defined functions unless the
|
|
+** function has been carefully audited and found to be free of potentially
|
|
+** security-adverse side-effects and information-leaks.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_SUBTYPE]] <dt>SQLITE_SUBTYPE</dt><dd>
|
|
+** The SQLITE_SUBTYPE flag indicates to SQLite that a function may call
|
|
+** [sqlite3_value_subtype()] to inspect the sub-types of its arguments.
|
|
+** Specifying this flag makes no difference for scalar or aggregate user
|
|
+** functions. However, if it is not specified for a user-defined window
|
|
+** function, then any sub-types belonging to arguments passed to the window
|
|
+** function may be discarded before the window function is called (i.e.
|
|
+** sqlite3_value_subtype() will always return 0).
|
|
+** </dd>
|
|
+** </dl>
|
|
*/
|
|
-#define SQLITE_DETERMINISTIC 0x800
|
|
+#define SQLITE_DETERMINISTIC 0x000000800
|
|
+#define SQLITE_DIRECTONLY 0x000080000
|
|
+#define SQLITE_SUBTYPE 0x000100000
|
|
+#define SQLITE_INNOCUOUS 0x000200000
|
|
|
|
/*
|
|
** CAPI3REF: Deprecated Functions
|
|
@@ -5025,8 +5333,8 @@
|
|
**
|
|
** These routines extract type, size, and content information from
|
|
** [protected sqlite3_value] objects. Protected sqlite3_value objects
|
|
-** are used to pass parameter information into implementation of
|
|
-** [application-defined SQL functions] and [virtual tables].
|
|
+** are used to pass parameter information into the functions that
|
|
+** implement [application-defined SQL functions] and [virtual tables].
|
|
**
|
|
** These routines work only with [protected sqlite3_value] objects.
|
|
** Any attempt to use these routines on an [unprotected sqlite3_value]
|
|
@@ -5083,7 +5391,7 @@
|
|
** ^The sqlite3_value_frombind(X) interface returns non-zero if the
|
|
** value X originated from one of the [sqlite3_bind_int|sqlite3_bind()]
|
|
** interfaces. ^If X comes from an SQL literal value, or a table column,
|
|
-** and expression, then sqlite3_value_frombind(X) returns zero.
|
|
+** or an expression, then sqlite3_value_frombind(X) returns zero.
|
|
**
|
|
** Please pay particular attention to the fact that the pointer returned
|
|
** from [sqlite3_value_blob()], [sqlite3_value_text()], or
|
|
@@ -5169,8 +5477,8 @@
|
|
** routine to allocate memory for storing their state.
|
|
**
|
|
** ^The first time the sqlite3_aggregate_context(C,N) routine is called
|
|
-** for a particular aggregate function, SQLite
|
|
-** allocates N of memory, zeroes out that memory, and returns a pointer
|
|
+** for a particular aggregate function, SQLite allocates
|
|
+** N bytes of memory, zeroes out that memory, and returns a pointer
|
|
** to the new memory. ^On second and subsequent calls to
|
|
** sqlite3_aggregate_context() for the same aggregate function instance,
|
|
** the same buffer is returned. Sqlite3_aggregate_context() is normally
|
|
@@ -5187,7 +5495,7 @@
|
|
**
|
|
** ^(The amount of space allocated by sqlite3_aggregate_context(C,N) is
|
|
** determined by the N parameter on first successful call. Changing the
|
|
-** value of N in subsequent call to sqlite3_aggregate_context() within
|
|
+** value of N in any subsequent call to sqlite3_aggregate_context() within
|
|
** the same aggregate function instance will not resize the memory
|
|
** allocation.)^ Within the xFinal callback, it is customary to set
|
|
** N=0 in calls to sqlite3_aggregate_context(C,N) so that no
|
|
@@ -5344,8 +5652,9 @@
|
|
** 2nd parameter of sqlite3_result_error() or sqlite3_result_error16()
|
|
** as the text of an error message. ^SQLite interprets the error
|
|
** message string from sqlite3_result_error() as UTF-8. ^SQLite
|
|
-** interprets the string from sqlite3_result_error16() as UTF-16 in native
|
|
-** byte order. ^If the third parameter to sqlite3_result_error()
|
|
+** interprets the string from sqlite3_result_error16() as UTF-16 using
|
|
+** the same [byte-order determination rules] as [sqlite3_bind_text16()].
|
|
+** ^If the third parameter to sqlite3_result_error()
|
|
** or sqlite3_result_error16() is negative then SQLite takes as the error
|
|
** message all text up through the first zero character.
|
|
** ^If the third parameter to sqlite3_result_error() or
|
|
@@ -5413,6 +5722,25 @@
|
|
** then SQLite makes a copy of the result into space obtained
|
|
** from [sqlite3_malloc()] before it returns.
|
|
**
|
|
+** ^For the sqlite3_result_text16(), sqlite3_result_text16le(), and
|
|
+** sqlite3_result_text16be() routines, and for sqlite3_result_text64()
|
|
+** when the encoding is not UTF8, if the input UTF16 begins with a
|
|
+** byte-order mark (BOM, U+FEFF) then the BOM is removed from the
|
|
+** string and the rest of the string is interpreted according to the
|
|
+** byte-order specified by the BOM. ^The byte-order specified by
|
|
+** the BOM at the beginning of the text overrides the byte-order
|
|
+** specified by the interface procedure. ^So, for example, if
|
|
+** sqlite3_result_text16le() is invoked with text that begins
|
|
+** with bytes 0xfe, 0xff (a big-endian byte-order mark) then the
|
|
+** first two bytes of input are skipped and the remaining input
|
|
+** is interpreted as UTF16BE text.
|
|
+**
|
|
+** ^For UTF16 input text to the sqlite3_result_text16(),
|
|
+** sqlite3_result_text16be(), sqlite3_result_text16le(), and
|
|
+** sqlite3_result_text64() routines, if the text contains invalid
|
|
+** UTF16 characters, the invalid characters might be converted
|
|
+** into the unicode replacement character, U+FFFD.
|
|
+**
|
|
** ^The sqlite3_result_value() interface sets the result of
|
|
** the application-defined function to be a copy of the
|
|
** [unprotected sqlite3_value] object specified by the 2nd parameter. ^The
|
|
@@ -5498,7 +5826,7 @@
|
|
** <li> [SQLITE_UTF16_ALIGNED].
|
|
** </ul>)^
|
|
** ^The eTextRep argument determines the encoding of strings passed
|
|
-** to the collating function callback, xCallback.
|
|
+** to the collating function callback, xCompare.
|
|
** ^The [SQLITE_UTF16] and [SQLITE_UTF16_ALIGNED] values for eTextRep
|
|
** force strings to be UTF16 with native byte order.
|
|
** ^The [SQLITE_UTF16_ALIGNED] value for eTextRep forces strings to begin
|
|
@@ -5507,18 +5835,19 @@
|
|
** ^The fourth argument, pArg, is an application data pointer that is passed
|
|
** through as the first argument to the collating function callback.
|
|
**
|
|
-** ^The fifth argument, xCallback, is a pointer to the collating function.
|
|
+** ^The fifth argument, xCompare, is a pointer to the collating function.
|
|
** ^Multiple collating functions can be registered using the same name but
|
|
** with different eTextRep parameters and SQLite will use whichever
|
|
** function requires the least amount of data transformation.
|
|
-** ^If the xCallback argument is NULL then the collating function is
|
|
+** ^If the xCompare argument is NULL then the collating function is
|
|
** deleted. ^When all collating functions having the same name are deleted,
|
|
** that collation is no longer usable.
|
|
**
|
|
** ^The collating function callback is invoked with a copy of the pArg
|
|
** application data pointer and with two strings in the encoding specified
|
|
-** by the eTextRep argument. The collating function must return an
|
|
-** integer that is negative, zero, or positive
|
|
+** by the eTextRep argument. The two integer parameters to the collating
|
|
+** function callback are the length of the two strings, in bytes. The collating
|
|
+** function must return an integer that is negative, zero, or positive
|
|
** if the first string is less than, equal to, or greater than the second,
|
|
** respectively. A collating function must always return the same answer
|
|
** given the same inputs. If two or more collating functions are registered
|
|
@@ -5535,7 +5864,7 @@
|
|
** </ol>
|
|
**
|
|
** If a collating function fails any of the above constraints and that
|
|
-** collating function is registered and used, then the behavior of SQLite
|
|
+** collating function is registered and used, then the behavior of SQLite
|
|
** is undefined.
|
|
**
|
|
** ^The sqlite3_create_collation_v2() works like sqlite3_create_collation()
|
|
@@ -5617,51 +5946,6 @@
|
|
void(*)(void*,sqlite3*,int eTextRep,const void*)
|
|
);
|
|
|
|
-#ifdef SQLITE_HAS_CODEC
|
|
-/*
|
|
-** Specify the key for an encrypted database. This routine should be
|
|
-** called right after sqlite3_open().
|
|
-**
|
|
-** The code to implement this API is not available in the public release
|
|
-** of SQLite.
|
|
-*/
|
|
-SQLITE_API int sqlite3_key(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const void *pKey, int nKey /* The key */
|
|
-);
|
|
-SQLITE_API int sqlite3_key_v2(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const char *zDbName, /* Name of the database */
|
|
- const void *pKey, int nKey /* The key */
|
|
-);
|
|
-
|
|
-/*
|
|
-** Change the key on an open database. If the current database is not
|
|
-** encrypted, this routine will encrypt it. If pNew==0 or nNew==0, the
|
|
-** database is decrypted.
|
|
-**
|
|
-** The code to implement this API is not available in the public release
|
|
-** of SQLite.
|
|
-*/
|
|
-SQLITE_API int sqlite3_rekey(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const void *pKey, int nKey /* The new key */
|
|
-);
|
|
-SQLITE_API int sqlite3_rekey_v2(
|
|
- sqlite3 *db, /* Database to be rekeyed */
|
|
- const char *zDbName, /* Name of the database */
|
|
- const void *pKey, int nKey /* The new key */
|
|
-);
|
|
-
|
|
-/*
|
|
-** Specify the activation key for a SEE database. Unless
|
|
-** activated, none of the SEE routines will work.
|
|
-*/
|
|
-SQLITE_API void sqlite3_activate_see(
|
|
- const char *zPassPhrase /* Activation phrase */
|
|
-);
|
|
-#endif
|
|
-
|
|
#ifdef SQLITE_ENABLE_CEROD
|
|
/*
|
|
** Specify the activation key for a CEROD database. Unless
|
|
@@ -5862,16 +6146,31 @@
|
|
** CAPI3REF: Return The Filename For A Database Connection
|
|
** METHOD: sqlite3
|
|
**
|
|
-** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
|
|
-** associated with database N of connection D. ^The main database file
|
|
-** has the name "main". If there is no attached database N on the database
|
|
+** ^The sqlite3_db_filename(D,N) interface returns a pointer to the filename
|
|
+** associated with database N of connection D.
|
|
+** ^If there is no attached database N on the database
|
|
** connection D, or if database N is a temporary or in-memory database, then
|
|
** this function will return either a NULL pointer or an empty string.
|
|
**
|
|
+** ^The string value returned by this routine is owned and managed by
|
|
+** the database connection. ^The value will be valid until the database N
|
|
+** is [DETACH]-ed or until the database connection closes.
|
|
+**
|
|
** ^The filename returned by this function is the output of the
|
|
** xFullPathname method of the [VFS]. ^In other words, the filename
|
|
** will be an absolute pathname, even if the filename used
|
|
** to open the database originally was a URI or relative pathname.
|
|
+**
|
|
+** If the filename pointer returned by this routine is not NULL, then it
|
|
+** can be used as the filename input parameter to these routines:
|
|
+** <ul>
|
|
+** <li> [sqlite3_uri_parameter()]
|
|
+** <li> [sqlite3_uri_boolean()]
|
|
+** <li> [sqlite3_uri_int64()]
|
|
+** <li> [sqlite3_filename_database()]
|
|
+** <li> [sqlite3_filename_journal()]
|
|
+** <li> [sqlite3_filename_wal()]
|
|
+** </ul>
|
|
*/
|
|
SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
|
|
|
|
@@ -6021,15 +6320,19 @@
|
|
**
|
|
** ^(The cache sharing mode set by this interface effects all subsequent
|
|
** calls to [sqlite3_open()], [sqlite3_open_v2()], and [sqlite3_open16()].
|
|
-** Existing database connections continue use the sharing mode
|
|
+** Existing database connections continue to use the sharing mode
|
|
** that was in effect at the time they were opened.)^
|
|
**
|
|
** ^(This routine returns [SQLITE_OK] if shared cache was enabled or disabled
|
|
** successfully. An [error code] is returned otherwise.)^
|
|
**
|
|
-** ^Shared cache is disabled by default. But this might change in
|
|
-** future releases of SQLite. Applications that care about shared
|
|
-** cache setting should set it explicitly.
|
|
+** ^Shared cache is disabled by default. It is recommended that it stay
|
|
+** that way. In other words, do not use this routine. This interface
|
|
+** continues to be provided for historical compatibility, but its use is
|
|
+** discouraged. Any use of shared cache is discouraged. If shared cache
|
|
+** must be used, it is recommended that shared cache only be enabled for
|
|
+** individual database connections using the [sqlite3_open_v2()] interface
|
|
+** with the [SQLITE_OPEN_SHAREDCACHE] flag.
|
|
**
|
|
** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
|
|
** and will always return SQLITE_MISUSE. On those systems,
|
|
@@ -6076,6 +6379,9 @@
|
|
/*
|
|
** CAPI3REF: Impose A Limit On Heap Size
|
|
**
|
|
+** These interfaces impose limits on the amount of heap memory that will be
|
|
+** by all database connections within a single process.
|
|
+**
|
|
** ^The sqlite3_soft_heap_limit64() interface sets and/or queries the
|
|
** soft limit on the amount of heap memory that may be allocated by SQLite.
|
|
** ^SQLite strives to keep heap memory utilization below the soft heap
|
|
@@ -6086,20 +6392,41 @@
|
|
** an [SQLITE_NOMEM] error. In other words, the soft heap limit
|
|
** is advisory only.
|
|
**
|
|
-** ^The return value from sqlite3_soft_heap_limit64() is the size of
|
|
-** the soft heap limit prior to the call, or negative in the case of an
|
|
-** error. ^If the argument N is negative
|
|
-** then no change is made to the soft heap limit. Hence, the current
|
|
-** size of the soft heap limit can be determined by invoking
|
|
-** sqlite3_soft_heap_limit64() with a negative argument.
|
|
-**
|
|
-** ^If the argument N is zero then the soft heap limit is disabled.
|
|
+** ^The sqlite3_hard_heap_limit64(N) interface sets a hard upper bound of
|
|
+** N bytes on the amount of memory that will be allocated. ^The
|
|
+** sqlite3_hard_heap_limit64(N) interface is similar to
|
|
+** sqlite3_soft_heap_limit64(N) except that memory allocations will fail
|
|
+** when the hard heap limit is reached.
|
|
**
|
|
-** ^(The soft heap limit is not enforced in the current implementation
|
|
+** ^The return value from both sqlite3_soft_heap_limit64() and
|
|
+** sqlite3_hard_heap_limit64() is the size of
|
|
+** the heap limit prior to the call, or negative in the case of an
|
|
+** error. ^If the argument N is negative
|
|
+** then no change is made to the heap limit. Hence, the current
|
|
+** size of heap limits can be determined by invoking
|
|
+** sqlite3_soft_heap_limit64(-1) or sqlite3_hard_heap_limit(-1).
|
|
+**
|
|
+** ^Setting the heap limits to zero disables the heap limiter mechanism.
|
|
+**
|
|
+** ^The soft heap limit may not be greater than the hard heap limit.
|
|
+** ^If the hard heap limit is enabled and if sqlite3_soft_heap_limit(N)
|
|
+** is invoked with a value of N that is greater than the hard heap limit,
|
|
+** the the soft heap limit is set to the value of the hard heap limit.
|
|
+** ^The soft heap limit is automatically enabled whenever the hard heap
|
|
+** limit is enabled. ^When sqlite3_hard_heap_limit64(N) is invoked and
|
|
+** the soft heap limit is outside the range of 1..N, then the soft heap
|
|
+** limit is set to N. ^Invoking sqlite3_soft_heap_limit64(0) when the
|
|
+** hard heap limit is enabled makes the soft heap limit equal to the
|
|
+** hard heap limit.
|
|
+**
|
|
+** The memory allocation limits can also be adjusted using
|
|
+** [PRAGMA soft_heap_limit] and [PRAGMA hard_heap_limit].
|
|
+**
|
|
+** ^(The heap limits are not enforced in the current implementation
|
|
** if one or more of following conditions are true:
|
|
**
|
|
** <ul>
|
|
-** <li> The soft heap limit is set to zero.
|
|
+** <li> The limit value is set to zero.
|
|
** <li> Memory accounting is disabled using a combination of the
|
|
** [sqlite3_config]([SQLITE_CONFIG_MEMSTATUS],...) start-time option and
|
|
** the [SQLITE_DEFAULT_MEMSTATUS] compile-time option.
|
|
@@ -6110,21 +6437,11 @@
|
|
** from the heap.
|
|
** </ul>)^
|
|
**
|
|
-** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
|
|
-** the soft heap limit is enforced
|
|
-** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
|
|
-** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
|
|
-** the soft heap limit is enforced on every memory allocation. Without
|
|
-** [SQLITE_ENABLE_MEMORY_MANAGEMENT], the soft heap limit is only enforced
|
|
-** when memory is allocated by the page cache. Testing suggests that because
|
|
-** the page cache is the predominate memory user in SQLite, most
|
|
-** applications will achieve adequate soft heap limit enforcement without
|
|
-** the use of [SQLITE_ENABLE_MEMORY_MANAGEMENT].
|
|
-**
|
|
-** The circumstances under which SQLite will enforce the soft heap limit may
|
|
+** The circumstances under which SQLite will enforce the heap limits may
|
|
** changes in future releases of SQLite.
|
|
*/
|
|
SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
|
|
+SQLITE_API sqlite3_int64 sqlite3_hard_heap_limit64(sqlite3_int64 N);
|
|
|
|
/*
|
|
** CAPI3REF: Deprecated Soft Heap Limit Interface
|
|
@@ -6148,7 +6465,7 @@
|
|
** interface returns SQLITE_OK and fills in the non-NULL pointers in
|
|
** the final five arguments with appropriate values if the specified
|
|
** column exists. ^The sqlite3_table_column_metadata() interface returns
|
|
-** SQLITE_ERROR and if the specified column does not exist.
|
|
+** SQLITE_ERROR if the specified column does not exist.
|
|
** ^If the column-name parameter to sqlite3_table_column_metadata() is a
|
|
** NULL pointer, then this routine simply checks for the existence of the
|
|
** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it
|
|
@@ -6290,7 +6607,7 @@
|
|
** 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
|
|
+** be enabled 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.
|
|
@@ -6377,7 +6694,7 @@
|
|
** KEYWORDS: sqlite3_module {virtual table module}
|
|
**
|
|
** This structure, sometimes called a "virtual table module",
|
|
-** defines the implementation of a [virtual tables].
|
|
+** defines the implementation of a [virtual table].
|
|
** This structure consists mostly of methods for the module.
|
|
**
|
|
** ^A virtual table module is created by filling in a persistent
|
|
@@ -6474,7 +6791,13 @@
|
|
** the right-hand side of the corresponding aConstraint[] is evaluated
|
|
** and becomes the argvIndex-th entry in argv. ^(If aConstraintUsage[].omit
|
|
** is true, then the constraint is assumed to be fully handled by the
|
|
-** virtual table and is not checked again by SQLite.)^
|
|
+** virtual table and might not be checked again by the byte code.)^ ^(The
|
|
+** aConstraintUsage[].omit flag is an optimization hint. When the omit flag
|
|
+** is left in its default setting of false, the constraint will always be
|
|
+** checked separately in byte code. If the omit flag is change to true, then
|
|
+** the constraint may or may not be checked in byte code. In other words,
|
|
+** when the omit flag is true there is no guarantee that the constraint will
|
|
+** not be checked again using byte code.)^
|
|
**
|
|
** ^The idxNum and idxPtr values are recorded and passed into the
|
|
** [xFilter] method.
|
|
@@ -6514,7 +6837,7 @@
|
|
** If a virtual table extension is
|
|
** used with an SQLite version earlier than 3.8.2, the results of attempting
|
|
** to read or write the estimatedRows field are undefined (but are likely
|
|
-** to included crashing the application). The estimatedRows field should
|
|
+** to include crashing the application). The estimatedRows field should
|
|
** therefore only be used if [sqlite3_libversion_number()] returns a
|
|
** value greater than or equal to 3008002. Similarly, the idxFlags field
|
|
** was added for [version 3.9.0] ([dateof:3.9.0]).
|
|
@@ -6566,7 +6889,7 @@
|
|
/*
|
|
** CAPI3REF: Virtual Table Constraint Operator Codes
|
|
**
|
|
-** These macros defined the allowed values for the
|
|
+** These macros define the allowed values for the
|
|
** [sqlite3_index_info].aConstraint[].op field. Each value represents
|
|
** an operator that is part of a constraint term in the wHERE clause of
|
|
** a query that uses a [virtual table].
|
|
@@ -6612,6 +6935,12 @@
|
|
** ^The sqlite3_create_module()
|
|
** interface is equivalent to sqlite3_create_module_v2() with a NULL
|
|
** destructor.
|
|
+**
|
|
+** ^If the third parameter (the pointer to the sqlite3_module object) is
|
|
+** NULL then no new module is create and any existing modules with the
|
|
+** same name are dropped.
|
|
+**
|
|
+** See also: [sqlite3_drop_modules()]
|
|
*/
|
|
SQLITE_API int sqlite3_create_module(
|
|
sqlite3 *db, /* SQLite connection to register module with */
|
|
@@ -6627,6 +6956,23 @@
|
|
void(*xDestroy)(void*) /* Module destructor function */
|
|
);
|
|
|
|
+/*
|
|
+** CAPI3REF: Remove Unnecessary Virtual Table Implementations
|
|
+** METHOD: sqlite3
|
|
+**
|
|
+** ^The sqlite3_drop_modules(D,L) interface removes all virtual
|
|
+** table modules from database connection D except those named on list L.
|
|
+** The L parameter must be either NULL or a pointer to an array of pointers
|
|
+** to strings where the array is terminated by a single NULL pointer.
|
|
+** ^If the L parameter is NULL, then all virtual table modules are removed.
|
|
+**
|
|
+** See also: [sqlite3_create_module()]
|
|
+*/
|
|
+SQLITE_API int sqlite3_drop_modules(
|
|
+ sqlite3 *db, /* Remove modules from this connection */
|
|
+ const char **azKeep /* Except, do not remove the ones named here */
|
|
+);
|
|
+
|
|
/*
|
|
** CAPI3REF: Virtual Table Instance Object
|
|
** KEYWORDS: sqlite3_vtab
|
|
@@ -7153,7 +7499,7 @@
|
|
** The only difference is that the public sqlite3_XXX functions enumerated
|
|
** above silently ignore any invocations that pass a NULL pointer instead
|
|
** of a valid mutex handle. The implementations of the methods defined
|
|
-** by this structure are not required to handle this case, the results
|
|
+** by this structure are not required to handle this case. The results
|
|
** of passing a NULL pointer instead of a valid mutex handle are undefined
|
|
** (i.e. it is acceptable to provide an implementation that segfaults if
|
|
** it is passed a NULL pointer).
|
|
@@ -7335,14 +7681,14 @@
|
|
#define SQLITE_TESTCTRL_FIRST 5
|
|
#define SQLITE_TESTCTRL_PRNG_SAVE 5
|
|
#define SQLITE_TESTCTRL_PRNG_RESTORE 6
|
|
-#define SQLITE_TESTCTRL_PRNG_RESET 7
|
|
+#define SQLITE_TESTCTRL_PRNG_RESET 7 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_BITVEC_TEST 8
|
|
#define SQLITE_TESTCTRL_FAULT_INSTALL 9
|
|
#define SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS 10
|
|
#define SQLITE_TESTCTRL_PENDING_BYTE 11
|
|
#define SQLITE_TESTCTRL_ASSERT 12
|
|
#define SQLITE_TESTCTRL_ALWAYS 13
|
|
-#define SQLITE_TESTCTRL_RESERVE 14
|
|
+#define SQLITE_TESTCTRL_RESERVE 14 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
|
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
|
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
|
@@ -7358,7 +7704,9 @@
|
|
#define SQLITE_TESTCTRL_IMPOSTER 25
|
|
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
|
|
#define SQLITE_TESTCTRL_RESULT_INTREAL 27
|
|
-#define SQLITE_TESTCTRL_LAST 27 /* Largest TESTCTRL */
|
|
+#define SQLITE_TESTCTRL_PRNG_SEED 28
|
|
+#define SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS 29
|
|
+#define SQLITE_TESTCTRL_LAST 29 /* Largest TESTCTRL */
|
|
|
|
/*
|
|
** CAPI3REF: SQL Keyword Checking
|
|
@@ -7624,7 +7972,7 @@
|
|
**
|
|
** [[SQLITE_STATUS_PAGECACHE_SIZE]] ^(<dt>SQLITE_STATUS_PAGECACHE_SIZE</dt>
|
|
** <dd>This parameter records the largest memory allocation request
|
|
-** handed to [pagecache memory allocator]. Only the value returned in the
|
|
+** handed to the [pagecache memory allocator]. Only the value returned in the
|
|
** *pHighwater parameter to [sqlite3_status()] is of interest.
|
|
** The value written into the *pCurrent parameter is undefined.</dd>)^
|
|
**
|
|
@@ -7700,7 +8048,7 @@
|
|
** checked out.</dd>)^
|
|
**
|
|
** [[SQLITE_DBSTATUS_LOOKASIDE_HIT]] ^(<dt>SQLITE_DBSTATUS_LOOKASIDE_HIT</dt>
|
|
-** <dd>This parameter returns the number malloc attempts that were
|
|
+** <dd>This parameter returns the number of malloc attempts that were
|
|
** satisfied using lookaside memory. Only the high-water value is meaningful;
|
|
** the current value is always zero.)^
|
|
**
|
|
@@ -7782,7 +8130,7 @@
|
|
** cache overflowing. Transactions are more efficient if they are written
|
|
** to disk all at once. When pages spill mid-transaction, that introduces
|
|
** additional overhead. This parameter can be used help identify
|
|
-** inefficiencies that can be resolve by increasing the cache size.
|
|
+** inefficiencies that can be resolved by increasing the cache size.
|
|
** </dd>
|
|
**
|
|
** [[SQLITE_DBSTATUS_DEFERRED_FKS]] ^(<dt>SQLITE_DBSTATUS_DEFERRED_FKS</dt>
|
|
@@ -7871,7 +8219,7 @@
|
|
**
|
|
** [[SQLITE_STMTSTATUS_REPREPARE]] <dt>SQLITE_STMTSTATUS_REPREPARE</dt>
|
|
** <dd>^This is the number of times that the prepare statement has been
|
|
-** automatically regenerated due to schema changes or change to
|
|
+** automatically regenerated due to schema changes or changes to
|
|
** [bound parameters] that might affect the query plan.
|
|
**
|
|
** [[SQLITE_STMTSTATUS_RUN]] <dt>SQLITE_STMTSTATUS_RUN</dt>
|
|
@@ -8042,7 +8390,7 @@
|
|
**
|
|
** ^(SQLite will normally invoke xFetch() with a createFlag of 0 or 1. SQLite
|
|
** will only use a createFlag of 2 after a prior call with a createFlag of 1
|
|
-** failed.)^ In between the to xFetch() calls, SQLite may
|
|
+** failed.)^ In between the xFetch() calls, SQLite may
|
|
** attempt to unpin one or more cache pages by spilling the content of
|
|
** pinned pages to disk and synching the operating system disk cache.
|
|
**
|
|
@@ -8360,7 +8708,7 @@
|
|
** the first argument to register for a callback that will be invoked
|
|
** when the blocking connections current transaction is concluded. ^The
|
|
** callback is invoked from within the [sqlite3_step] or [sqlite3_close]
|
|
-** call that concludes the blocking connections transaction.
|
|
+** call that concludes the blocking connection's transaction.
|
|
**
|
|
** ^(If sqlite3_unlock_notify() is called in a multi-threaded application,
|
|
** there is a chance that the blocking connection will have already
|
|
@@ -8398,7 +8746,7 @@
|
|
** an unlock-notify callback is a pointer to an array of void* pointers,
|
|
** and the second is the number of entries in the array.
|
|
**
|
|
-** When a blocking connections transaction is concluded, there may be
|
|
+** When a blocking connection's transaction is concluded, there may be
|
|
** more than one blocked connection that has registered for an unlock-notify
|
|
** callback. ^If two or more such blocked connections have specified the
|
|
** same callback function, then instead of invoking the callback function
|
|
@@ -8746,14 +9094,20 @@
|
|
** If this interface is invoked outside the context of an xConnect or
|
|
** xCreate virtual table method then the behavior is undefined.
|
|
**
|
|
-** At present, there is only one option that may be configured using
|
|
-** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
|
|
-** may be added in the future.
|
|
+** In the call sqlite3_vtab_config(D,C,...) the D parameter is the
|
|
+** [database connection] in which the virtual table is being created and
|
|
+** which is passed in as the first argument to the [xConnect] or [xCreate]
|
|
+** method that is invoking sqlite3_vtab_config(). The C parameter is one
|
|
+** of the [virtual table configuration options]. The presence and meaning
|
|
+** of parameters after C depend on which [virtual table configuration option]
|
|
+** is used.
|
|
*/
|
|
SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
|
|
|
|
/*
|
|
** CAPI3REF: Virtual Table Configuration Options
|
|
+** KEYWORDS: {virtual table configuration options}
|
|
+** KEYWORDS: {virtual table configuration option}
|
|
**
|
|
** These macros define the various options to the
|
|
** [sqlite3_vtab_config()] interface that [virtual table] implementations
|
|
@@ -8761,7 +9115,7 @@
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_VTAB_CONSTRAINT_SUPPORT]]
|
|
-** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT
|
|
+** <dt>SQLITE_VTAB_CONSTRAINT_SUPPORT</dt>
|
|
** <dd>Calls of the form
|
|
** [sqlite3_vtab_config](db,SQLITE_VTAB_CONSTRAINT_SUPPORT,X) are supported,
|
|
** where X is an integer. If X is zero, then the [virtual table] whose
|
|
@@ -8790,9 +9144,31 @@
|
|
** return SQLITE_OK. Or, if this is not possible, it may return
|
|
** SQLITE_CONSTRAINT, in which case SQLite falls back to OR ABORT
|
|
** constraint handling.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_VTAB_DIRECTONLY]]<dt>SQLITE_VTAB_DIRECTONLY</dt>
|
|
+** <dd>Calls of the form
|
|
+** [sqlite3_vtab_config](db,SQLITE_VTAB_DIRECTONLY) from within the
|
|
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
|
+** prohibits that virtual table from being used from within triggers and
|
|
+** views.
|
|
+** </dd>
|
|
+**
|
|
+** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt>
|
|
+** <dd>Calls of the form
|
|
+** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the
|
|
+** the [xConnect] or [xCreate] methods of a [virtual table] implmentation
|
|
+** identify that virtual table as being safe to use from within triggers
|
|
+** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the
|
|
+** virtual table can do no serious harm even if it is controlled by a
|
|
+** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS
|
|
+** flag unless absolutely necessary.
|
|
+** </dd>
|
|
** </dl>
|
|
*/
|
|
#define SQLITE_VTAB_CONSTRAINT_SUPPORT 1
|
|
+#define SQLITE_VTAB_INNOCUOUS 2
|
|
+#define SQLITE_VTAB_DIRECTONLY 3
|
|
|
|
/*
|
|
** CAPI3REF: Determine The Virtual Table Conflict Policy
|
|
@@ -8872,15 +9248,15 @@
|
|
**
|
|
** <dl>
|
|
** [[SQLITE_SCANSTAT_NLOOP]] <dt>SQLITE_SCANSTAT_NLOOP</dt>
|
|
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be
|
|
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be
|
|
** set to the total number of times that the X-th loop has run.</dd>
|
|
**
|
|
** [[SQLITE_SCANSTAT_NVISIT]] <dt>SQLITE_SCANSTAT_NVISIT</dt>
|
|
-** <dd>^The [sqlite3_int64] variable pointed to by the T parameter will be set
|
|
+** <dd>^The [sqlite3_int64] variable pointed to by the V parameter will be set
|
|
** to the total number of rows examined by all iterations of the X-th loop.</dd>
|
|
**
|
|
** [[SQLITE_SCANSTAT_EST]] <dt>SQLITE_SCANSTAT_EST</dt>
|
|
-** <dd>^The "double" variable pointed to by the T parameter will be set to the
|
|
+** <dd>^The "double" variable pointed to by the V parameter will be set to the
|
|
** query planner's estimate for the average number of rows output from each
|
|
** iteration of the X-th loop. If the query planner's estimates was accurate,
|
|
** then this value will approximate the quotient NVISIT/NLOOP and the
|
|
@@ -8888,17 +9264,17 @@
|
|
** be the NLOOP value for the current loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_NAME]] <dt>SQLITE_SCANSTAT_NAME</dt>
|
|
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
|
|
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
|
|
** to a zero-terminated UTF-8 string containing the name of the index or table
|
|
** used for the X-th loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_EXPLAIN]] <dt>SQLITE_SCANSTAT_EXPLAIN</dt>
|
|
-** <dd>^The "const char *" variable pointed to by the T parameter will be set
|
|
+** <dd>^The "const char *" variable pointed to by the V parameter will be set
|
|
** to a zero-terminated UTF-8 string containing the [EXPLAIN QUERY PLAN]
|
|
** description for the X-th loop.
|
|
**
|
|
** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECT</dt>
|
|
-** <dd>^The "int" variable pointed to by the T parameter will be set to the
|
|
+** <dd>^The "int" variable pointed to by the V parameter will be set to the
|
|
** "select-id" for the X-th loop. The select-id identifies which query or
|
|
** subquery the loop is part of. The main query has a select-id of zero.
|
|
** The select-id is the same value as is output in the first column
|
|
@@ -9753,7 +10129,7 @@
|
|
** The second argument (xFilter) is the "filter callback". For changes to rows
|
|
** in tables that are not attached to the Session object, the filter is called
|
|
** to determine whether changes to the table's rows should be tracked or not.
|
|
-** If xFilter returns 0, changes is not tracked. Note that once a table is
|
|
+** If xFilter returns 0, changes are not tracked. Note that once a table is
|
|
** attached, xFilter will not be called again.
|
|
*/
|
|
SQLITE_API void sqlite3session_table_filter(
|
|
@@ -9927,7 +10303,7 @@
|
|
** It an error if database zFrom does not exist or does not contain the
|
|
** required compatible table.
|
|
**
|
|
-** If the operation successful, SQLITE_OK is returned. Otherwise, an SQLite
|
|
+** If the operation is successful, SQLITE_OK is returned. Otherwise, an SQLite
|
|
** error code. In this case, if argument pzErrMsg is not NULL, *pzErrMsg
|
|
** may be set to point to a buffer containing an English language error
|
|
** message. It is the responsibility of the caller to free this buffer using
|
|
@@ -10064,7 +10440,7 @@
|
|
** CAPI3REF: Advance A Changeset Iterator
|
|
** METHOD: sqlite3_changeset_iter
|
|
**
|
|
-** This function may only be used with iterators created by function
|
|
+** This function may only be used with iterators created by the function
|
|
** [sqlite3changeset_start()]. If it is called on an iterator passed to
|
|
** a conflict-handler callback by [sqlite3changeset_apply()], SQLITE_MISUSE
|
|
** is returned and the call has no effect.
|
|
@@ -10480,8 +10856,8 @@
|
|
** case, this function fails with SQLITE_SCHEMA. If the input changeset
|
|
** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
|
|
** returned. Or, if an out-of-memory condition occurs during processing, this
|
|
-** function returns SQLITE_NOMEM. In all cases, if an error occurs the
|
|
-** final contents of the changegroup is undefined.
|
|
+** function returns SQLITE_NOMEM. In all cases, if an error occurs the state
|
|
+** of the final contents of the changegroup is undefined.
|
|
**
|
|
** If no error occurs, SQLITE_OK is returned.
|
|
*/
|
|
@@ -10656,7 +11032,7 @@
|
|
**
|
|
** It is safe to execute SQL statements, including those that write to the
|
|
** table that the callback related to, from within the xConflict callback.
|
|
-** This can be used to further customize the applications conflict
|
|
+** This can be used to further customize the application's conflict
|
|
** resolution strategy.
|
|
**
|
|
** All changes made by these functions are enclosed in a savepoint transaction.
|
|
@@ -10966,7 +11342,7 @@
|
|
**
|
|
** Argument pIn must point to a buffer containing a changeset nIn bytes
|
|
** in size. This function allocates and populates a buffer with a copy
|
|
-** of the changeset rebased rebased according to the configuration of the
|
|
+** of the changeset rebased according to the configuration of the
|
|
** rebaser object passed as the first argument. If successful, (*ppOut)
|
|
** is set to point to the new buffer containing the rebased changeset and
|
|
** (*pnOut) to its size in bytes and SQLITE_OK returned. It is the
|
|
@@ -11374,7 +11750,7 @@
|
|
**
|
|
** xSetAuxdata(pFts5, pAux, xDelete)
|
|
**
|
|
-** Save the pointer passed as the second argument as the extension functions
|
|
+** Save the pointer passed as the second argument as the extension function's
|
|
** "auxiliary data". The pointer may then be retrieved by the current or any
|
|
** future invocation of the same fts5 extension function made as part of
|
|
** the same MATCH query using the xGetAuxdata() API.
|
|
@@ -11616,8 +11992,8 @@
|
|
**
|
|
** There are several ways to approach this in FTS5:
|
|
**
|
|
-** <ol><li> By mapping all synonyms to a single token. In this case, the
|
|
-** In the above example, this means that the tokenizer returns the
|
|
+** <ol><li> By mapping all synonyms to a single token. In this case, using
|
|
+** the above example, this means that the tokenizer returns the
|
|
** same token for inputs "first" and "1st". Say that token is in
|
|
** fact "first", so that when the user inserts the document "I won
|
|
** 1st place" entries are added to the index for tokens "i", "won",
|
|
--- contrib/sqlite3/sqlite3ext.h.orig
|
|
+++ contrib/sqlite3/sqlite3ext.h
|
|
@@ -322,6 +322,19 @@
|
|
/* Version 3.28.0 and later */
|
|
int (*stmt_isexplain)(sqlite3_stmt*);
|
|
int (*value_frombind)(sqlite3_value*);
|
|
+ /* Version 3.30.0 and later */
|
|
+ int (*drop_modules)(sqlite3*,const char**);
|
|
+ /* Version 3.31.0 and later */
|
|
+ sqlite3_int64 (*hard_heap_limit64)(sqlite3_int64);
|
|
+ const char *(*uri_key)(const char*,int);
|
|
+ const char *(*filename_database)(const char*);
|
|
+ const char *(*filename_journal)(const char*);
|
|
+ const char *(*filename_wal)(const char*);
|
|
+ /* Version 3.32.0 and later */
|
|
+ char *(*create_filename)(const char*,const char*,const char*,
|
|
+ int,const char**);
|
|
+ void (*free_filename)(char*);
|
|
+ sqlite3_file *(*database_file_object)(const char*);
|
|
};
|
|
|
|
/*
|
|
@@ -612,8 +625,20 @@
|
|
/* Version 3.26.0 and later */
|
|
#define sqlite3_normalized_sql sqlite3_api->normalized_sql
|
|
/* Version 3.28.0 and later */
|
|
-#define sqlite3_stmt_isexplain sqlite3_api->isexplain
|
|
-#define sqlite3_value_frombind sqlite3_api->frombind
|
|
+#define sqlite3_stmt_isexplain sqlite3_api->stmt_isexplain
|
|
+#define sqlite3_value_frombind sqlite3_api->value_frombind
|
|
+/* Version 3.30.0 and later */
|
|
+#define sqlite3_drop_modules sqlite3_api->drop_modules
|
|
+/* Version 3.31.0 and later */
|
|
+#define sqlite3_hard_heap_limit64 sqlite3_api->hard_heap_limit64
|
|
+#define sqlite3_uri_key sqlite3_api->uri_key
|
|
+#define sqlite3_filename_database sqlite3_api->filename_database
|
|
+#define sqlite3_filename_journal sqlite3_api->filename_journal
|
|
+#define sqlite3_filename_wal sqlite3_api->filename_wal
|
|
+/* Version 3.32.0 and later */
|
|
+#define sqlite3_create_filename sqlite3_api->create_filename
|
|
+#define sqlite3_free_filename sqlite3_api->free_filename
|
|
+#define sqlite3_database_file_object sqlite3_api->database_file_object
|
|
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
|
|
|
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
|
--- contrib/sqlite3/tea/configure.orig
|
|
+++ contrib/sqlite3/tea/configure
|
|
@@ -1,6 +1,6 @@
|
|
#! /bin/sh
|
|
# Guess values for system-dependent variables and create Makefiles.
|
|
-# Generated by GNU Autoconf 2.69 for sqlite 3.29.0.
|
|
+# Generated by GNU Autoconf 2.69 for sqlite 3.32.2.
|
|
#
|
|
#
|
|
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
|
@@ -577,8 +577,8 @@
|
|
# Identity of this package.
|
|
PACKAGE_NAME='sqlite'
|
|
PACKAGE_TARNAME='sqlite'
|
|
-PACKAGE_VERSION='3.29.0'
|
|
-PACKAGE_STRING='sqlite 3.29.0'
|
|
+PACKAGE_VERSION='3.32.2'
|
|
+PACKAGE_STRING='sqlite 3.32.2'
|
|
PACKAGE_BUGREPORT=''
|
|
PACKAGE_URL=''
|
|
|
|
@@ -1303,7 +1303,7 @@
|
|
# Omit some internal or obsolete options to make the list less imposing.
|
|
# This message is too long to be a string in the A/UX 3.1 sh.
|
|
cat <<_ACEOF
|
|
-\`configure' configures sqlite 3.29.0 to adapt to many kinds of systems.
|
|
+\`configure' configures sqlite 3.32.2 to adapt to many kinds of systems.
|
|
|
|
Usage: $0 [OPTION]... [VAR=VALUE]...
|
|
|
|
@@ -1365,7 +1365,7 @@
|
|
|
|
if test -n "$ac_init_help"; then
|
|
case $ac_init_help in
|
|
- short | recursive ) echo "Configuration of sqlite 3.29.0:";;
|
|
+ short | recursive ) echo "Configuration of sqlite 3.32.2:";;
|
|
esac
|
|
cat <<\_ACEOF
|
|
|
|
@@ -1467,7 +1467,7 @@
|
|
test -n "$ac_init_help" && exit $ac_status
|
|
if $ac_init_version; then
|
|
cat <<\_ACEOF
|
|
-sqlite configure 3.29.0
|
|
+sqlite configure 3.32.2
|
|
generated by GNU Autoconf 2.69
|
|
|
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
|
@@ -1878,7 +1878,7 @@
|
|
This file contains any messages produced by compilers while
|
|
running configure, to aid debugging if configure makes a mistake.
|
|
|
|
-It was created by sqlite $as_me 3.29.0, which was
|
|
+It was created by sqlite $as_me 3.32.2, which was
|
|
generated by GNU Autoconf 2.69. Invocation command line was
|
|
|
|
$ $0 $@
|
|
@@ -9373,7 +9373,7 @@
|
|
# report actual input values of CONFIG_FILES etc. instead of their
|
|
# values after options handling.
|
|
ac_log="
|
|
-This file was extended by sqlite $as_me 3.29.0, which was
|
|
+This file was extended by sqlite $as_me 3.32.2, which was
|
|
generated by GNU Autoconf 2.69. Invocation command line was
|
|
|
|
CONFIG_FILES = $CONFIG_FILES
|
|
@@ -9426,7 +9426,7 @@
|
|
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
|
|
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
|
|
ac_cs_version="\\
|
|
-sqlite config.status 3.29.0
|
|
+sqlite config.status 3.32.2
|
|
configured by $0, generated by GNU Autoconf 2.69,
|
|
with options \\"\$ac_cs_config\\"
|
|
|
|
--- contrib/sqlite3/tea/configure.ac.orig
|
|
+++ contrib/sqlite3/tea/configure.ac
|
|
@@ -19,7 +19,7 @@
|
|
# so you can encode the package version directly into the source files.
|
|
#-----------------------------------------------------------------------
|
|
|
|
-AC_INIT([sqlite], [3.29.0])
|
|
+AC_INIT([sqlite], [3.32.2])
|
|
|
|
#--------------------------------------------------------------------
|
|
# Call TEA_INIT as the first TEA_ macro to set up initial vars.
|
|
--- contrib/sqlite3/tea/generic/tclsqlite3.c.orig
|
|
+++ contrib/sqlite3/tea/generic/tclsqlite3.c
|
|
@@ -1922,33 +1922,33 @@
|
|
"authorizer", "backup", "bind_fallback",
|
|
"busy", "cache", "changes",
|
|
"close", "collate", "collation_needed",
|
|
- "commit_hook", "complete", "copy",
|
|
- "deserialize", "enable_load_extension", "errorcode",
|
|
- "eval", "exists", "function",
|
|
- "incrblob", "interrupt", "last_insert_rowid",
|
|
- "nullvalue", "onecolumn", "preupdate",
|
|
- "profile", "progress", "rekey",
|
|
- "restore", "rollback_hook", "serialize",
|
|
- "status", "timeout", "total_changes",
|
|
- "trace", "trace_v2", "transaction",
|
|
- "unlock_notify", "update_hook", "version",
|
|
- "wal_hook", 0
|
|
+ "commit_hook", "complete", "config",
|
|
+ "copy", "deserialize", "enable_load_extension",
|
|
+ "errorcode", "eval", "exists",
|
|
+ "function", "incrblob", "interrupt",
|
|
+ "last_insert_rowid", "nullvalue", "onecolumn",
|
|
+ "preupdate", "profile", "progress",
|
|
+ "rekey", "restore", "rollback_hook",
|
|
+ "serialize", "status", "timeout",
|
|
+ "total_changes", "trace", "trace_v2",
|
|
+ "transaction", "unlock_notify", "update_hook",
|
|
+ "version", "wal_hook", 0
|
|
};
|
|
enum DB_enum {
|
|
DB_AUTHORIZER, DB_BACKUP, DB_BIND_FALLBACK,
|
|
DB_BUSY, DB_CACHE, DB_CHANGES,
|
|
DB_CLOSE, DB_COLLATE, DB_COLLATION_NEEDED,
|
|
- DB_COMMIT_HOOK, DB_COMPLETE, DB_COPY,
|
|
- DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,DB_ERRORCODE,
|
|
- DB_EVAL, DB_EXISTS, DB_FUNCTION,
|
|
- DB_INCRBLOB, DB_INTERRUPT, DB_LAST_INSERT_ROWID,
|
|
- DB_NULLVALUE, DB_ONECOLUMN, DB_PREUPDATE,
|
|
- DB_PROFILE, DB_PROGRESS, DB_REKEY,
|
|
- DB_RESTORE, DB_ROLLBACK_HOOK, DB_SERIALIZE,
|
|
- DB_STATUS, DB_TIMEOUT, DB_TOTAL_CHANGES,
|
|
- DB_TRACE, DB_TRACE_V2, DB_TRANSACTION,
|
|
- DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK, DB_VERSION,
|
|
- DB_WAL_HOOK
|
|
+ DB_COMMIT_HOOK, DB_COMPLETE, DB_CONFIG,
|
|
+ DB_COPY, DB_DESERIALIZE, DB_ENABLE_LOAD_EXTENSION,
|
|
+ DB_ERRORCODE, DB_EVAL, DB_EXISTS,
|
|
+ DB_FUNCTION, DB_INCRBLOB, DB_INTERRUPT,
|
|
+ DB_LAST_INSERT_ROWID, DB_NULLVALUE, DB_ONECOLUMN,
|
|
+ DB_PREUPDATE, DB_PROFILE, DB_PROGRESS,
|
|
+ DB_REKEY, DB_RESTORE, DB_ROLLBACK_HOOK,
|
|
+ DB_SERIALIZE, DB_STATUS, DB_TIMEOUT,
|
|
+ DB_TOTAL_CHANGES, DB_TRACE, DB_TRACE_V2,
|
|
+ DB_TRANSACTION, DB_UNLOCK_NOTIFY, DB_UPDATE_HOOK,
|
|
+ DB_VERSION, DB_WAL_HOOK
|
|
};
|
|
/* don't leave trailing commas on DB_enum, it confuses the AIX xlc compiler */
|
|
|
|
@@ -2336,6 +2336,76 @@
|
|
break;
|
|
}
|
|
|
|
+ /* $db config ?OPTION? ?BOOLEAN?
|
|
+ **
|
|
+ ** Configure the database connection using the sqlite3_db_config()
|
|
+ ** interface.
|
|
+ */
|
|
+ case DB_CONFIG: {
|
|
+ static const struct DbConfigChoices {
|
|
+ const char *zName;
|
|
+ int op;
|
|
+ } aDbConfig[] = {
|
|
+ { "defensive", SQLITE_DBCONFIG_DEFENSIVE },
|
|
+ { "dqs_ddl", SQLITE_DBCONFIG_DQS_DDL },
|
|
+ { "dqs_dml", SQLITE_DBCONFIG_DQS_DML },
|
|
+ { "enable_fkey", SQLITE_DBCONFIG_ENABLE_FKEY },
|
|
+ { "enable_qpsg", SQLITE_DBCONFIG_ENABLE_QPSG },
|
|
+ { "enable_trigger", SQLITE_DBCONFIG_ENABLE_TRIGGER },
|
|
+ { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW },
|
|
+ { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER },
|
|
+ { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE },
|
|
+ { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT },
|
|
+ { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
|
|
+ { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
|
|
+ { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE },
|
|
+ { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP },
|
|
+ { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA },
|
|
+ { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA },
|
|
+ };
|
|
+ Tcl_Obj *pResult;
|
|
+ int ii;
|
|
+ if( objc>4 ){
|
|
+ Tcl_WrongNumArgs(interp, 2, objv, "?OPTION? ?BOOLEAN?");
|
|
+ return TCL_ERROR;
|
|
+ }
|
|
+ if( objc==2 ){
|
|
+ /* With no arguments, list all configuration options and with the
|
|
+ ** current value */
|
|
+ pResult = Tcl_NewListObj(0,0);
|
|
+ for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
|
|
+ int v = 0;
|
|
+ sqlite3_db_config(pDb->db, aDbConfig[ii].op, -1, &v);
|
|
+ Tcl_ListObjAppendElement(interp, pResult,
|
|
+ Tcl_NewStringObj(aDbConfig[ii].zName,-1));
|
|
+ Tcl_ListObjAppendElement(interp, pResult,
|
|
+ Tcl_NewIntObj(v));
|
|
+ }
|
|
+ }else{
|
|
+ const char *zOpt = Tcl_GetString(objv[2]);
|
|
+ int onoff = -1;
|
|
+ int v = 0;
|
|
+ if( zOpt[0]=='-' ) zOpt++;
|
|
+ for(ii=0; ii<sizeof(aDbConfig)/sizeof(aDbConfig[0]); ii++){
|
|
+ if( strcmp(aDbConfig[ii].zName, zOpt)==0 ) break;
|
|
+ }
|
|
+ if( ii>=sizeof(aDbConfig)/sizeof(aDbConfig[0]) ){
|
|
+ Tcl_AppendResult(interp, "unknown config option: \"", zOpt,
|
|
+ "\"", (void*)0);
|
|
+ return TCL_ERROR;
|
|
+ }
|
|
+ if( objc==4 ){
|
|
+ if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ){
|
|
+ return TCL_ERROR;
|
|
+ }
|
|
+ }
|
|
+ sqlite3_db_config(pDb->db, aDbConfig[ii].op, onoff, &v);
|
|
+ pResult = Tcl_NewIntObj(v);
|
|
+ }
|
|
+ Tcl_SetObjResult(interp, pResult);
|
|
+ break;
|
|
+ }
|
|
+
|
|
/* $db copy conflict-algorithm table filename ?SEPARATOR? ?NULLINDICATOR?
|
|
**
|
|
** Copy data into table from filename, optionally using SEPARATOR
|
|
@@ -2746,10 +2816,17 @@
|
|
}
|
|
|
|
/*
|
|
- ** $db function NAME [-argcount N] [-deterministic] SCRIPT
|
|
+ ** $db function NAME [OPTIONS] SCRIPT
|
|
**
|
|
** Create a new SQL function called NAME. Whenever that function is
|
|
** called, invoke SCRIPT to evaluate the function.
|
|
+ **
|
|
+ ** Options:
|
|
+ ** --argcount N Function has exactly N arguments
|
|
+ ** --deterministic The function is pure
|
|
+ ** --directonly Prohibit use inside triggers and views
|
|
+ ** --innocuous Has no side effects or information leaks
|
|
+ ** --returntype TYPE Specify the return type of the function
|
|
*/
|
|
case DB_FUNCTION: {
|
|
int flags = SQLITE_UTF8;
|
|
@@ -2782,6 +2859,12 @@
|
|
if( n>1 && strncmp(z, "-deterministic",n)==0 ){
|
|
flags |= SQLITE_DETERMINISTIC;
|
|
}else
|
|
+ if( n>1 && strncmp(z, "-directonly",n)==0 ){
|
|
+ flags |= SQLITE_DIRECTONLY;
|
|
+ }else
|
|
+ if( n>1 && strncmp(z, "-innocuous",n)==0 ){
|
|
+ flags |= SQLITE_INNOCUOUS;
|
|
+ }else
|
|
if( n>1 && strncmp(z, "-returntype", n)==0 ){
|
|
const char *azType[] = {"integer", "real", "text", "blob", "any", 0};
|
|
assert( SQLITE_INTEGER==1 && SQLITE_FLOAT==2 && SQLITE_TEXT==3 );
|
|
@@ -2797,7 +2880,8 @@
|
|
eType++;
|
|
}else{
|
|
Tcl_AppendResult(interp, "bad option \"", z,
|
|
- "\": must be -argcount, -deterministic or -returntype", (char*)0
|
|
+ "\": must be -argcount, -deterministic, -directonly,"
|
|
+ " -innocuous, or -returntype", (char*)0
|
|
);
|
|
return TCL_ERROR;
|
|
}
|
|
@@ -3015,22 +3099,10 @@
|
|
** Change the encryption key on the currently open database.
|
|
*/
|
|
case DB_REKEY: {
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- int nKey;
|
|
- void *pKey;
|
|
-#endif
|
|
if( objc!=3 ){
|
|
Tcl_WrongNumArgs(interp, 2, objv, "KEY");
|
|
return TCL_ERROR;
|
|
}
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- pKey = Tcl_GetByteArrayFromObj(objv[2], &nKey);
|
|
- rc = sqlite3_rekey(pDb->db, pKey, nKey);
|
|
- if( rc ){
|
|
- Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0);
|
|
- rc = TCL_ERROR;
|
|
- }
|
|
-#endif
|
|
break;
|
|
}
|
|
|
|
@@ -3597,10 +3669,8 @@
|
|
){
|
|
Tcl_WrongNumArgs(interp, 1, objv,
|
|
"HANDLE ?FILENAME? ?-vfs VFSNAME? ?-readonly BOOLEAN? ?-create BOOLEAN?"
|
|
+ " ?-nofollow BOOLEAN?"
|
|
" ?-nomutex BOOLEAN? ?-fullmutex BOOLEAN? ?-uri BOOLEAN?"
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- " ?-key CODECKEY?"
|
|
-#endif
|
|
);
|
|
return TCL_ERROR;
|
|
}
|
|
@@ -3608,6 +3678,7 @@
|
|
/*
|
|
** sqlite3 DBNAME FILENAME ?-vfs VFSNAME? ?-key KEY? ?-readonly BOOLEAN?
|
|
** ?-create BOOLEAN? ?-nomutex BOOLEAN?
|
|
+** ?-nofollow BOOLEAN?
|
|
**
|
|
** This is the main Tcl command. When the "sqlite" Tcl command is
|
|
** invoked, this routine runs to process that command.
|
|
@@ -3633,11 +3704,8 @@
|
|
const char *zFile = 0;
|
|
const char *zVfs = 0;
|
|
int flags;
|
|
+ int bTranslateFileName = 1;
|
|
Tcl_DString translatedFilename;
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- void *pKey = 0;
|
|
- int nKey = 0;
|
|
-#endif
|
|
int rc;
|
|
|
|
/* In normal use, each TCL interpreter runs in a single thread. So
|
|
@@ -3664,11 +3732,7 @@
|
|
return TCL_OK;
|
|
}
|
|
if( strcmp(zArg,"-has-codec")==0 ){
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- Tcl_AppendResult(interp,"1",(char*)0);
|
|
-#else
|
|
Tcl_AppendResult(interp,"0",(char*)0);
|
|
-#endif
|
|
return TCL_OK;
|
|
}
|
|
if( zArg[0]=='-' ) return sqliteCmdUsage(interp, objv);
|
|
@@ -3683,9 +3747,7 @@
|
|
if( i==objc-1 ) return sqliteCmdUsage(interp, objv);
|
|
i++;
|
|
if( strcmp(zArg,"-key")==0 ){
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- pKey = Tcl_GetByteArrayFromObj(objv[i], &nKey);
|
|
-#endif
|
|
+ /* no-op */
|
|
}else if( strcmp(zArg, "-vfs")==0 ){
|
|
zVfs = Tcl_GetString(objv[i]);
|
|
}else if( strcmp(zArg, "-readonly")==0 ){
|
|
@@ -3706,6 +3768,14 @@
|
|
}else{
|
|
flags &= ~SQLITE_OPEN_CREATE;
|
|
}
|
|
+ }else if( strcmp(zArg, "-nofollow")==0 ){
|
|
+ int b;
|
|
+ if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
|
+ if( b ){
|
|
+ flags |= SQLITE_OPEN_NOFOLLOW;
|
|
+ }else{
|
|
+ flags &= ~SQLITE_OPEN_NOFOLLOW;
|
|
+ }
|
|
}else if( strcmp(zArg, "-nomutex")==0 ){
|
|
int b;
|
|
if( Tcl_GetBooleanFromObj(interp, objv[i], &b) ) return TCL_ERROR;
|
|
@@ -3732,6 +3802,10 @@
|
|
}else{
|
|
flags &= ~SQLITE_OPEN_URI;
|
|
}
|
|
+ }else if( strcmp(zArg, "-translatefilename")==0 ){
|
|
+ if( Tcl_GetBooleanFromObj(interp, objv[i], &bTranslateFileName) ){
|
|
+ return TCL_ERROR;
|
|
+ }
|
|
}else{
|
|
Tcl_AppendResult(interp, "unknown option: ", zArg, (char*)0);
|
|
return TCL_ERROR;
|
|
@@ -3741,9 +3815,13 @@
|
|
p = (SqliteDb*)Tcl_Alloc( sizeof(*p) );
|
|
memset(p, 0, sizeof(*p));
|
|
if( zFile==0 ) zFile = "";
|
|
- zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
|
|
+ if( bTranslateFileName ){
|
|
+ zFile = Tcl_TranslateFileName(interp, zFile, &translatedFilename);
|
|
+ }
|
|
rc = sqlite3_open_v2(zFile, &p->db, flags, zVfs);
|
|
- Tcl_DStringFree(&translatedFilename);
|
|
+ if( bTranslateFileName ){
|
|
+ Tcl_DStringFree(&translatedFilename);
|
|
+ }
|
|
if( p->db ){
|
|
if( SQLITE_OK!=sqlite3_errcode(p->db) ){
|
|
zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(p->db));
|
|
@@ -3753,11 +3831,6 @@
|
|
}else{
|
|
zErrMsg = sqlite3_mprintf("%s", sqlite3_errstr(rc));
|
|
}
|
|
-#if defined(SQLITE_HAS_CODEC) && !defined(SQLITE_OMIT_CODEC_FROM_TCL)
|
|
- if( p->db ){
|
|
- sqlite3_key(p->db, pKey, nKey);
|
|
- }
|
|
-#endif
|
|
if( p->db==0 ){
|
|
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
|
|
Tcl_Free((char*)p);
|
|
--- contrib/sqlite3/tea/win/makefile.vc.orig
|
|
+++ contrib/sqlite3/tea/win/makefile.vc
|
|
@@ -153,7 +153,7 @@
|
|
#
|
|
#-------------------------------------------------------------------------
|
|
|
|
-PROJECT = sqlite3
|
|
+PROJECT = tclsqlite3
|
|
!include "rules.vc"
|
|
|
|
# nmakehelp -V <file> <tag> will search the file for tag, skips until a
|
|
@@ -162,18 +162,15 @@
|
|
|
|
!if [echo REM = This file is generated from Makefile.vc > versions.vc]
|
|
!endif
|
|
-# get project version from row "AC_INIT([sqlite], [3.7.14])"
|
|
+# get project version from row "AC_INIT([sqlite], [3.x.y])"
|
|
!if [echo DOTVERSION = \>> versions.vc] \
|
|
- && [nmakehlp -V ..\configure.in AC_INIT >> versions.vc]
|
|
+ && [nmakehlp -V ..\configure.ac AC_INIT >> versions.vc]
|
|
!endif
|
|
!include "versions.vc"
|
|
|
|
VERSION = $(DOTVERSION:.=)
|
|
STUBPREFIX = $(PROJECT)stub
|
|
|
|
-DLLOBJS = \
|
|
- $(TMP_DIR)\tclsqlite3.obj
|
|
-
|
|
#-------------------------------------------------------------------------
|
|
# Target names and paths ( shouldn't need changing )
|
|
#-------------------------------------------------------------------------
|
|
@@ -182,7 +179,7 @@
|
|
ROOT = ..
|
|
|
|
PRJIMPLIB = $(OUT_DIR)\$(PROJECT)$(VERSION)$(SUFX).lib
|
|
-PRJLIBNAME = $(PROJECT)$(VERSION)$(SUFX).$(EXT)
|
|
+PRJLIBNAME = $(PROJECT).$(EXT)
|
|
PRJLIB = $(OUT_DIR)\$(PRJLIBNAME)
|
|
|
|
PRJSTUBLIBNAME = $(STUBPREFIX)$(VERSION).lib
|
|
@@ -204,6 +201,17 @@
|
|
TOOLSDIR = $(ROOT)\tools
|
|
COMPATDIR = $(ROOT)\compat
|
|
|
|
+### Figure out where the primary source code file(s) is/are.
|
|
+!if exist("$(ROOT)\..\..\sqlite3.c") && exist("$(ROOT)\..\..\src\tclsqlite.c")
|
|
+SQL_INCLUDES = -I"$(ROOT)\..\.."
|
|
+SQLITE_SRCDIR = $(ROOT)\..\..
|
|
+TCLSQLITE_SRCDIR = $(ROOT)\..\..\src
|
|
+DLLOBJS = $(TMP_DIR)\sqlite3.obj $(TMP_DIR)\tclsqlite.obj
|
|
+!else
|
|
+TCLSQLITE_SRCDIR = $(ROOT)\generic
|
|
+DLLOBJS = $(TMP_DIR)\tclsqlite3.obj
|
|
+!endif
|
|
+
|
|
#---------------------------------------------------------------------
|
|
# Compile flags
|
|
#---------------------------------------------------------------------
|
|
@@ -223,7 +231,7 @@
|
|
!endif
|
|
|
|
### Declarations common to all compiler options
|
|
-cflags = -nologo -c -W3 -YX -Fp$(TMP_DIR)^\
|
|
+cflags = -nologo -c -W3 -D_CRT_SECURE_NO_WARNINGS -YX -Fp$(TMP_DIR)^\
|
|
|
|
!if $(MSVCRT)
|
|
!if $(DEBUG)
|
|
@@ -239,8 +247,8 @@
|
|
!endif
|
|
!endif
|
|
|
|
-INCLUDES = $(TCL_INCLUDES) -I"$(WINDIR)" -I"$(GENERICDIR)" \
|
|
- -I"$(ROOT)\.."
|
|
+INCLUDES = $(SQL_INCLUDES) $(TCL_INCLUDES) -I"$(WINDIR)" \
|
|
+ -I"$(GENERICDIR)" -I"$(ROOT)\.."
|
|
BASE_CLFAGS = $(cflags) $(cdebug) $(crt) $(INCLUDES) \
|
|
-DSQLITE_3_SUFFIX_ONLY=1 -DSQLITE_ENABLE_RTREE=1 \
|
|
-DSQLITE_ENABLE_FTS3=1 -DSQLITE_OMIT_DEPRECATED=1
|
|
@@ -341,20 +349,17 @@
|
|
# Implicit rules
|
|
#---------------------------------------------------------------------
|
|
|
|
-{$(WINDIR)}.c{$(TMP_DIR)}.obj::
|
|
- $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
|
|
-$<
|
|
-<<
|
|
+$(TMP_DIR)\sqlite3.obj: $(SQLITE_SRCDIR)\sqlite3.c
|
|
+ $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
|
|
+ -c $(SQLITE_SRCDIR)\sqlite3.c
|
|
|
|
-{$(GENERICDIR)}.c{$(TMP_DIR)}.obj::
|
|
- $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
|
|
-$<
|
|
-<<
|
|
+$(TMP_DIR)\tclsqlite.obj: $(TCLSQLITE_SRCDIR)\tclsqlite.c
|
|
+ $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
|
|
+ -c $(TCLSQLITE_SRCDIR)\tclsqlite.c
|
|
|
|
-{$(COMPATDIR)}.c{$(TMP_DIR)}.obj::
|
|
- $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ @<<
|
|
-$<
|
|
-<<
|
|
+$(TMP_DIR)\tclsqlite3.obj: $(TCLSQLITE_SRCDIR)\tclsqlite3.c
|
|
+ $(cc32) $(TCL_CFLAGS) -DBUILD_$(PROJECT) -Fo$(TMP_DIR)\ \
|
|
+ -c $(TCLSQLITE_SRCDIR)\tclsqlite3.c
|
|
|
|
{$(WINDIR)}.rc{$(TMP_DIR)}.res:
|
|
$(rc32) -fo $@ -r -i "$(GENERICDIR)" -D__WIN32__ \
|