Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 814aad618c | |||
| da1f49b83f | |||
| ba87c6c2cd | |||
| 76cf858d3d | |||
| 0942559a14 | |||
| f217f3b68c | |||
| 90cdec0672 | |||
| 594ccd09b1 | |||
| 20c9c3f4eb | |||
| c74d962a1f | |||
| 2ebf8f474e | |||
| 6e3bccd5c9 | |||
| 56790ea567 | |||
| eafc6dfe2b | |||
| e46c63d565 | |||
| c62aab5ba8 | |||
| c097b309aa | |||
| c5d353fb33 | |||
| d96cc6fbcb | |||
| ca66f6c6f4 | |||
| cc97ca4c08 | |||
| d1417ee1cb | |||
| cf1393df94 | |||
| b1d66c5986 | |||
| a4327e65bb | |||
| 64bf76d2b2 | |||
| 3b77506ba5 | |||
| 4c88348729 | |||
| 5930f663a1 | |||
| 629a75f69a | |||
| 1346fdad65 | |||
| 16d62901a3 | |||
| f151890791 | |||
| a2e71ced79 | |||
| 170ad68a40 | |||
| 6c2d94f928 | |||
| c5e56b3473 | |||
| cdbb126be7 | |||
| 3528f6b62b | |||
| 6b37e0adc9 | |||
| d4ab003d4e | |||
| d5bdd5effb | |||
| b8a1290a28 | |||
| 02f18cc5ac | |||
| a8b9793c86 | |||
| d03257c141 | |||
| 2ab792e4c0 | |||
| d26d2c7de2 | |||
| e70d01f143 | |||
| 1e669f02bc | |||
| 8c9ed054b3 | |||
| 77f6af2b96 | |||
| 5f5a2d1c3c | |||
| 8abc54e2e8 | |||
| 979dd1be57 | |||
| d8a295669c | |||
| e16a350f17 | |||
| ae2ac854b3 | |||
| 14e845a9d4 | |||
| 137c46f8b6 | |||
| 65ff63ea62 | |||
| dc6de47925 | |||
| 074ce1e7fd | |||
| 8389bff0a8 | |||
| f43ce0b445 | |||
| 831265f962 | |||
| 63ad86e70e | |||
| ce13b99f99 | |||
| 92b71757f7 | |||
| 1d1fc5e385 | |||
| eff0a7b25e | |||
| 3f1e9e00e6 | |||
| d4fb196531 | |||
| 07d0f15e93 | |||
| 453ca043a2 | |||
| ee841262d9 | |||
| d758722449 | |||
| 21766c0c16 | |||
| 78436d4c66 | |||
| e46515b53f | |||
| bcbb066534 | |||
| 748465b49e | |||
| 1e1c4226ee |
@@ -12,7 +12,7 @@ sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
|
||||
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
|
||||
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h msvc.h
|
||||
include_HEADERS = sqlite3.h sqlite3ext.h
|
||||
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#! /bin/sh
|
||||
# Guess values for system-dependent variables and create Makefiles.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.19.1.
|
||||
# Generated by GNU Autoconf 2.69 for sqlite 3.20.0.
|
||||
#
|
||||
#
|
||||
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
|
||||
@@ -726,8 +726,8 @@ MAKEFLAGS=
|
||||
# Identity of this package.
|
||||
PACKAGE_NAME='sqlite'
|
||||
PACKAGE_TARNAME='sqlite'
|
||||
PACKAGE_VERSION='3.19.1'
|
||||
PACKAGE_STRING='sqlite 3.19.1'
|
||||
PACKAGE_VERSION='3.20.0'
|
||||
PACKAGE_STRING='sqlite 3.20.0'
|
||||
PACKAGE_BUGREPORT=''
|
||||
PACKAGE_URL=''
|
||||
|
||||
@@ -1463,7 +1463,7 @@ if test "$ac_init_help" = "long"; then
|
||||
# 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.19.1 to adapt to many kinds of systems.
|
||||
\`configure' configures sqlite 3.20.0 to adapt to many kinds of systems.
|
||||
|
||||
Usage: $0 [OPTION]... [VAR=VALUE]...
|
||||
|
||||
@@ -1528,7 +1528,7 @@ fi
|
||||
|
||||
if test -n "$ac_init_help"; then
|
||||
case $ac_init_help in
|
||||
short | recursive ) echo "Configuration of sqlite 3.19.1:";;
|
||||
short | recursive ) echo "Configuration of sqlite 3.20.0:";;
|
||||
esac
|
||||
cat <<\_ACEOF
|
||||
|
||||
@@ -1652,7 +1652,7 @@ fi
|
||||
test -n "$ac_init_help" && exit $ac_status
|
||||
if $ac_init_version; then
|
||||
cat <<\_ACEOF
|
||||
sqlite configure 3.19.1
|
||||
sqlite configure 3.20.0
|
||||
generated by GNU Autoconf 2.69
|
||||
|
||||
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||
@@ -2071,7 +2071,7 @@ cat >config.log <<_ACEOF
|
||||
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.19.1, which was
|
||||
It was created by sqlite $as_me 3.20.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
$ $0 $@
|
||||
@@ -11356,7 +11356,7 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS5" >&5
|
||||
$as_echo_n "checking whether to support MEMSYS5... " >&6; }
|
||||
if test "${enable_memsys5}" = "yes"; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS5"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
@@ -11373,7 +11373,7 @@ fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to support MEMSYS3" >&5
|
||||
$as_echo_n "checking whether to support MEMSYS3... " >&6; }
|
||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS3"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
else
|
||||
@@ -11391,7 +11391,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
fi
|
||||
# Check whether --enable-fts4 was given.
|
||||
if test "${enable_fts4+set}" = set; then :
|
||||
@@ -11401,7 +11401,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
@@ -11467,7 +11467,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing log" >&5
|
||||
$as_echo_n "checking for library containing log... " >&6; }
|
||||
if ${ac_cv_search_log+:} false; then :
|
||||
@@ -11536,7 +11536,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11549,7 +11549,7 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -11562,12 +11562,12 @@ else
|
||||
fi
|
||||
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
do
|
||||
case $option in
|
||||
@@ -12151,7 +12151,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
|
||||
# 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.19.1, which was
|
||||
This file was extended by sqlite $as_me 3.20.0, which was
|
||||
generated by GNU Autoconf 2.69. Invocation command line was
|
||||
|
||||
CONFIG_FILES = $CONFIG_FILES
|
||||
@@ -12217,7 +12217,7 @@ _ACEOF
|
||||
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.19.1
|
||||
sqlite config.status 3.20.0
|
||||
configured by $0, generated by GNU Autoconf 2.69,
|
||||
with options \\"\$ac_cs_config\\"
|
||||
|
||||
|
||||
+10
-10
@@ -596,7 +596,7 @@ AC_ARG_ENABLE(memsys5,
|
||||
[enable_memsys5=yes],[enable_memsys5=no])
|
||||
AC_MSG_CHECKING([whether to support MEMSYS5])
|
||||
if test "${enable_memsys5}" = "yes"; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS5"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
@@ -606,7 +606,7 @@ AC_ARG_ENABLE(memsys3,
|
||||
[enable_memsys3=yes],[enable_memsys3=no])
|
||||
AC_MSG_CHECKING([whether to support MEMSYS3])
|
||||
if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_MEMSYS3"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3"
|
||||
AC_MSG_RESULT([yes])
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
@@ -618,20 +618,20 @@ AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3],
|
||||
[Enable the FTS3 extension]),
|
||||
[enable_fts3=yes],[enable_fts3=no])
|
||||
if test "${enable_fts3}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3"
|
||||
fi
|
||||
AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4],
|
||||
[Enable the FTS4 extension]),
|
||||
[enable_fts4=yes],[enable_fts4=no])
|
||||
if test "${enable_fts4}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS4"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5],
|
||||
[Enable the FTS5 extension]),
|
||||
[enable_fts5=yes],[enable_fts5=no])
|
||||
if test "${enable_fts5}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS5"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5"
|
||||
AC_SEARCH_LIBS([log],[m])
|
||||
fi
|
||||
|
||||
@@ -641,7 +641,7 @@ AC_ARG_ENABLE(json1, AC_HELP_STRING([--enable-json1],
|
||||
[Enable the JSON1 extension]),
|
||||
[enable_json1=yes],[enable_json1=no])
|
||||
if test "${enable_json1}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_JSON1"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -650,7 +650,7 @@ AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
|
||||
[Enable the RTREE extension]),
|
||||
[enable_rtree=yes],[enable_rtree=no])
|
||||
if test "${enable_rtree}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE"
|
||||
fi
|
||||
|
||||
#########
|
||||
@@ -659,12 +659,12 @@ AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session],
|
||||
[Enable the SESSION extension]),
|
||||
[enable_session=yes],[enable_session=no])
|
||||
if test "${enable_session}" = "yes" ; then
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="$(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION"
|
||||
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK"
|
||||
fi
|
||||
|
||||
#########
|
||||
# attempt to duplicate any OMITS and ENABLES into the $(OPT_FEATURE_FLAGS) parameter
|
||||
# attempt to duplicate any OMITS and ENABLES into the ${OPT_FEATURE_FLAGS} parameter
|
||||
for option in $CFLAGS $CPPFLAGS
|
||||
do
|
||||
case $option in
|
||||
|
||||
@@ -23,6 +23,26 @@ or embedded controllers.</p>
|
||||
<p>This document is an introduction to the Lemon
|
||||
parser generator.</p>
|
||||
|
||||
<h2>Security Note</h2>
|
||||
|
||||
<p>The language parser code created by Lemon is very robust and
|
||||
is well-suited for use in internet-facing applications that need to
|
||||
safely process maliciously crafted inputs.
|
||||
|
||||
<p>The "lemon.exe" command-line tool itself works great when given a valid
|
||||
input grammar file and almost always gives helpful
|
||||
error messages for malformed inputs. However, it is possible for
|
||||
a malicious user to craft a grammar file that will cause
|
||||
lemon.exe to crash.
|
||||
We do not see this as a problem, as lemon.exe is not intended to be used
|
||||
with hostile inputs.
|
||||
To summarize:</p>
|
||||
|
||||
<ul>
|
||||
<li>Parser code generated by lemon → Robust and secure
|
||||
<li>The "lemon.exe" command line tool itself → Not so much
|
||||
</ul>
|
||||
|
||||
<h2>Theory of Operation</h2>
|
||||
|
||||
<p>The main goal of Lemon is to translate a context free grammar (CFG)
|
||||
|
||||
@@ -171,10 +171,11 @@ static int fts5HashResize(Fts5Hash *pHash){
|
||||
|
||||
for(i=0; i<pHash->nSlot; i++){
|
||||
while( apOld[i] ){
|
||||
int iHash;
|
||||
unsigned int iHash;
|
||||
Fts5HashEntry *p = apOld[i];
|
||||
apOld[i] = p->pHashNext;
|
||||
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p), strlen(fts5EntryKey(p)));
|
||||
iHash = fts5HashKey(nNew, (u8*)fts5EntryKey(p),
|
||||
(int)strlen(fts5EntryKey(p)));
|
||||
p->pHashNext = apNew[iHash];
|
||||
apNew[iHash] = p;
|
||||
}
|
||||
@@ -477,7 +478,7 @@ int sqlite3Fts5HashQuery(
|
||||
int *pnDoclist /* OUT: Size of doclist in bytes */
|
||||
){
|
||||
unsigned int iHash = fts5HashKey(pHash->nSlot, (const u8*)pTerm, nTerm);
|
||||
char *zKey;
|
||||
char *zKey = 0;
|
||||
Fts5HashEntry *p;
|
||||
|
||||
for(p=pHash->aSlot[iHash]; p; p=p->pHashNext){
|
||||
|
||||
@@ -182,7 +182,7 @@ static int fts5tokConnectMethod(
|
||||
Fts5tokTable *pTab = 0;
|
||||
int rc;
|
||||
char **azDequote = 0;
|
||||
int nDequote;
|
||||
int nDequote = 0;
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(input HIDDEN, token, start, end, position)"
|
||||
|
||||
@@ -90,6 +90,7 @@ do_test 2.7 {
|
||||
execsql { SELECT rowid FROM tt('a') ORDER BY rank; } db
|
||||
} {1 3 2}
|
||||
|
||||
db2 close
|
||||
|
||||
#--------------------------------------------------------------------------
|
||||
# At one point there was a problem with queries such as:
|
||||
|
||||
@@ -1001,7 +1001,6 @@ static void amatchWriteCost(amatch_word *pWord){
|
||||
/* Circumvent compiler warnings about the use of strcpy() by supplying
|
||||
** our own implementation.
|
||||
*/
|
||||
#if defined(__OpenBSD__)
|
||||
static void amatchStrcpy(char *dest, const char *src){
|
||||
while( (*(dest++) = *(src++))!=0 ){}
|
||||
}
|
||||
@@ -1009,11 +1008,6 @@ static void amatchStrcat(char *dest, const char *src){
|
||||
while( *dest ) dest++;
|
||||
amatchStrcpy(dest, src);
|
||||
}
|
||||
#else
|
||||
# define amatchStrcpy strcpy
|
||||
# define amatchStrcat strcat
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** Add a new amatch_word object to the queue.
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@
|
||||
** The generate_series "function" is really a virtual table with the
|
||||
** following schema:
|
||||
**
|
||||
** CREATE FUNCTION generate_series(
|
||||
** CREATE TABLE generate_series(
|
||||
** value,
|
||||
** start HIDDEN,
|
||||
** stop HIDDEN,
|
||||
|
||||
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
** 2017-05-31
|
||||
**
|
||||
** 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 demonstrates an eponymous virtual table that returns information
|
||||
** about all prepared statements for the database connection.
|
||||
**
|
||||
** Usage example:
|
||||
**
|
||||
** .load ./stmts
|
||||
** .mode line
|
||||
** .header on
|
||||
** SELECT * FROM stmts;
|
||||
*/
|
||||
#include "sqlite3ext.h"
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
|
||||
/*
|
||||
** The following macros are used to cast pointers to integers.
|
||||
** The way you do this varies from one compiler
|
||||
** to the next, so we have developed the following set of #if statements
|
||||
** to generate appropriate macros for a wide range of compilers.
|
||||
*/
|
||||
#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC */
|
||||
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(__PTRDIFF_TYPE__)(X))
|
||||
#elif !defined(__GNUC__) /* Works for compilers other than LLVM */
|
||||
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(((char*)X)-(char*)0))
|
||||
#elif defined(HAVE_STDINT_H) /* Use this case if we have ANSI headers */
|
||||
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(intptr_t)(X))
|
||||
#else /* Generates a warning - but it always works */
|
||||
# define SQLITE_PTR_TO_INT64(X) ((sqlite3_int64)(X))
|
||||
#endif
|
||||
|
||||
|
||||
/* stmts_vtab is a subclass of sqlite3_vtab which will
|
||||
** serve as the underlying representation of a stmts virtual table
|
||||
*/
|
||||
typedef struct stmts_vtab stmts_vtab;
|
||||
struct stmts_vtab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this stmts vtab */
|
||||
};
|
||||
|
||||
/* stmts_cursor is a subclass of sqlite3_vtab_cursor which will
|
||||
** serve as the underlying representation of a cursor that scans
|
||||
** over rows of the result
|
||||
*/
|
||||
typedef struct stmts_cursor stmts_cursor;
|
||||
struct stmts_cursor {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3 *db; /* Database connection for this cursor */
|
||||
sqlite3_stmt *pStmt; /* Statement cursor is currently pointing at */
|
||||
sqlite3_int64 iRowid; /* The rowid */
|
||||
};
|
||||
|
||||
/*
|
||||
** The stmtsConnect() method is invoked to create a new
|
||||
** stmts_vtab that describes the generate_stmts virtual table.
|
||||
**
|
||||
** Think of this routine as the constructor for stmts_vtab objects.
|
||||
**
|
||||
** All this routine needs to do is:
|
||||
**
|
||||
** (1) Allocate the stmts_vtab object and initialize all fields.
|
||||
**
|
||||
** (2) Tell SQLite (via the sqlite3_declare_vtab() interface) what the
|
||||
** result set of queries against generate_stmts will look like.
|
||||
*/
|
||||
static int stmtsConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
stmts_vtab *pNew;
|
||||
int rc;
|
||||
|
||||
/* Column numbers */
|
||||
#define STMTS_COLUMN_PTR 0 /* Numeric value of the statement pointer */
|
||||
#define STMTS_COLUMN_SQL 1 /* SQL for the statement */
|
||||
#define STMTS_COLUMN_NCOL 2 /* Number of result columns */
|
||||
#define STMTS_COLUMN_RO 3 /* True if read-only */
|
||||
#define STMTS_COLUMN_BUSY 4 /* True if currently busy */
|
||||
#define STMTS_COLUMN_NSCAN 5 /* SQLITE_STMTSTATUS_FULLSCAN_STEP */
|
||||
#define STMTS_COLUMN_NSORT 6 /* SQLITE_STMTSTATUS_SORT */
|
||||
#define STMTS_COLUMN_NAIDX 7 /* SQLITE_STMTSTATUS_AUTOINDEX */
|
||||
#define STMTS_COLUMN_NSTEP 8 /* SQLITE_STMTSTATUS_VM_STEP */
|
||||
#define STMTS_COLUMN_MEM 9 /* SQLITE_STMTSTATUS_MEMUSED */
|
||||
|
||||
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(ptr,sql,ncol,ro,busy,nscan,nsort,naidx,nstep,mem)");
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
pNew->db = db;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is the destructor for stmts_cursor objects.
|
||||
*/
|
||||
static int stmtsDisconnect(sqlite3_vtab *pVtab){
|
||||
sqlite3_free(pVtab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Constructor for a new stmts_cursor object.
|
||||
*/
|
||||
static int stmtsOpen(sqlite3_vtab *p, sqlite3_vtab_cursor **ppCursor){
|
||||
stmts_cursor *pCur;
|
||||
pCur = sqlite3_malloc( sizeof(*pCur) );
|
||||
if( pCur==0 ) return SQLITE_NOMEM;
|
||||
memset(pCur, 0, sizeof(*pCur));
|
||||
pCur->db = ((stmts_vtab*)p)->db;
|
||||
*ppCursor = &pCur->base;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Destructor for a stmts_cursor.
|
||||
*/
|
||||
static int stmtsClose(sqlite3_vtab_cursor *cur){
|
||||
sqlite3_free(cur);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Advance a stmts_cursor to its next row of output.
|
||||
*/
|
||||
static int stmtsNext(sqlite3_vtab_cursor *cur){
|
||||
stmts_cursor *pCur = (stmts_cursor*)cur;
|
||||
pCur->iRowid++;
|
||||
pCur->pStmt = sqlite3_next_stmt(pCur->db, pCur->pStmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return values of columns for the row at which the stmts_cursor
|
||||
** is currently pointing.
|
||||
*/
|
||||
static int stmtsColumn(
|
||||
sqlite3_vtab_cursor *cur, /* The cursor */
|
||||
sqlite3_context *ctx, /* First argument to sqlite3_result_...() */
|
||||
int i /* Which column to return */
|
||||
){
|
||||
stmts_cursor *pCur = (stmts_cursor*)cur;
|
||||
switch( i ){
|
||||
case STMTS_COLUMN_PTR: {
|
||||
sqlite3_result_int64(ctx, SQLITE_PTR_TO_INT64(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
case STMTS_COLUMN_SQL: {
|
||||
sqlite3_result_text(ctx, sqlite3_sql(pCur->pStmt), -1, SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case STMTS_COLUMN_NCOL: {
|
||||
sqlite3_result_int(ctx, sqlite3_column_count(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
case STMTS_COLUMN_RO: {
|
||||
sqlite3_result_int(ctx, sqlite3_stmt_readonly(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
case STMTS_COLUMN_BUSY: {
|
||||
sqlite3_result_int(ctx, sqlite3_stmt_busy(pCur->pStmt));
|
||||
break;
|
||||
}
|
||||
case STMTS_COLUMN_NSCAN:
|
||||
case STMTS_COLUMN_NSORT:
|
||||
case STMTS_COLUMN_NAIDX:
|
||||
case STMTS_COLUMN_NSTEP:
|
||||
case STMTS_COLUMN_MEM: {
|
||||
sqlite3_result_int(ctx, sqlite3_stmt_status(pCur->pStmt,
|
||||
i-STMTS_COLUMN_NSCAN+SQLITE_STMTSTATUS_FULLSCAN_STEP, 0));
|
||||
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 stmtsRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
stmts_cursor *pCur = (stmts_cursor*)cur;
|
||||
*pRowid = pCur->iRowid;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return TRUE if the cursor has been moved off of the last
|
||||
** row of output.
|
||||
*/
|
||||
static int stmtsEof(sqlite3_vtab_cursor *cur){
|
||||
stmts_cursor *pCur = (stmts_cursor*)cur;
|
||||
return pCur->pStmt==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** This method is called to "rewind" the stmts_cursor object back
|
||||
** to the first row of output. This method is always called at least
|
||||
** once prior to any call to stmtsColumn() or stmtsRowid() or
|
||||
** stmtsEof().
|
||||
*/
|
||||
static int stmtsFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
stmts_cursor *pCur = (stmts_cursor *)pVtabCursor;
|
||||
pCur->pStmt = 0;
|
||||
pCur->iRowid = 0;
|
||||
return stmtsNext(pVtabCursor);
|
||||
}
|
||||
|
||||
/*
|
||||
** SQLite will invoke this method one or more times while planning a query
|
||||
** that uses the generate_stmts virtual table. This routine needs to create
|
||||
** a query plan for each invocation and compute an estimated cost for that
|
||||
** plan.
|
||||
*/
|
||||
static int stmtsBestIndex(
|
||||
sqlite3_vtab *tab,
|
||||
sqlite3_index_info *pIdxInfo
|
||||
){
|
||||
pIdxInfo->estimatedCost = (double)500;
|
||||
pIdxInfo->estimatedRows = 500;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** This following structure defines all the methods for the
|
||||
** generate_stmts virtual table.
|
||||
*/
|
||||
static sqlite3_module stmtsModule = {
|
||||
0, /* iVersion */
|
||||
0, /* xCreate */
|
||||
stmtsConnect, /* xConnect */
|
||||
stmtsBestIndex, /* xBestIndex */
|
||||
stmtsDisconnect, /* xDisconnect */
|
||||
0, /* xDestroy */
|
||||
stmtsOpen, /* xOpen - open a cursor */
|
||||
stmtsClose, /* xClose - close a cursor */
|
||||
stmtsFilter, /* xFilter - configure scan constraints */
|
||||
stmtsNext, /* xNext - advance a cursor */
|
||||
stmtsEof, /* xEof - check for end of scan */
|
||||
stmtsColumn, /* xColumn - read data */
|
||||
stmtsRowid, /* xRowid - read data */
|
||||
0, /* xUpdate */
|
||||
0, /* xBegin */
|
||||
0, /* xSync */
|
||||
0, /* xCommit */
|
||||
0, /* xRollback */
|
||||
0, /* xFindMethod */
|
||||
0, /* xRename */
|
||||
};
|
||||
|
||||
#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
int sqlite3_stmts_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( sqlite3_libversion_number()<3008012 ){
|
||||
*pzErrMsg = sqlite3_mprintf(
|
||||
"generate_stmts() requires SQLite 3.8.12 or later");
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
rc = sqlite3_create_module(db, "stmts", &stmtsModule, 0);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
@@ -298,6 +298,14 @@ do_test 2.1.2 {
|
||||
list [catch { rbu close } msg] $msg
|
||||
} {1 {SQLITE_ERROR - cannot vacuum wal mode database}}
|
||||
|
||||
do_test 2.1.3 {
|
||||
sqlite3rbu_vacuum rbu test.db state.db
|
||||
rbu step
|
||||
} {SQLITE_ERROR}
|
||||
do_test 2.1.4 {
|
||||
list [catch { rbu close_no_error } msg] $msg
|
||||
} {1 SQLITE_ERROR}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.2.0 {
|
||||
CREATE TABLE tx(a PRIMARY KEY, b BLOB);
|
||||
|
||||
@@ -3787,7 +3787,11 @@ int sqlite3rbu_close(sqlite3rbu *p, char **pzErrmsg){
|
||||
|
||||
rbuEditErrmsg(p);
|
||||
rc = p->rc;
|
||||
*pzErrmsg = p->zErrmsg;
|
||||
if( pzErrmsg ){
|
||||
*pzErrmsg = p->zErrmsg;
|
||||
}else{
|
||||
sqlite3_free(p->zErrmsg);
|
||||
}
|
||||
sqlite3_free(p->zState);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
|
||||
@@ -420,10 +420,10 @@ int sqlite3rbu_savestate(sqlite3rbu *pRbu);
|
||||
**
|
||||
** If an error has already occurred as part of an sqlite3rbu_step()
|
||||
** or sqlite3rbu_open() call, or if one occurs within this function, an
|
||||
** SQLite error code is returned. Additionally, *pzErrmsg may be set to
|
||||
** point to a buffer containing a utf-8 formatted English language error
|
||||
** message. It is the responsibility of the caller to eventually free any
|
||||
** such buffer using sqlite3_free().
|
||||
** SQLite error code is returned. Additionally, if pzErrmsg is not NULL,
|
||||
** *pzErrmsg may be set to point to a buffer containing a utf-8 formatted
|
||||
** English language error message. It is the responsibility of the caller to
|
||||
** eventually free any such buffer using sqlite3_free().
|
||||
**
|
||||
** Otherwise, if no error occurs, this function returns SQLITE_OK if the
|
||||
** update has been partially applied, or SQLITE_DONE if it has been
|
||||
|
||||
+7
-1
@@ -78,6 +78,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
|
||||
{"db", 3, "RBU"}, /* 6 */
|
||||
{"state", 2, ""}, /* 7 */
|
||||
{"progress", 2, ""}, /* 8 */
|
||||
{"close_no_error", 2, ""}, /* 9 */
|
||||
{0,0,0}
|
||||
};
|
||||
int iCmd;
|
||||
@@ -102,11 +103,16 @@ static int SQLITE_TCLAPI test_sqlite3rbu_cmd(
|
||||
break;
|
||||
}
|
||||
|
||||
case 9: /* close_no_error */
|
||||
case 1: /* close */ {
|
||||
char *zErrmsg = 0;
|
||||
int rc;
|
||||
Tcl_DeleteCommand(interp, Tcl_GetString(objv[0]));
|
||||
rc = sqlite3rbu_close(pRbu, &zErrmsg);
|
||||
if( iCmd==1 ){
|
||||
rc = sqlite3rbu_close(pRbu, &zErrmsg);
|
||||
}else{
|
||||
rc = sqlite3rbu_close(pRbu, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK || rc==SQLITE_DONE ){
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
assert( zErrmsg==0 );
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
# 2015-07-31
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests for the [sqldiff --changeset] command.
|
||||
#
|
||||
#
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
set testprefix sessiondiff
|
||||
|
||||
set PROG [test_find_sqldiff]
|
||||
db close
|
||||
|
||||
proc sqlesc {id} {
|
||||
set ret "'[string map {' ''} $id]'"
|
||||
set ret
|
||||
}
|
||||
|
||||
proc database_cksum {db1} {
|
||||
set txt ""
|
||||
|
||||
sqlite3 dbtmp $db1
|
||||
foreach tbl [dbtmp eval {SELECT name FROM sqlite_master WHERE type='table'}] {
|
||||
set cols [list]
|
||||
dbtmp eval "PRAGMA table_info = [sqlesc $tbl]" {
|
||||
lappend cols "quote( $name )"
|
||||
}
|
||||
append txt [dbtmp eval \
|
||||
"SELECT [join $cols {||'.'||}] FROM [sqlesc $tbl] ORDER BY 1"
|
||||
]
|
||||
}
|
||||
dbtmp close
|
||||
|
||||
md5 $txt
|
||||
}
|
||||
|
||||
proc readfile {filename} {
|
||||
set fd [open $filename]
|
||||
fconfigure $fd -translation binary -encoding binary
|
||||
set data [read $fd]
|
||||
close $fd
|
||||
set data
|
||||
}
|
||||
|
||||
proc get_changeset {db1 db2} {
|
||||
exec $::PROG --changeset changeset.bin $db1 $db2
|
||||
set bin [readfile changeset.bin]
|
||||
return $bin
|
||||
}
|
||||
|
||||
proc xConflict {args} {
|
||||
return ""
|
||||
}
|
||||
|
||||
proc do_changeset_test {tn sql1 sql2} {
|
||||
forcedelete test.db123 test.db124
|
||||
|
||||
sqlite3 db test.db123
|
||||
db eval $sql1
|
||||
db close
|
||||
|
||||
sqlite3 db test.db124
|
||||
db eval $sql2
|
||||
|
||||
set cs [get_changeset test.db124 test.db123]
|
||||
sqlite3changeset_apply db $cs xConflict
|
||||
db close
|
||||
|
||||
set database_cksum1 [database_cksum test.db123]
|
||||
set database_cksum2 [database_cksum test.db124]
|
||||
|
||||
uplevel [list \
|
||||
do_test $tn [list string compare $database_cksum1 $database_cksum2] 0
|
||||
]
|
||||
}
|
||||
|
||||
do_changeset_test 1.0 {
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
} {
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
}
|
||||
|
||||
do_changeset_test 1.1 {
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
CREATE TABLE t2(x PRIMARY KEY, y);
|
||||
INSERT INTO t2 VALUES(1, 2);
|
||||
} {
|
||||
CREATE TABLE t1(x PRIMARY KEY);
|
||||
CREATE TABLE t2(x PRIMARY KEY, y);
|
||||
INSERT INTO t2 VALUES(3, 4);
|
||||
}
|
||||
|
||||
do_changeset_test 1.2 {
|
||||
CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
|
||||
INSERT INTO t2 VALUES(1, 2, 3);
|
||||
INSERT INTO t2 VALUES(4, 5, 6);
|
||||
} {
|
||||
CREATE TABLE t2(a, b, c, PRIMARY KEY(b, c));
|
||||
INSERT INTO t2 VALUES(1, 2, 11);
|
||||
INSERT INTO t2 VALUES(7, 8, 9);
|
||||
}
|
||||
|
||||
finish_test
|
||||
@@ -2836,11 +2836,12 @@ static int sessionChangesetNext(
|
||||
p->in.iCurrent = p->in.iNext;
|
||||
|
||||
op = p->in.aData[p->in.iNext++];
|
||||
if( op=='T' || op=='P' ){
|
||||
while( op=='T' || op=='P' ){
|
||||
p->bPatchset = (op=='P');
|
||||
if( sessionChangesetReadTblhdr(p) ) return p->rc;
|
||||
if( (p->rc = sessionInputBuffer(&p->in, 2)) ) return p->rc;
|
||||
p->in.iCurrent = p->in.iNext;
|
||||
if( p->in.iNext>=p->in.nData ) return SQLITE_DONE;
|
||||
op = p->in.aData[p->in.iNext++];
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
C Version\s3.19.1
|
||||
D 2017-05-24T13:08:33.856
|
||||
C Ensure\sthat\sthe\svalue\sof\sthe\sTHREADSAFE\ssymbol\sis\salways\sincluded\swhen\nreporting\scompile\stime\soptions,\seven\sif\sit\swas\snot\sexplicitly\sconfigured.
|
||||
D 2017-06-17T17:29:24.923
|
||||
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc
|
||||
F README.md 2b15fae33852f2f53996774c21fb41e1d94181c4401a0e43ac93e11f2cc901b9
|
||||
F VERSION 1699c6ade55970f0e2ab64ef0aa90ff406db479796172c8676e0899704f5dbe8
|
||||
F VERSION 87f1498f27e398bce3da2fa8125c9879a38ed9d87e4b5fb922b351de1e25cadb
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am ed95854f5df64c1d0a447d8ecb55edc67e3c32f79f597c3a4870f9ac51698275
|
||||
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
|
||||
F autoconf/Makefile.msc 1014be616b420a5f48611d21b62ca2f50ec97ee795087ecb8a4d6bf6375ba11d
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
@@ -30,10 +30,10 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
|
||||
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
|
||||
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
|
||||
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure a02beb39087ff63175fa1da1172c90db8c27b9cecf24639cd7438c1f3596163f x
|
||||
F configure.ac 901e8db2c211e8b655e51ee24f2b8faa33407acde87effc47f70380f3b04e452
|
||||
F configure 1bcc61cdd063171d8945551c265e5701a770deeff77e0ad634f8d22e4e91c831 x
|
||||
F configure.ac 13f45f02e6c51dd0e347315b5401c3f047712b7f79b7f35619115c23755afcff
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
|
||||
F doc/lemon.html 1f8b8d4c9f5cfe40e679fee279cc9eb2da8e6eb74ad406028538d7864cc4b6cb
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
@@ -104,13 +104,13 @@ F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
|
||||
F ext/fts5/fts5_buffer.c 1dd1ec0446b3acfc2d7d407eb894762a461613e2695273f48e449bfd13e973ff
|
||||
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
|
||||
F ext/fts5/fts5_expr.c f2825f714d91bbe62ab5820aee9ad12e0c94205b2a01725eaa9072415ae9ff1c
|
||||
F ext/fts5/fts5_hash.c 534d5591f479c0999543689122ad6952823bc7c85273a0ff4f7f91d9f914a54b
|
||||
F ext/fts5/fts5_hash.c 32be400cf761868c9db33efe81a06eb19a17c5402ad477ee9efb51301546dd55
|
||||
F ext/fts5/fts5_index.c cdceac47287c66500214ee946ca871ac48027a82a0ca82177c1c6af19f181ca0
|
||||
F ext/fts5/fts5_main.c 1ba0e7806886c1bc16e20d0dde1c2b535d1aeb98cbbb937c4c3e064af5ac6f03
|
||||
F ext/fts5/fts5_storage.c 7750986004f3f0c94619a85ecb5dd6cbef53e5e3853488e8a906c269d4d11db6
|
||||
F ext/fts5/fts5_tcl.c 4a901f00c8553740dba63511603f5527d741c26a
|
||||
F ext/fts5/fts5_test_mi.c 783b86697ebf773c18fc109992426c0173a055bc
|
||||
F ext/fts5/fts5_test_tok.c f4c27f2e3200653a458f5316f6aaa863f7532d98fff7534ece3670fb7f2c196b
|
||||
F ext/fts5/fts5_test_tok.c ffd657dd67e7fcdb31bf63fb60b6d867299a581d0f46e97086abacd66c2a9b26
|
||||
F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
|
||||
F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
|
||||
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
|
||||
@@ -181,7 +181,7 @@ F ext/fts5/test/fts5porter.test 7cdc07bef301d70eebbfa75dcaf45c3680e1d0e1
|
||||
F ext/fts5/test/fts5porter2.test 2e65633d58a1c525d5af0f6c01e5a59155bb3487
|
||||
F ext/fts5/test/fts5prefix.test 6ef7e875738412907b17687d25db39a25cbdaba4
|
||||
F ext/fts5/test/fts5query.test f5ec25f5f2fbb70033424113cdffc101b1985a40
|
||||
F ext/fts5/test/fts5rank.test 2bdc0c5f22ccc1f9dbe9f4d0b82a491dce6f8a32
|
||||
F ext/fts5/test/fts5rank.test 485e1d7ab8b0f939172a88e279acd0894b1f64458f92d7cd5826a31335c6a093
|
||||
F ext/fts5/test/fts5rebuild.test 03935f617ace91ed23a6099c7c74d905227ff29b
|
||||
F ext/fts5/test/fts5restart.test c17728fdea26e7d0f617d22ad5b4b2862b994c17
|
||||
F ext/fts5/test/fts5rowid.test 16908a99d6efc9ba21081b4f2b86b3fc699839a6
|
||||
@@ -209,7 +209,7 @@ F ext/icu/README.txt d9fbbad0c2f647c3fdf715fc9fd64af53aedfc43
|
||||
F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
|
||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
|
||||
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
|
||||
F ext/misc/amatch.c 6db4607cb17c54b853a2d7c7c36046d004853f65b9b733e6f019d543d5dfae87
|
||||
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
@@ -228,11 +228,12 @@ F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
|
||||
F ext/misc/remember.c 8440f8d0b452c5cdefb62b57135ccd1267aa729d
|
||||
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
|
||||
F ext/misc/scrub.c 1c5bfb8b0cd18b602fcb55755e84abf0023ac2fb
|
||||
F ext/misc/series.c e11e534ada797d5b816d7e7a93c022306563ca35
|
||||
F ext/misc/series.c b0f5f346aca9b7ff7caaf0da2efb4ad462441abd4dcd92a460cb573b3ea2370b
|
||||
F ext/misc/sha1.c 0b9e9b855354910d3ca467bf39099d570e73db56
|
||||
F ext/misc/shathree.c fa185d7aee0ad0aca5e091b4a2db7baff11796170e5793b5de99e511a13af448
|
||||
F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c a4723b6aff748a417b5091b68a46443265c40f0d
|
||||
F ext/misc/stmts.c 4aa554f671f6a55a52060437a0215a93d2e9f10f2fa66b0f7f65aa0576fc90bb
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
F ext/misc/vfsstat.c bf10ef0bc51e1ad6756629e1edb142f7a8db1178
|
||||
@@ -267,11 +268,11 @@ F ext/rbu/rbufts.test 828cd689da825f0a7b7c53ffc1f6f7fdb6fa5bda
|
||||
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
|
||||
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
|
||||
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
|
||||
F ext/rbu/rbuvacuum.test 4a977447c15c2581ab668781d9ef4294382530e0
|
||||
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
|
||||
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
|
||||
F ext/rbu/sqlite3rbu.c 2a89efba9eeba8e6c89a498dc195e8efbdde2694
|
||||
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
|
||||
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
|
||||
F ext/rbu/sqlite3rbu.c d1438580a451eebda3bfd42ef69b677512f00125285e0e4e789b6131a45f6dd8
|
||||
F ext/rbu/sqlite3rbu.h fc25e1fcd99b5c6d32b1b5b1c73122632e873ac89bd0be9bf646db362b7ce02c
|
||||
F ext/rbu/test_rbu.c ec18cfc69a104309df23c359e3c80306c9a6bdd1d2c53c8b70ae158e9832dcd6
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 8205d6e4466f766e57ce1b8aa38224ac9e1cec2d2bf4684cd1cc5a6ddf9b7014
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
@@ -315,10 +316,11 @@ F ext/session/sessionG.test 01ef705096a9d3984eebdcca79807a211dee1b60
|
||||
F ext/session/session_common.tcl 7776eda579773113b30c7abfd4545c445228cb73
|
||||
F ext/session/session_speed_test.c edc1f96fd5e0e4b16eb03e2a73041013d59e8723
|
||||
F ext/session/sessionat.test b25d61d663ebc795506bf74079dc4ba0092fad25
|
||||
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
|
||||
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
|
||||
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
|
||||
F ext/session/sessionwor.test 2f3744236dc8b170a695b7d8ddc8c743c7e79fdc
|
||||
F ext/session/sqlite3session.c 13642d9c754cc18f17e141f82860d269e2adf920
|
||||
F ext/session/sqlite3session.c cc127222a9ea6f4eaa31281aa9da924f5244f6099be0ee526c950684fb3513a6
|
||||
F ext/session/sqlite3session.h d4db650adfcc7a4360e9f12a09c2d117b1db6b53
|
||||
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
|
||||
F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
@@ -341,22 +343,22 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
|
||||
F src/analyze.c 0d0ccf7520a201d8747ea2f02c92c26e26f801bc161f714f27b9f7630dde0421
|
||||
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
|
||||
F src/attach.c 3bd555e28382603e80d430dfebb2270f86e1e375b4c4be3e1ab1aec3a0c44943
|
||||
F src/auth.c 79f96c6f33bf0e5da8d1c282cee5ebb1852bb8a6ccca3e485d7c459b035d9c3c
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
||||
F src/btree.c 8c1fd4cfa2b0bf021386e0a1f4e30b64eea7a2c1bc2e0c3e5901a626b1ab6aa9
|
||||
F src/btree.h 80f518c0788be6cec8d9f8e13bd8e380df299d2b5e4ac340dc887b0642647cfc
|
||||
F src/btree.c 430e34151e6ef37e42d3f956bb062907c80ff91e1380704b967b8c1a02a98f64
|
||||
F src/btree.h 3edc5329bc59534d2d15b4f069a9f54b779a7e51289e98fa481ae3c0e526a5ca
|
||||
F src/btreeInt.h a392d353104b4add58b4a59cb185f5d5693dde832c565b77d8d4c343ed98f610
|
||||
F src/build.c 4026a9c554b233e50c5e9ad46963e676cf54dd2306d952aa1eaa07a1bc9ce14f
|
||||
F src/build.c 88a8cdc11d1c081ed565aa3e795bdf9160f4556463b4c4555e9860b59dd80340
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c
|
||||
F src/ctime.c ce45bd3078346f08f04d87ad4cb04af573490c46ca5c55a23a45166589542a6f
|
||||
F src/date.c cc42a41c7422389860d40419a5e3bce5eaf6e7835c3ba2677751dc653550a5c7
|
||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||
F src/delete.c 665e705641e5815c3f32d05820d1a5aa630274e568af73f377fdbc614fcf40b4
|
||||
F src/expr.c c83f799f3e5e3f3863bd0716119383e4a062d00a1e34e7273a78555918840a7c
|
||||
F src/delete.c 3213547e97b676c6fa79948b7a9ede4801ea04a01a2043241deafedf132ecf5d
|
||||
F src/expr.c 452c6f3aa656aabf3eefe96bb5f316b2c987fbc12c647964e4ed880f193ca31f
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c db65492ae549c3b548c9ef1f279ce1684f1c473b116e1c56a90878cd5dcf968d
|
||||
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
|
||||
@@ -365,10 +367,10 @@ F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c d4bb3a135948553d18cf992f76f7ed7b18aa0327f250607b5a6671e55d9947d5
|
||||
F src/insert.c 974499a3999d339a4c1ba8ef129a988d9f136b3789e423808b38cdc19d28adbe
|
||||
F src/legacy.c e88ed13c2d531decde75d42c2e35623fb9ce3cb0
|
||||
F src/loadext.c a72909474dadce771d3669bf84bf689424f6f87d471fee898589c3ef9b2acfd9
|
||||
F src/main.c a56577fa6407fb49650c1fd27bf828cd9b55126716b1f766a03c9c2cb42b43a0
|
||||
F src/main.c 18f2145d572069dae91161add89446aec680aab296492a92ae5afcc2fc7c6b5a
|
||||
F src/malloc.c e20bb2b48abec52d3faf01cce12e8b4f95973755fafec98d45162dfdab111978
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -390,32 +392,32 @@ F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
|
||||
F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 80893c0860199aebc6efa4f102ab11eebde338b7fdbb0c04d4b04647c2fd62d1
|
||||
F src/pager.c 14f6982c470c05b8e85575c69e9c1712010602e20400f8670d8699e21283e0e4
|
||||
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
|
||||
F src/parse.y 0513387ce02fea97897d8caef82d45f347818593f24f1bdc48e0c530a8af122d
|
||||
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
|
||||
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
|
||||
F src/pcache.h 521bb9610d38ef17a3cc9b5ddafd4546c2ea67fa3d0e464823d73c2a28d50e11
|
||||
F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
|
||||
F src/pragma.c 2362670a9d28b71708aecb2b9b10b3f7be71f4c950961c07e81dc400e3ce6371
|
||||
F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921
|
||||
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
|
||||
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
|
||||
F src/resolve.c adf3ef9843135b1383321ad751f16f5a40c3f37925154555a3e61653d2a954e8
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 9db6887514a663ef4eb117f12cbae613bece9267f180d0fcdfa49402b013483e
|
||||
F src/shell.c a37d96b20b3644d0eb905df5aa7a0fcf9f6e73c15898337230c760a24a8df794
|
||||
F src/sqlite.h.in 8dd468837a4f6d76713e3a4cc65bea48095009038593d41040ab46c1b351197f
|
||||
F src/select.c 0d2afdbdba5fbc61432c5454a35e0236e7aa4aa3756986a7d51b81a508e8083a
|
||||
F src/shell.c bcd3358ad6cb3f3dc7ec76ad3bd8191f123ed2425360c5c48fe431780eceb729
|
||||
F src/sqlite.h.in 67fa8bd29808e7988e0ce36c8d4c6043eb1727f94522fc612687aa5af51931e6
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
|
||||
F src/sqliteInt.h aea3aa1b81e0d07d5b1c39b8c5a54a1dc5e4f10136cb63da392aef9eb2a5108b
|
||||
F src/sqliteInt.h 17e9bce594ea0c38c44ad0cbff4aa50cbff4b25f4bac9d38306caf9f1f028ac9
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c c8cf60d0c5411d5e70e7c136470d29dbe760d250f55198b71682c67086524e4a
|
||||
F src/test1.c c99f0442918a7a5d5b68a95d6024c211989e6c782c15ced5a558994baaf76a5e
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
|
||||
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
|
||||
F src/test6.c 004ad42f121f693b8cbe060d1a330678abc61620
|
||||
@@ -432,7 +434,7 @@ F src/test_config.c edcba290248dc18736dd814c9b95863c6762e0b35753048d8cbe5bf65f7a
|
||||
F src/test_delete.c e2fe07646dff6300b48d49b2fee2fe192ed389e834dd635e3b3bac0ce0bf9f8f
|
||||
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
||||
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
|
||||
F src/test_fs.c e16cbe68d3b107e00a907c20a9a02629870eb69b
|
||||
F src/test_fs.c 35a2f7dd8a915900873386331386d9ba1ae1b5026d74fd20c2807bc76221f291
|
||||
F src/test_func.c a4fdab3363b436c1b12660e9362ce3f3782b7b5e
|
||||
F src/test_hexio.c 1d4469ca61ab202a1fcec6543f584d2407205e8d
|
||||
F src/test_init.c 4413c211a94b62157ca4c145b3f27c497f03c664
|
||||
@@ -465,29 +467,29 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
|
||||
F src/treeview.c 6cf8d7fe9e63fae57dad1bb57f6615e14eac0c527e43d868e805042cae8ed1f7
|
||||
F src/trigger.c c9f0810043b265724fdb1bdd466894f984dfc182
|
||||
F src/trigger.c d1cae560bfacc8bfb3a072d73658245c1714c0389097da69b4cb23877a082d7e
|
||||
F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
|
||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c fc081ec6f63448dcd80d3dfad35baecfa104823254a815b081a4d9fe76e1db23
|
||||
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
|
||||
F src/vdbe.c 70f1c27d3de7b3ea68d3ee2b7fbf407335b66f7483eb321201ffe53724f9c54e
|
||||
F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848
|
||||
F src/vdbeInt.h 1ecdacc1322fdd3241ec30c32a480e328a6f864e532dc53fae8e0ab68121aebf
|
||||
F src/vdbeapi.c dc904b3c5e459727993c2421e653e29d63223846d129fae98adc782b0a996481
|
||||
F src/vdbeaux.c 01dcf59b2a96bd3cc9db8c0d7f266518d113587459a2b3316279c4f9c90f28a9
|
||||
F src/vacuum.c 874c0f2f15ab2908748297d587d22d485ea96d55aaec91d4775dddb2e24d2ecf
|
||||
F src/vdbe.c 6783778df820f3e0c68289fe5d12ddd34168b0eb1acf248668fec6e2ea1012d5
|
||||
F src/vdbe.h 70a409d171d4e51b962f0d53abf15c33c404c6aa4c9d62fb3a931b5a62ba9615
|
||||
F src/vdbeInt.h cdcdabad4f5d6bf7a3beb826a7f33ee6f8f1cb220042bedd5b7d4bf2ea1d179f
|
||||
F src/vdbeapi.c c961d8d9e0f52e2df60a6ddbbccd7d99dc4d00103db7e53f77fcef44fbd23178
|
||||
F src/vdbeaux.c bc9b3228f6d99bef0d0ecaf3a0e0e8358b3873242d0d2fe944226de3fdf9521e
|
||||
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
|
||||
F src/vdbemem.c 2c70f8f5de6c71fb99a22c5b83be9fab5c47cdd8e279fa44a8c00cfed06d7e89
|
||||
F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c
|
||||
F src/vdbemem.c 94b17d851f31d4fd075d47d373d4b33ed3962a6ecb82cf385018025751091360
|
||||
F src/vdbesort.c f512c68d0bf7e0105316a5594c4329358c8ee9cae3b25138df041d97516c0372
|
||||
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
||||
F src/vtab.c 35b9bdc2b41de32a417141d12097bcc4e29a77ed7cdb8f836d1d2305d946b61b
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
||||
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
||||
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
|
||||
F src/where.c c6352f15be5031907c68bcbde96cad1a6da20e9f4051d10168a59235de9a8566
|
||||
F src/walker.c d46044e7a5842560dfe7122d93ff5145dd4a96f4d0bf5ba5910a7731b8c01e79
|
||||
F src/where.c aa213e1b1c29eb8946a9f25108a18666a745ae5bac41b58d0be98730937a7785
|
||||
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
|
||||
F src/wherecode.c 8ad48867660519e262a401720845dc76934f86f558ec9606335fafcd7a2554f8
|
||||
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
|
||||
F src/wherecode.c 339ee802d9d311acf0cba8b5a9a092e167ef71c3a777d4b3e57de25d193251c7
|
||||
F src/whereexpr.c a2fe3811d45af45a5c6667caabc15e01054fe6228c64e86e1f7d2ba5ef5284f9
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -537,7 +539,7 @@ F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
|
||||
F test/autovacuum.test 92c24eedbdb68e49f3fb71f26f9ce6d8988cac15
|
||||
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
|
||||
F test/backcompat.test 3e64cedda754c778ef6bbe417b6e7a295e662a4d
|
||||
@@ -643,7 +645,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/csv01.test e0ba3caaa57e4c667a0b45977689fb8082f14348
|
||||
F test/ctime.test ff6c38e822459d6ca743c34901caf57740b08b54
|
||||
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
|
||||
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
|
||||
F test/cursorhint2.test 8457e93d97f665f23f97cdbc8477d16e3480331b
|
||||
F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
|
||||
@@ -827,7 +829,7 @@ F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
|
||||
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
|
||||
F test/fts4onepass.test 7319d61a2ed1325fc54afd0c060a0513b462303a
|
||||
F test/fts4opt.test fd6a11684b965e1999564ae763797b7fb9e34c96
|
||||
F test/fts4unicode.test 27378af76394542cf490cf001d8d1505fe55f6a9
|
||||
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
|
||||
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
|
||||
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
|
||||
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
|
||||
@@ -906,7 +908,7 @@ F test/ioerr3.test d3cec5e1a11ad6d27527d0d38573fbff14c71bdd
|
||||
F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
|
||||
F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/join.test a26e4c45edba5d2090216be6fc26d8d862c1a66e5729ce38308b4f286aa745e5
|
||||
F test/join.test 302f164f4a41c240d16ebd780762834233be77b852f15232c9a48a6fe37ac0fa
|
||||
F test/join2.test a48f723c5692e2cbb23a9297ac2720cb77d51a70
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
@@ -923,7 +925,7 @@ F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb2848
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
F test/keyword1.test 37ef6bba5d2ed5b07ecdd6810571de2956599dff
|
||||
F test/kvtest.c b9a9822dda05a1aa481215a52e2fc93cd8b22ee5
|
||||
F test/kvtest.c d2b8cfc91047ebf6cac4f3a04f19c3a864e4ecfd683bbb65c395df450b8dc79c
|
||||
F test/lastinsert.test 42e948fd6442f07d60acbd15d33fb86473e0ef63
|
||||
F test/laststmtchanges.test ae613f53819206b3222771828d024154d51db200
|
||||
F test/like.test 0603f4fa0dad50987f70032c05800cbfa8985302
|
||||
@@ -1059,7 +1061,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl cb06c4df0de4872e65b178316f8a87ccf7624d59 x
|
||||
F test/releasetest.tcl 7bb585433ce7fb2a2c255ae4b5e24f1bc27fe177ec1120f886cc4852f48f5ee9 x
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
|
||||
@@ -1414,7 +1416,7 @@ F test/vtabC.test 4528f459a13136f982e75614d120aef165f17292
|
||||
F test/vtabD.test 05b3f1d77117271671089e48719524b676842e96
|
||||
F test/vtabE.test d5024aa42754962f6bb0afd261681686488e7afe
|
||||
F test/vtabF.test 1918844c7c902f6a16c8dacf1ec8f84886d6e78b
|
||||
F test/vtabH.test 5f9253eb9e41ba9fe94f4aa3e9230191893d7764
|
||||
F test/vtabH.test 26d54e8b5407f797638b787a55f9c88323850a58dd142de02d06b9a1159bd283
|
||||
F test/vtabI.test 751b07636700dbdea328e4265b6077ccd6811a3f
|
||||
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
|
||||
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
|
||||
@@ -1476,7 +1478,7 @@ F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/with1.test cef099a491eac9874f2c28bd2dc86394fb3e47b3
|
||||
F test/with1.test 732e3ef398dcecb609839cd5ef0cb63beb2a9eff31420f3b745fc55b9e85b61e
|
||||
F test/with2.test 2b40da883658eb74ad8ad06afabe11a408e7fb87
|
||||
F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6
|
||||
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
|
||||
@@ -1512,7 +1514,8 @@ F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
|
||||
F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/mkautoconfamal.sh ab527af92dc684028e0d1db3fa6241787fae78987b99e5bbac7eb87e1970b8e5
|
||||
F tool/mkautoconfamal.sh e855df211ecbcc7131dee817110ff386cfb112f7
|
||||
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
|
||||
F tool/mkkeywordhash.c f7f3b342211ac6a14258b9726d5b97cf4f548f22
|
||||
F tool/mkmsvcmin.tcl cbd93f1cfa3a0a9ae56fc958510aa3fc3ac65e29cb111716199e3d0e66eefaa4
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
@@ -1521,7 +1524,7 @@ F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl 32bb40741df11bddc8451de9ea4d130e7b4476d8064794b1cf402ac110840fba
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
|
||||
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
|
||||
F tool/mksqlite3c.tcl 226da6d794d7d43a31e159a6fa89db867bf1f5eafe4b37d031222287ef8dbadc
|
||||
F tool/mksqlite3h.tcl 51bd5e7e840a920388a5966c9f2ccc618f434c57bd68c1bab4085b2553e1e237
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl b9e0777a213c23156b6542842c238479e496ebf5
|
||||
@@ -1539,7 +1542,7 @@ F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
|
||||
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
|
||||
F tool/spaceanal.tcl f40dc82b4d5e39d040a02a3ec38268e324068815e4292a15ffa30ee93208bbfd
|
||||
F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
@@ -1547,7 +1550,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c 3fb48a6c6669d2d2c59a7f072a410dd2583579b4
|
||||
F tool/sqldiff.c 30879bbc8de686df4624e86adce2d8981f500904c1cfb55b5d1eea2ffd9341eb
|
||||
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
@@ -1580,10 +1583,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 05ada741554b9fd00befcf7b4083637f53de68699ae5210ac18e0773ad1a9910
|
||||
R 7de9199234b8233f96ae8f86cad0d9b4
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.19.1 *
|
||||
U drh
|
||||
Z 01699a882c84539aef9719d24b44a477
|
||||
P bc1951d699e6eeacbe15776a37cd0f5cf3f09eb85d3ae01cff43293cb286fcd7
|
||||
R 45624ce11a236a8a994baa28885733aa
|
||||
U dan
|
||||
Z 71fa8cc8dcaaff976fb71d5480f74630
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
f6d7b988f40217821a382bc298180e9e6794f3ed79a83c6ef5cae048989b3f86
|
||||
95141c642697dc037e57f9e4992ff3460155995d3caef6259235601ee722cb93
|
||||
+16
-15
@@ -69,7 +69,8 @@ static void attachFunc(
|
||||
char *zPath = 0;
|
||||
char *zErr = 0;
|
||||
unsigned int flags;
|
||||
Db *aNew;
|
||||
Db *aNew; /* New array of Db pointers */
|
||||
Db *pNew; /* Db object for the newly attached database */
|
||||
char *zErrDyn = 0;
|
||||
sqlite3_vfs *pVfs;
|
||||
|
||||
@@ -117,8 +118,8 @@ static void attachFunc(
|
||||
if( aNew==0 ) return;
|
||||
}
|
||||
db->aDb = aNew;
|
||||
aNew = &db->aDb[db->nDb];
|
||||
memset(aNew, 0, sizeof(*aNew));
|
||||
pNew = &db->aDb[db->nDb];
|
||||
memset(pNew, 0, sizeof(*pNew));
|
||||
|
||||
/* Open the database file. If the btree is successfully opened, use
|
||||
** it to obtain the database schema. At this point the schema may
|
||||
@@ -134,7 +135,7 @@ static void attachFunc(
|
||||
}
|
||||
assert( pVfs );
|
||||
flags |= SQLITE_OPEN_MAIN_DB;
|
||||
rc = sqlite3BtreeOpen(pVfs, zPath, db, &aNew->pBt, 0, flags);
|
||||
rc = sqlite3BtreeOpen(pVfs, zPath, db, &pNew->pBt, 0, flags);
|
||||
sqlite3_free( zPath );
|
||||
db->nDb++;
|
||||
db->skipBtreeMutex = 0;
|
||||
@@ -143,28 +144,28 @@ static void attachFunc(
|
||||
zErrDyn = sqlite3MPrintf(db, "database is already attached");
|
||||
}else if( rc==SQLITE_OK ){
|
||||
Pager *pPager;
|
||||
aNew->pSchema = sqlite3SchemaGet(db, aNew->pBt);
|
||||
if( !aNew->pSchema ){
|
||||
pNew->pSchema = sqlite3SchemaGet(db, pNew->pBt);
|
||||
if( !pNew->pSchema ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}else if( aNew->pSchema->file_format && aNew->pSchema->enc!=ENC(db) ){
|
||||
}else if( pNew->pSchema->file_format && pNew->pSchema->enc!=ENC(db) ){
|
||||
zErrDyn = sqlite3MPrintf(db,
|
||||
"attached databases must use the same text encoding as main database");
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3BtreeEnter(aNew->pBt);
|
||||
pPager = sqlite3BtreePager(aNew->pBt);
|
||||
sqlite3BtreeEnter(pNew->pBt);
|
||||
pPager = sqlite3BtreePager(pNew->pBt);
|
||||
sqlite3PagerLockingMode(pPager, db->dfltLockMode);
|
||||
sqlite3BtreeSecureDelete(aNew->pBt,
|
||||
sqlite3BtreeSecureDelete(pNew->pBt,
|
||||
sqlite3BtreeSecureDelete(db->aDb[0].pBt,-1) );
|
||||
#ifndef SQLITE_OMIT_PAGER_PRAGMAS
|
||||
sqlite3BtreeSetPagerFlags(aNew->pBt,
|
||||
sqlite3BtreeSetPagerFlags(pNew->pBt,
|
||||
PAGER_SYNCHRONOUS_FULL | (db->flags & PAGER_FLAGS_MASK));
|
||||
#endif
|
||||
sqlite3BtreeLeave(aNew->pBt);
|
||||
sqlite3BtreeLeave(pNew->pBt);
|
||||
}
|
||||
aNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
|
||||
aNew->zDbSName = sqlite3DbStrDup(db, zName);
|
||||
if( rc==SQLITE_OK && aNew->zDbSName==0 ){
|
||||
pNew->safety_level = SQLITE_DEFAULT_SYNCHRONOUS+1;
|
||||
pNew->zDbSName = sqlite3DbStrDup(db, zName);
|
||||
if( rc==SQLITE_OK && pNew->zDbSName==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
|
||||
+215
-210
@@ -771,7 +771,7 @@ static int btreeMoveto(
|
||||
if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT;
|
||||
sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey);
|
||||
if( pIdxKey->nField==0 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
|
||||
goto moveto_done;
|
||||
}
|
||||
}else{
|
||||
@@ -1000,7 +1000,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){
|
||||
if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]);
|
||||
|
||||
sqlite3PagerUnref(pDbPage);
|
||||
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT;
|
||||
if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1385,7 +1385,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
|
||||
int sz = get2byte(&data[iFree+2]);
|
||||
int top = get2byte(&data[hdr+5]);
|
||||
if( iFree2 ){
|
||||
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT;
|
||||
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
sz2 = get2byte(&data[iFree2+2]);
|
||||
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
|
||||
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
|
||||
@@ -1416,13 +1416,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
|
||||
** if PRAGMA cell_size_check=ON.
|
||||
*/
|
||||
if( pc<iCellFirst || pc>iCellLast ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
assert( pc>=iCellFirst && pc<=iCellLast );
|
||||
size = pPage->xCellSize(pPage, &src[pc]);
|
||||
cbrk -= size;
|
||||
if( cbrk<iCellFirst || pc+size>usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
assert( cbrk+size<=usableSize && cbrk>=iCellFirst );
|
||||
testcase( cbrk+size==usableSize );
|
||||
@@ -1442,7 +1442,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
|
||||
|
||||
defragment_out:
|
||||
if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
assert( cbrk>=iCellFirst );
|
||||
put2byte(&data[hdr+5], cbrk);
|
||||
@@ -1481,7 +1481,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
|
||||
/* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of
|
||||
** increasing offset. */
|
||||
if( pc>usableSize-4 || pc<iAddr+4 ){
|
||||
*pRc = SQLITE_CORRUPT_BKPT;
|
||||
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
|
||||
return 0;
|
||||
}
|
||||
/* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each
|
||||
@@ -1492,7 +1492,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){
|
||||
testcase( x==4 );
|
||||
testcase( x==3 );
|
||||
if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){
|
||||
*pRc = SQLITE_CORRUPT_BKPT;
|
||||
*pRc = SQLITE_CORRUPT_PGNO(pPg->pgno);
|
||||
return 0;
|
||||
}else if( x<4 ){
|
||||
/* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total
|
||||
@@ -1559,7 +1559,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){
|
||||
if( top==0 && pPage->pBt->usableSize==65536 ){
|
||||
top = 65536;
|
||||
}else{
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1655,11 +1655,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
|
||||
if( iFreeBlk<iPtr+4 ){
|
||||
if( iFreeBlk==0 ) break;
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
iPtr = iFreeBlk;
|
||||
}
|
||||
if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT;
|
||||
if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
assert( iFreeBlk>iPtr || iFreeBlk==0 );
|
||||
|
||||
/* At this point:
|
||||
@@ -1670,9 +1670,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
*/
|
||||
if( iFreeBlk && iEnd+3>=iFreeBlk ){
|
||||
nFrag = iFreeBlk - iEnd;
|
||||
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT;
|
||||
if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]);
|
||||
if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT;
|
||||
if( iEnd > pPage->pBt->usableSize ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
iSize = iEnd - iStart;
|
||||
iFreeBlk = get2byte(&data[iFreeBlk]);
|
||||
}
|
||||
@@ -1684,20 +1686,20 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
if( iPtr>hdr+1 ){
|
||||
int iPtrEnd = iPtr + get2byte(&data[iPtr+2]);
|
||||
if( iPtrEnd+3>=iStart ){
|
||||
if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT;
|
||||
if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
nFrag += iStart - iPtrEnd;
|
||||
iSize = iEnd - iPtr;
|
||||
iStart = iPtr;
|
||||
}
|
||||
}
|
||||
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT;
|
||||
if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
data[hdr+7] -= nFrag;
|
||||
}
|
||||
if( iStart==get2byte(&data[hdr+5]) ){
|
||||
/* 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( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT;
|
||||
if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
put2byte(&data[hdr+1], iFreeBlk);
|
||||
put2byte(&data[hdr+5], iEnd);
|
||||
}else{
|
||||
@@ -1765,7 +1767,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){
|
||||
}else{
|
||||
/* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is
|
||||
** an error. */
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
pPage->max1bytePayload = pBt->max1bytePayload;
|
||||
return SQLITE_OK;
|
||||
@@ -1781,6 +1783,16 @@ static int decodeFlags(MemPage *pPage, int flagByte){
|
||||
** we failed to detect any corruption.
|
||||
*/
|
||||
static int btreeInitPage(MemPage *pPage){
|
||||
int pc; /* Address of a freeblock within pPage->aData[] */
|
||||
u8 hdr; /* Offset to beginning of page header */
|
||||
u8 *data; /* Equal to pPage->aData */
|
||||
BtShared *pBt; /* The main btree structure */
|
||||
int usableSize; /* Amount of usable space on each page */
|
||||
u16 cellOffset; /* Offset from start of page to first cell pointer */
|
||||
int nFree; /* Number of unused bytes on the page */
|
||||
int top; /* First byte of the cell content area */
|
||||
int iCellFirst; /* First allowable cell or freeblock offset */
|
||||
int iCellLast; /* Last possible cell or freeblock offset */
|
||||
|
||||
assert( pPage->pBt!=0 );
|
||||
assert( pPage->pBt->db!=0 );
|
||||
@@ -1788,127 +1800,119 @@ static int btreeInitPage(MemPage *pPage){
|
||||
assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
|
||||
assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
|
||||
assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
|
||||
assert( pPage->isInit==0 );
|
||||
|
||||
if( !pPage->isInit ){
|
||||
int pc; /* Address of a freeblock within pPage->aData[] */
|
||||
u8 hdr; /* Offset to beginning of page header */
|
||||
u8 *data; /* Equal to pPage->aData */
|
||||
BtShared *pBt; /* The main btree structure */
|
||||
int usableSize; /* Amount of usable space on each page */
|
||||
u16 cellOffset; /* Offset from start of page to first cell pointer */
|
||||
int nFree; /* Number of unused bytes on the page */
|
||||
int top; /* First byte of the cell content area */
|
||||
int iCellFirst; /* First allowable cell or freeblock offset */
|
||||
int iCellLast; /* Last possible cell or freeblock offset */
|
||||
|
||||
pBt = pPage->pBt;
|
||||
|
||||
hdr = pPage->hdrOffset;
|
||||
data = pPage->aData;
|
||||
/* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
|
||||
** the b-tree page type. */
|
||||
if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
|
||||
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
|
||||
pPage->maskPage = (u16)(pBt->pageSize - 1);
|
||||
pPage->nOverflow = 0;
|
||||
usableSize = pBt->usableSize;
|
||||
pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
|
||||
pPage->aDataEnd = &data[usableSize];
|
||||
pPage->aCellIdx = &data[cellOffset];
|
||||
pPage->aDataOfst = &data[pPage->childPtrSize];
|
||||
/* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
|
||||
** the start of the cell content area. A zero value for this integer is
|
||||
** interpreted as 65536. */
|
||||
top = get2byteNotZero(&data[hdr+5]);
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
pPage->nCell = get2byte(&data[hdr+3]);
|
||||
if( pPage->nCell>MX_CELL(pBt) ){
|
||||
/* To many cells for a single page. The page must be corrupt */
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
testcase( pPage->nCell==MX_CELL(pBt) );
|
||||
/* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
|
||||
** possible for a root page of a table that contains no rows) then the
|
||||
** offset to the cell content area will equal the page size minus the
|
||||
** bytes of reserved space. */
|
||||
assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
|
||||
|
||||
/* A malformed database page might cause us to read past the end
|
||||
** of page when parsing a cell.
|
||||
**
|
||||
** The following block of code checks early to see if a cell extends
|
||||
** past the end of a page boundary and causes SQLITE_CORRUPT to be
|
||||
** returned if it does.
|
||||
*/
|
||||
iCellFirst = cellOffset + 2*pPage->nCell;
|
||||
iCellLast = usableSize - 4;
|
||||
if( pBt->db->flags & SQLITE_CellSizeCk ){
|
||||
int i; /* Index into the cell pointer array */
|
||||
int sz; /* Size of a cell */
|
||||
|
||||
if( !pPage->leaf ) iCellLast--;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
pc = get2byteAligned(&data[cellOffset+i*2]);
|
||||
testcase( pc==iCellFirst );
|
||||
testcase( pc==iCellLast );
|
||||
if( pc<iCellFirst || pc>iCellLast ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
sz = pPage->xCellSize(pPage, &data[pc]);
|
||||
testcase( pc+sz==usableSize );
|
||||
if( pc+sz>usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
}
|
||||
if( !pPage->leaf ) iCellLast++;
|
||||
}
|
||||
|
||||
/* Compute the total free space on the page
|
||||
** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
|
||||
** start of the first freeblock on the page, or is zero if there are no
|
||||
** freeblocks. */
|
||||
pc = get2byte(&data[hdr+1]);
|
||||
nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
|
||||
if( pc>0 ){
|
||||
u32 next, size;
|
||||
if( pc<iCellFirst ){
|
||||
/* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
|
||||
** always be at least one cell before the first freeblock.
|
||||
*/
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
while( 1 ){
|
||||
if( pc>iCellLast ){
|
||||
return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */
|
||||
}
|
||||
next = get2byte(&data[pc]);
|
||||
size = get2byte(&data[pc+2]);
|
||||
nFree = nFree + size;
|
||||
if( next<=pc+size+3 ) break;
|
||||
pc = next;
|
||||
}
|
||||
if( next>0 ){
|
||||
return SQLITE_CORRUPT_BKPT; /* Freeblock not in ascending order */
|
||||
}
|
||||
if( pc+size>(unsigned int)usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT; /* Last freeblock extends past page end */
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point, nFree contains the sum of the offset to the start
|
||||
** of the cell-content area plus the number of free bytes within
|
||||
** the cell-content area. If this is greater than the usable-size
|
||||
** of the page, then the page must be corrupted. This check also
|
||||
** serves to verify that the offset to the start of the cell-content
|
||||
** area, according to the page header, lies within the page.
|
||||
*/
|
||||
if( nFree>usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
pPage->nFree = (u16)(nFree - iCellFirst);
|
||||
pPage->isInit = 1;
|
||||
pBt = pPage->pBt;
|
||||
hdr = pPage->hdrOffset;
|
||||
data = pPage->aData;
|
||||
/* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
|
||||
** the b-tree page type. */
|
||||
if( decodeFlags(pPage, data[hdr]) ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
|
||||
pPage->maskPage = (u16)(pBt->pageSize - 1);
|
||||
pPage->nOverflow = 0;
|
||||
usableSize = pBt->usableSize;
|
||||
pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
|
||||
pPage->aDataEnd = &data[usableSize];
|
||||
pPage->aCellIdx = &data[cellOffset];
|
||||
pPage->aDataOfst = &data[pPage->childPtrSize];
|
||||
/* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
|
||||
** the start of the cell content area. A zero value for this integer is
|
||||
** interpreted as 65536. */
|
||||
top = get2byteNotZero(&data[hdr+5]);
|
||||
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
|
||||
** number of cells on the page. */
|
||||
pPage->nCell = get2byte(&data[hdr+3]);
|
||||
if( pPage->nCell>MX_CELL(pBt) ){
|
||||
/* To many cells for a single page. The page must be corrupt */
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
testcase( pPage->nCell==MX_CELL(pBt) );
|
||||
/* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
|
||||
** possible for a root page of a table that contains no rows) then the
|
||||
** offset to the cell content area will equal the page size minus the
|
||||
** bytes of reserved space. */
|
||||
assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
|
||||
|
||||
/* A malformed database page might cause us to read past the end
|
||||
** of page when parsing a cell.
|
||||
**
|
||||
** The following block of code checks early to see if a cell extends
|
||||
** past the end of a page boundary and causes SQLITE_CORRUPT to be
|
||||
** returned if it does.
|
||||
*/
|
||||
iCellFirst = cellOffset + 2*pPage->nCell;
|
||||
iCellLast = usableSize - 4;
|
||||
if( pBt->db->flags & SQLITE_CellSizeCk ){
|
||||
int i; /* Index into the cell pointer array */
|
||||
int sz; /* Size of a cell */
|
||||
|
||||
if( !pPage->leaf ) iCellLast--;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
pc = get2byteAligned(&data[cellOffset+i*2]);
|
||||
testcase( pc==iCellFirst );
|
||||
testcase( pc==iCellLast );
|
||||
if( pc<iCellFirst || pc>iCellLast ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
sz = pPage->xCellSize(pPage, &data[pc]);
|
||||
testcase( pc+sz==usableSize );
|
||||
if( pc+sz>usableSize ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
}
|
||||
if( !pPage->leaf ) iCellLast++;
|
||||
}
|
||||
|
||||
/* Compute the total free space on the page
|
||||
** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
|
||||
** start of the first freeblock on the page, or is zero if there are no
|
||||
** freeblocks. */
|
||||
pc = get2byte(&data[hdr+1]);
|
||||
nFree = data[hdr+7] + top; /* Init nFree to non-freeblock free space */
|
||||
if( pc>0 ){
|
||||
u32 next, size;
|
||||
if( pc<iCellFirst ){
|
||||
/* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
|
||||
** always be at least one cell before the first freeblock.
|
||||
*/
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
while( 1 ){
|
||||
if( pc>iCellLast ){
|
||||
/* Freeblock off the end of the page */
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
next = get2byte(&data[pc]);
|
||||
size = get2byte(&data[pc+2]);
|
||||
nFree = nFree + size;
|
||||
if( next<=pc+size+3 ) break;
|
||||
pc = next;
|
||||
}
|
||||
if( next>0 ){
|
||||
/* Freeblock not in ascending order */
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
if( pc+size>(unsigned int)usableSize ){
|
||||
/* Last freeblock extends past page end */
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
}
|
||||
|
||||
/* At this point, nFree contains the sum of the offset to the start
|
||||
** of the cell-content area plus the number of free bytes within
|
||||
** the cell-content area. If this is greater than the usable-size
|
||||
** of the page, then the page must be corrupted. This check also
|
||||
** serves to verify that the offset to the start of the cell-content
|
||||
** area, according to the page header, lies within the page.
|
||||
*/
|
||||
if( nFree>usableSize ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
pPage->nFree = (u16)(nFree - iCellFirst);
|
||||
pPage->isInit = 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -2072,7 +2076,7 @@ static int getAndInitPage(
|
||||
/* If obtaining a child page for a cursor, we must verify that the page is
|
||||
** compatible with the root page. */
|
||||
if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(pgno);
|
||||
releasePage(*ppPage);
|
||||
goto getAndInitPage_error;
|
||||
}
|
||||
@@ -3360,7 +3364,7 @@ static int setChildPtrmaps(MemPage *pPage){
|
||||
Pgno pgno = pPage->pgno;
|
||||
|
||||
assert( sqlite3_mutex_held(pPage->pBt->mutex) );
|
||||
rc = btreeInitPage(pPage);
|
||||
rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
|
||||
if( rc!=SQLITE_OK ) return rc;
|
||||
nCell = pPage->nCell;
|
||||
|
||||
@@ -3403,7 +3407,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
||||
if( eType==PTRMAP_OVERFLOW2 ){
|
||||
/* The pointer is always the first 4 bytes of the page in this case. */
|
||||
if( get4byte(pPage->aData)!=iFrom ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
put4byte(pPage->aData, iTo);
|
||||
}else{
|
||||
@@ -3411,7 +3415,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
||||
int nCell;
|
||||
int rc;
|
||||
|
||||
rc = btreeInitPage(pPage);
|
||||
rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
|
||||
if( rc ) return rc;
|
||||
nCell = pPage->nCell;
|
||||
|
||||
@@ -3422,7 +3426,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
||||
pPage->xParseCell(pPage, pCell, &info);
|
||||
if( info.nLocal<info.nPayload ){
|
||||
if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
if( iFrom==get4byte(pCell+info.nSize-4) ){
|
||||
put4byte(pCell+info.nSize-4, iTo);
|
||||
@@ -3440,7 +3444,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){
|
||||
if( i==nCell ){
|
||||
if( eType!=PTRMAP_BTREE ||
|
||||
get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
put4byte(&pPage->aData[pPage->hdrOffset+8], iTo);
|
||||
}
|
||||
@@ -4548,7 +4552,7 @@ static int accessPayload(
|
||||
** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
|
||||
** but is recast into its current form to avoid integer overflow problems
|
||||
*/
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
|
||||
/* Check if data must be read/written to/from the btree page itself. */
|
||||
@@ -4695,7 +4699,8 @@ static int accessPayload(
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && amt>0 ){
|
||||
return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */
|
||||
/* Overflow chain ends prematurely */
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -4961,7 +4966,7 @@ static int moveToRoot(BtCursor *pCur){
|
||||
** (or the freelist). */
|
||||
assert( pRoot->intKey==1 || pRoot->intKey==0 );
|
||||
if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno);
|
||||
}
|
||||
|
||||
skip_init:
|
||||
@@ -5166,16 +5171,19 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
/* If the requested key is one more than the previous key, then
|
||||
** try to get there using sqlite3BtreeNext() rather than a full
|
||||
** binary search. This is an optimization only. The correct answer
|
||||
** is still obtained without this ase, only a little more slowely */
|
||||
** is still obtained without this case, only a little more slowely */
|
||||
if( pCur->info.nKey+1==intKey && !pCur->skipNext ){
|
||||
*pRes = 0;
|
||||
rc = sqlite3BtreeNext(pCur, pRes);
|
||||
if( rc ) return rc;
|
||||
if( *pRes==0 ){
|
||||
rc = sqlite3BtreeNext(pCur, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
getCellInfo(pCur);
|
||||
if( pCur->info.nKey==intKey ){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
}else if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5231,7 +5239,9 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
pCell = findCellPastPtr(pPage, idx);
|
||||
if( pPage->intKeyLeaf ){
|
||||
while( 0x80 <= *(pCell++) ){
|
||||
if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT;
|
||||
if( pCell>=pPage->aDataEnd ){
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
}
|
||||
}
|
||||
getVarint(pCell, (u64*)&nCellKey);
|
||||
@@ -5304,7 +5314,7 @@ int sqlite3BtreeMovetoUnpacked(
|
||||
testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */
|
||||
testcase( nCell==2 ); /* Minimum legal index key size */
|
||||
if( nCell<2 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
goto moveto_finish;
|
||||
}
|
||||
pCellKey = sqlite3Malloc( nCell+18 );
|
||||
@@ -5409,10 +5419,12 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance the cursor to the next entry in the database. If
|
||||
** successful then set *pRes=0. If the cursor
|
||||
** was already pointing to the last entry in the database before
|
||||
** this routine was called, then set *pRes=1.
|
||||
** Advance the cursor to the next entry in the database.
|
||||
** Return value:
|
||||
**
|
||||
** SQLITE_OK success
|
||||
** SQLITE_DONE cursor is already pointing at the last element
|
||||
** otherwise some kind of error occurred
|
||||
**
|
||||
** The main entry point is sqlite3BtreeNext(). That routine is optimized
|
||||
** for the common case of merely incrementing the cell counter BtCursor.aiIdx
|
||||
@@ -5420,23 +5432,19 @@ i64 sqlite3BtreeRowCountEst(BtCursor *pCur){
|
||||
** routine is called when it is necessary to move to a different page or
|
||||
** to restore the cursor.
|
||||
**
|
||||
** The calling function will set *pRes to 0 or 1. The initial *pRes value
|
||||
** will be 1 if the cursor being stepped corresponds to an SQL index and
|
||||
** if this routine could have been skipped if that SQL index had been
|
||||
** a unique index. Otherwise the caller will have set *pRes to zero.
|
||||
** Zero is the common case. The btree implementation is free to use the
|
||||
** initial *pRes value as a hint to improve performance, but the current
|
||||
** SQLite btree implementation does not. (Note that the comdb2 btree
|
||||
** implementation does use this hint, however.)
|
||||
** If bit 0x01 of the flags argument is 1, then the cursor corresponds to
|
||||
** an SQL index and this routine could have been skipped if the SQL index
|
||||
** had been a unique index. The flags argument is a hint to the implement.
|
||||
** SQLite btree implementation does not use this hint, but COMDB2 does.
|
||||
*/
|
||||
static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
|
||||
static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int flags){
|
||||
int rc;
|
||||
int idx;
|
||||
MemPage *pPage;
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
|
||||
assert( *pRes==0 );
|
||||
assert( flags==0 );
|
||||
if( pCur->eState!=CURSOR_VALID ){
|
||||
assert( (pCur->curFlags & BTCF_ValidOvfl)==0 );
|
||||
rc = restoreCursorPosition(pCur);
|
||||
@@ -5444,8 +5452,7 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
|
||||
return rc;
|
||||
}
|
||||
if( CURSOR_INVALID==pCur->eState ){
|
||||
*pRes = 1;
|
||||
return SQLITE_OK;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
if( pCur->skipNext ){
|
||||
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
|
||||
@@ -5477,15 +5484,14 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
|
||||
}
|
||||
do{
|
||||
if( pCur->iPage==0 ){
|
||||
*pRes = 1;
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
return SQLITE_OK;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
moveToParent(pCur);
|
||||
pPage = pCur->apPage[pCur->iPage];
|
||||
}while( pCur->ix>=pPage->nCell );
|
||||
if( pPage->intKey ){
|
||||
return sqlite3BtreeNext(pCur, pRes);
|
||||
return sqlite3BtreeNext(pCur, flags);
|
||||
}else{
|
||||
return SQLITE_OK;
|
||||
}
|
||||
@@ -5496,20 +5502,18 @@ static SQLITE_NOINLINE int btreeNext(BtCursor *pCur, int *pRes){
|
||||
return moveToLeftmost(pCur);
|
||||
}
|
||||
}
|
||||
int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
||||
int sqlite3BtreeNext(BtCursor *pCur, int flags){
|
||||
MemPage *pPage;
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( pRes!=0 );
|
||||
assert( *pRes==0 || *pRes==1 );
|
||||
assert( flags==0 || flags==1 );
|
||||
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
|
||||
pCur->info.nSize = 0;
|
||||
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
|
||||
*pRes = 0;
|
||||
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, pRes);
|
||||
if( pCur->eState!=CURSOR_VALID ) return btreeNext(pCur, 0);
|
||||
pPage = pCur->apPage[pCur->iPage];
|
||||
if( (++pCur->ix)>=pPage->nCell ){
|
||||
pCur->ix--;
|
||||
return btreeNext(pCur, pRes);
|
||||
return btreeNext(pCur, 0);
|
||||
}
|
||||
if( pPage->leaf ){
|
||||
return SQLITE_OK;
|
||||
@@ -5519,10 +5523,12 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
||||
}
|
||||
|
||||
/*
|
||||
** Step the cursor to the back to the previous entry in the database. If
|
||||
** successful then set *pRes=0. If the cursor
|
||||
** was already pointing to the first entry in the database before
|
||||
** this routine was called, then set *pRes=1.
|
||||
** Step the cursor to the back to the previous entry in the database.
|
||||
** Return values:
|
||||
**
|
||||
** SQLITE_OK success
|
||||
** SQLITE_DONE the cursor is already on the first element of the table
|
||||
** otherwise some kind of error occurred
|
||||
**
|
||||
** The main entry point is sqlite3BtreePrevious(). That routine is optimized
|
||||
** for the common case of merely decrementing the cell counter BtCursor.aiIdx
|
||||
@@ -5530,22 +5536,18 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
|
||||
** helper routine is called when it is necessary to move to a different page
|
||||
** or to restore the cursor.
|
||||
**
|
||||
** The calling function will set *pRes to 0 or 1. The initial *pRes value
|
||||
** will be 1 if the cursor being stepped corresponds to an SQL index and
|
||||
** if this routine could have been skipped if that SQL index had been
|
||||
** a unique index. Otherwise the caller will have set *pRes to zero.
|
||||
** Zero is the common case. The btree implementation is free to use the
|
||||
** initial *pRes value as a hint to improve performance, but the current
|
||||
** SQLite btree implementation does not. (Note that the comdb2 btree
|
||||
** implementation does use this hint, however.)
|
||||
**
|
||||
** If bit 0x01 of the flags argument is 1, then the cursor corresponds to
|
||||
** an SQL index and this routine could have been skipped if the SQL index
|
||||
** had been a unique index. The flags argument is a hint to the implement.
|
||||
** SQLite btree implementation does not use this hint, but COMDB2 does.
|
||||
*/
|
||||
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
|
||||
static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int flags){
|
||||
int rc;
|
||||
MemPage *pPage;
|
||||
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( pRes!=0 );
|
||||
assert( *pRes==0 );
|
||||
assert( flags==0 );
|
||||
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
|
||||
assert( (pCur->curFlags & (BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey))==0 );
|
||||
assert( pCur->info.nSize==0 );
|
||||
@@ -5555,8 +5557,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
|
||||
return rc;
|
||||
}
|
||||
if( CURSOR_INVALID==pCur->eState ){
|
||||
*pRes = 1;
|
||||
return SQLITE_OK;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
if( pCur->skipNext ){
|
||||
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_SKIPNEXT );
|
||||
@@ -5580,8 +5581,7 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
|
||||
while( pCur->ix==0 ){
|
||||
if( pCur->iPage==0 ){
|
||||
pCur->eState = CURSOR_INVALID;
|
||||
*pRes = 1;
|
||||
return SQLITE_OK;
|
||||
return SQLITE_DONE;
|
||||
}
|
||||
moveToParent(pCur);
|
||||
}
|
||||
@@ -5591,26 +5591,24 @@ static SQLITE_NOINLINE int btreePrevious(BtCursor *pCur, int *pRes){
|
||||
pCur->ix--;
|
||||
pPage = pCur->apPage[pCur->iPage];
|
||||
if( pPage->intKey && !pPage->leaf ){
|
||||
rc = sqlite3BtreePrevious(pCur, pRes);
|
||||
rc = sqlite3BtreePrevious(pCur, flags);
|
||||
}else{
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
|
||||
int sqlite3BtreePrevious(BtCursor *pCur, int flags){
|
||||
assert( cursorOwnsBtShared(pCur) );
|
||||
assert( pRes!=0 );
|
||||
assert( *pRes==0 || *pRes==1 );
|
||||
assert( flags==0 || flags==1 );
|
||||
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
|
||||
*pRes = 0;
|
||||
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl|BTCF_ValidNKey);
|
||||
pCur->info.nSize = 0;
|
||||
if( pCur->eState!=CURSOR_VALID
|
||||
|| pCur->ix==0
|
||||
|| pCur->apPage[pCur->iPage]->leaf==0
|
||||
){
|
||||
return btreePrevious(pCur, pRes);
|
||||
return btreePrevious(pCur, 0);
|
||||
}
|
||||
pCur->ix--;
|
||||
return SQLITE_OK;
|
||||
@@ -5718,7 +5716,7 @@ static int allocateBtreePage(
|
||||
}
|
||||
testcase( iTrunk==mxPage );
|
||||
if( iTrunk>mxPage || nSearch++ > n ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(pPrevTrunk ? pPrevTrunk->pgno : 1);
|
||||
}else{
|
||||
rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0);
|
||||
}
|
||||
@@ -5747,7 +5745,7 @@ static int allocateBtreePage(
|
||||
TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1));
|
||||
}else if( k>(u32)(pBt->usableSize/4 - 2) ){
|
||||
/* Value of k is out of range. Database corruption */
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(iTrunk);
|
||||
goto end_allocate_page;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
}else if( searchList
|
||||
@@ -5781,7 +5779,7 @@ static int allocateBtreePage(
|
||||
MemPage *pNewTrunk;
|
||||
Pgno iNewTrunk = get4byte(&pTrunk->aData[8]);
|
||||
if( iNewTrunk>mxPage ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(iTrunk);
|
||||
goto end_allocate_page;
|
||||
}
|
||||
testcase( iNewTrunk==mxPage );
|
||||
@@ -5846,7 +5844,7 @@ static int allocateBtreePage(
|
||||
iPage = get4byte(&aData[8+closest*4]);
|
||||
testcase( iPage==mxPage );
|
||||
if( iPage>mxPage ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
rc = SQLITE_CORRUPT_PGNO(iTrunk);
|
||||
goto end_allocate_page;
|
||||
}
|
||||
testcase( iPage==mxPage );
|
||||
@@ -6116,7 +6114,8 @@ static int clearCell(
|
||||
return SQLITE_OK; /* No overflow pages. Return without doing anything */
|
||||
}
|
||||
if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
|
||||
return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */
|
||||
/* Cell extends past end of page */
|
||||
return SQLITE_CORRUPT_PGNO(pPage->pgno);
|
||||
}
|
||||
ovflPgno = get4byte(pCell + pInfo->nSize - 4);
|
||||
assert( pBt->usableSize > 4 );
|
||||
@@ -8174,12 +8173,18 @@ int sqlite3BtreeInsert(
|
||||
memcpy(newCell, oldCell, 4);
|
||||
}
|
||||
rc = clearCell(pPage, oldCell, &info);
|
||||
if( info.nSize==szNew && info.nLocal==info.nPayload ){
|
||||
if( info.nSize==szNew && info.nLocal==info.nPayload
|
||||
&& (!ISAUTOVACUUM || szNew<pPage->minLocal)
|
||||
){
|
||||
/* Overwrite the old cell with the new if they are the same size.
|
||||
** We could also try to do this if the old cell is smaller, then add
|
||||
** the leftover space to the free list. But experiments show that
|
||||
** doing that is no faster then skipping this optimization and just
|
||||
** calling dropCell() and insertCell(). */
|
||||
** calling dropCell() and insertCell().
|
||||
**
|
||||
** This optimization cannot be used on an autovacuum database if the
|
||||
** 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;
|
||||
memcpy(oldCell, newCell, szNew);
|
||||
@@ -8325,8 +8330,8 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
|
||||
** sub-tree headed by the child page of the cell being deleted. This makes
|
||||
** balancing the tree following the delete operation easier. */
|
||||
if( !pPage->leaf ){
|
||||
int notUsed = 0;
|
||||
rc = sqlite3BtreePrevious(pCur, ¬Used);
|
||||
rc = sqlite3BtreePrevious(pCur, 0);
|
||||
assert( rc!=SQLITE_DONE );
|
||||
if( rc ) return rc;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -286,9 +286,9 @@ int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
|
||||
int flags, int seekResult);
|
||||
int sqlite3BtreeFirst(BtCursor*, int *pRes);
|
||||
int sqlite3BtreeLast(BtCursor*, int *pRes);
|
||||
int sqlite3BtreeNext(BtCursor*, int *pRes);
|
||||
int sqlite3BtreeNext(BtCursor*, int flags);
|
||||
int sqlite3BtreeEof(BtCursor*);
|
||||
int sqlite3BtreePrevious(BtCursor*, int *pRes);
|
||||
int sqlite3BtreePrevious(BtCursor*, int flags);
|
||||
i64 sqlite3BtreeIntegerKey(BtCursor*);
|
||||
int sqlite3BtreePayload(BtCursor*, u32 offset, u32 amt, void*);
|
||||
const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
|
||||
|
||||
@@ -939,7 +939,11 @@ void sqlite3StartTable(
|
||||
pTable->iPKey = -1;
|
||||
pTable->pSchema = db->aDb[iDb].pSchema;
|
||||
pTable->nTabRef = 1;
|
||||
#ifdef SQLITE_DEFAULT_ROWEST
|
||||
pTable->nRowLogEst = sqlite3LogEst(SQLITE_DEFAULT_ROWEST);
|
||||
#else
|
||||
pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
|
||||
#endif
|
||||
assert( pParse->pNewTable==0 );
|
||||
pParse->pNewTable = pTable;
|
||||
|
||||
|
||||
+335
-62
@@ -16,7 +16,11 @@
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
|
||||
#include "sqliteInt.h"
|
||||
|
||||
/* These macros are provided to "stringify" the value of the define
|
||||
** for those options in which the value is meaningful. */
|
||||
#define CTIMEOPT_VAL_(opt) #opt
|
||||
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
|
||||
|
||||
/*
|
||||
** An array of names of all compile-time options. This array should
|
||||
@@ -28,17 +32,30 @@
|
||||
*/
|
||||
static const char * const azCompileOpt[] = {
|
||||
|
||||
/* These macros are provided to "stringify" the value of the define
|
||||
** for those options in which the value is meaningful. */
|
||||
#define CTIMEOPT_VAL_(opt) #opt
|
||||
#define CTIMEOPT_VAL(opt) CTIMEOPT_VAL_(opt)
|
||||
|
||||
/*
|
||||
** BEGIN CODE GENERATED BY tool/mkctime.tcl
|
||||
*/
|
||||
#if SQLITE_32BIT_ROWID
|
||||
"32BIT_ROWID",
|
||||
#endif
|
||||
#if SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
"4_BYTE_ALIGNED_MALLOC",
|
||||
#endif
|
||||
#if SQLITE_64BIT_STATS
|
||||
"64BIT_STATS",
|
||||
#endif
|
||||
#if SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||
"ALLOW_COVERING_INDEX_SCAN",
|
||||
#endif
|
||||
#if SQLITE_ALLOW_URI_AUTHORITY
|
||||
"ALLOW_URI_AUTHORITY",
|
||||
#endif
|
||||
#ifdef SQLITE_BITMASK_TYPE
|
||||
"BITMASK_TYPE=" CTIMEOPT_VAL(SQLITE_BITMASK_TYPE),
|
||||
#endif
|
||||
#if SQLITE_BUG_COMPATIBLE_20160819
|
||||
"BUG_COMPATIBLE_20160819",
|
||||
#endif
|
||||
#if SQLITE_CASE_SENSITIVE_LIKE
|
||||
"CASE_SENSITIVE_LIKE",
|
||||
#endif
|
||||
@@ -57,31 +74,100 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_COVERAGE_TEST
|
||||
"COVERAGE_TEST",
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
#if SQLITE_DEBUG
|
||||
"DEBUG",
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_LOCKING_MODE
|
||||
#if SQLITE_DEFAULT_AUTOMATIC_INDEX
|
||||
"DEFAULT_AUTOMATIC_INDEX",
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_AUTOVACUUM
|
||||
"DEFAULT_AUTOVACUUM",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_CACHE_SIZE
|
||||
"DEFAULT_CACHE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_CACHE_SIZE),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
"DEFAULT_CKPTFULLFSYNC",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_FILE_FORMAT
|
||||
"DEFAULT_FILE_FORMAT=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_FORMAT),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_FILE_PERMISSIONS
|
||||
"DEFAULT_FILE_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_FILE_PERMISSIONS),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_FOREIGN_KEYS
|
||||
"DEFAULT_FOREIGN_KEYS",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
|
||||
"DEFAULT_JOURNAL_SIZE_LIMIT=" CTIMEOPT_VAL(SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_LOCKING_MODE
|
||||
"DEFAULT_LOCKING_MODE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOCKING_MODE),
|
||||
#endif
|
||||
#if defined(SQLITE_DEFAULT_MMAP_SIZE) && !defined(SQLITE_DEFAULT_MMAP_SIZE_xc)
|
||||
#ifdef SQLITE_DEFAULT_LOOKASIDE
|
||||
"DEFAULT_LOOKASIDE=" CTIMEOPT_VAL(SQLITE_DEFAULT_LOOKASIDE),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_MEMSTATUS
|
||||
"DEFAULT_MEMSTATUS",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_MMAP_SIZE
|
||||
"DEFAULT_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_MMAP_SIZE),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_SYNCHRONOUS
|
||||
#ifdef SQLITE_DEFAULT_PAGE_SIZE
|
||||
"DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_PAGE_SIZE),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_PCACHE_INITSZ
|
||||
"DEFAULT_PCACHE_INITSZ=" CTIMEOPT_VAL(SQLITE_DEFAULT_PCACHE_INITSZ),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
|
||||
"DEFAULT_PROXYDIR_PERMISSIONS=" CTIMEOPT_VAL(SQLITE_DEFAULT_PROXYDIR_PERMISSIONS),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
||||
"DEFAULT_RECURSIVE_TRIGGERS",
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_ROWEST
|
||||
"DEFAULT_ROWEST=" CTIMEOPT_VAL(SQLITE_DEFAULT_ROWEST),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_SECTOR_SIZE
|
||||
"DEFAULT_SECTOR_SIZE=" CTIMEOPT_VAL(SQLITE_DEFAULT_SECTOR_SIZE),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_SYNCHRONOUS
|
||||
"DEFAULT_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_SYNCHRONOUS),
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
#ifdef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
|
||||
"DEFAULT_WAL_AUTOCHECKPOINT=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_AUTOCHECKPOINT),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
"DEFAULT_WAL_SYNCHRONOUS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WAL_SYNCHRONOUS),
|
||||
#endif
|
||||
#ifdef SQLITE_DEFAULT_WORKER_THREADS
|
||||
"DEFAULT_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_DEFAULT_WORKER_THREADS),
|
||||
#endif
|
||||
#if SQLITE_DIRECT_OVERFLOW_READ
|
||||
"DIRECT_OVERFLOW_READ",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_DIRSYNC
|
||||
"DISABLE_DIRSYNC",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_FTS3_UNICODE
|
||||
"DISABLE_FTS3_UNICODE",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_FTS4_DEFERRED
|
||||
"DISABLE_FTS4_DEFERRED",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_INTRINSIC
|
||||
"DISABLE_INTRINSIC",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_LFS
|
||||
"DISABLE_LFS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_8_3_NAMES
|
||||
#if SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
"DISABLE_PAGECACHE_OVERFLOW_STATS",
|
||||
#endif
|
||||
#if SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
||||
"DISABLE_SKIPAHEAD_DISTINCT",
|
||||
#endif
|
||||
#ifdef SQLITE_ENABLE_8_3_NAMES
|
||||
"ENABLE_8_3_NAMES=" CTIMEOPT_VAL(SQLITE_ENABLE_8_3_NAMES),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
@@ -96,6 +182,15 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_ENABLE_COLUMN_METADATA
|
||||
"ENABLE_COLUMN_METADATA",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
"ENABLE_COLUMN_USED_MASK",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_COSTMULT
|
||||
"ENABLE_COSTMULT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_CURSOR_HINTS
|
||||
"ENABLE_CURSOR_HINTS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_DBSTAT_VTAB
|
||||
"ENABLE_DBSTAT_VTAB",
|
||||
#endif
|
||||
@@ -114,12 +209,18 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
"ENABLE_FTS3_PARENTHESIS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS3_TOKENIZER
|
||||
"ENABLE_FTS3_TOKENIZER",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS4
|
||||
"ENABLE_FTS4",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_FTS5
|
||||
"ENABLE_FTS5",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
"ENABLE_HIDDEN_COLUMNS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ICU
|
||||
"ENABLE_ICU",
|
||||
#endif
|
||||
@@ -132,7 +233,7 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_ENABLE_LOAD_EXTENSION
|
||||
"ENABLE_LOAD_EXTENSION",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_LOCKING_STYLE
|
||||
#ifdef SQLITE_ENABLE_LOCKING_STYLE
|
||||
"ENABLE_LOCKING_STYLE=" CTIMEOPT_VAL(SQLITE_ENABLE_LOCKING_STYLE),
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
@@ -144,26 +245,86 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_ENABLE_MEMSYS5
|
||||
"ENABLE_MEMSYS5",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_MULTIPLEX
|
||||
"ENABLE_MULTIPLEX",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_NULL_TRIM
|
||||
"ENABLE_NULL_TRIM",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
"ENABLE_OVERSIZE_CELL_CHECK",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
"ENABLE_PREUPDATE_HOOK",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_RBU
|
||||
"ENABLE_RBU",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_RTREE
|
||||
"ENABLE_RTREE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SELECTTRACE
|
||||
"ENABLE_SELECTTRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SESSION
|
||||
"ENABLE_SESSION",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SNAPSHOT
|
||||
"ENABLE_SNAPSHOT",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_SQLLOG
|
||||
"ENABLE_SQLLOG",
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
"ENABLE_STAT4",
|
||||
#elif defined(SQLITE_ENABLE_STAT3)
|
||||
"ENABLE_STAT3",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
"ENABLE_STMT_SCANSTATUS",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
"ENABLE_UNKNOWN_SQL_FUNCTION",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
"ENABLE_UNLOCK_NOTIFY",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
"ENABLE_UPDATE_DELETE_LIMIT",
|
||||
#endif
|
||||
#if defined(SQLITE_ENABLE_URI_00_ERROR)
|
||||
#if SQLITE_ENABLE_URI_00_ERROR
|
||||
"ENABLE_URI_00_ERROR",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_VFSTRACE
|
||||
"ENABLE_VFSTRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_WHERETRACE
|
||||
"ENABLE_WHERETRACE",
|
||||
#endif
|
||||
#if SQLITE_ENABLE_ZIPVFS
|
||||
"ENABLE_ZIPVFS",
|
||||
#endif
|
||||
#if SQLITE_EXPLAIN_ESTIMATED_ROWS
|
||||
"EXPLAIN_ESTIMATED_ROWS",
|
||||
#endif
|
||||
#if SQLITE_EXTRA_IFNULLROW
|
||||
"EXTRA_IFNULLROW",
|
||||
#endif
|
||||
#ifdef SQLITE_EXTRA_INIT
|
||||
"EXTRA_INIT=" CTIMEOPT_VAL(SQLITE_EXTRA_INIT),
|
||||
#endif
|
||||
#ifdef SQLITE_EXTRA_SHUTDOWN
|
||||
"EXTRA_SHUTDOWN=" CTIMEOPT_VAL(SQLITE_EXTRA_SHUTDOWN),
|
||||
#endif
|
||||
#ifdef SQLITE_FTS3_MAX_EXPR_DEPTH
|
||||
"FTS3_MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_FTS3_MAX_EXPR_DEPTH),
|
||||
#endif
|
||||
#if SQLITE_FTS5_ENABLE_TEST_MI
|
||||
"FTS5_ENABLE_TEST_MI",
|
||||
#endif
|
||||
#if SQLITE_FTS5_NO_WITHOUT_ROWID
|
||||
"FTS5_NO_WITHOUT_ROWID",
|
||||
#endif
|
||||
#if SQLITE_HAS_CODEC
|
||||
"HAS_CODEC",
|
||||
#endif
|
||||
@@ -179,27 +340,114 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
"IGNORE_FLOCK_LOCK_ERRORS",
|
||||
#endif
|
||||
#ifdef SQLITE_INT64_TYPE
|
||||
#if SQLITE_INLINE_MEMCPY
|
||||
"INLINE_MEMCPY",
|
||||
#endif
|
||||
#if SQLITE_INT64_TYPE
|
||||
"INT64_TYPE",
|
||||
#endif
|
||||
#ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
#ifdef SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
||||
"INTEGRITY_CHECK_ERROR_MAX=" CTIMEOPT_VAL(SQLITE_INTEGRITY_CHECK_ERROR_MAX),
|
||||
#endif
|
||||
#if SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
"LIKE_DOESNT_MATCH_BLOBS",
|
||||
#endif
|
||||
#if SQLITE_LOCK_TRACE
|
||||
"LOCK_TRACE",
|
||||
#endif
|
||||
#if defined(SQLITE_MAX_MMAP_SIZE) && !defined(SQLITE_MAX_MMAP_SIZE_xc)
|
||||
#if SQLITE_LOG_CACHE_SPILL
|
||||
"LOG_CACHE_SPILL",
|
||||
#endif
|
||||
#ifdef SQLITE_MALLOC_SOFT_LIMIT
|
||||
"MALLOC_SOFT_LIMIT=" CTIMEOPT_VAL(SQLITE_MALLOC_SOFT_LIMIT),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_ATTACHED
|
||||
"MAX_ATTACHED=" CTIMEOPT_VAL(SQLITE_MAX_ATTACHED),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_COLUMN
|
||||
"MAX_COLUMN=" CTIMEOPT_VAL(SQLITE_MAX_COLUMN),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_COMPOUND_SELECT
|
||||
"MAX_COMPOUND_SELECT=" CTIMEOPT_VAL(SQLITE_MAX_COMPOUND_SELECT),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_DEFAULT_PAGE_SIZE
|
||||
"MAX_DEFAULT_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_DEFAULT_PAGE_SIZE),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_EXPR_DEPTH
|
||||
"MAX_EXPR_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_EXPR_DEPTH),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_FUNCTION_ARG
|
||||
"MAX_FUNCTION_ARG=" CTIMEOPT_VAL(SQLITE_MAX_FUNCTION_ARG),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_LENGTH
|
||||
"MAX_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LENGTH),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_LIKE_PATTERN_LENGTH
|
||||
"MAX_LIKE_PATTERN_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_LIKE_PATTERN_LENGTH),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_MEMORY
|
||||
"MAX_MEMORY=" CTIMEOPT_VAL(SQLITE_MAX_MEMORY),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_MMAP_SIZE
|
||||
"MAX_MMAP_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_MMAP_SIZE_
|
||||
"MAX_MMAP_SIZE_=" CTIMEOPT_VAL(SQLITE_MAX_MMAP_SIZE_),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_PAGE_COUNT
|
||||
"MAX_PAGE_COUNT=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_COUNT),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_PAGE_SIZE
|
||||
"MAX_PAGE_SIZE=" CTIMEOPT_VAL(SQLITE_MAX_PAGE_SIZE),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_SCHEMA_RETRY
|
||||
"MAX_SCHEMA_RETRY=" CTIMEOPT_VAL(SQLITE_MAX_SCHEMA_RETRY),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_SQL_LENGTH
|
||||
"MAX_SQL_LENGTH=" CTIMEOPT_VAL(SQLITE_MAX_SQL_LENGTH),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_TRIGGER_DEPTH
|
||||
"MAX_TRIGGER_DEPTH=" CTIMEOPT_VAL(SQLITE_MAX_TRIGGER_DEPTH),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_VARIABLE_NUMBER
|
||||
"MAX_VARIABLE_NUMBER=" CTIMEOPT_VAL(SQLITE_MAX_VARIABLE_NUMBER),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_VDBE_OP
|
||||
"MAX_VDBE_OP=" CTIMEOPT_VAL(SQLITE_MAX_VDBE_OP),
|
||||
#endif
|
||||
#ifdef SQLITE_MAX_WORKER_THREADS
|
||||
"MAX_WORKER_THREADS=" CTIMEOPT_VAL(SQLITE_MAX_WORKER_THREADS),
|
||||
#endif
|
||||
#if SQLITE_MEMDEBUG
|
||||
"MEMDEBUG",
|
||||
#endif
|
||||
#if SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
"MIXED_ENDIAN_64BIT_FLOAT",
|
||||
#endif
|
||||
#if SQLITE_MMAP_READWRITE
|
||||
"MMAP_READWRITE",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_NOOP
|
||||
"MUTEX_NOOP",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_NREF
|
||||
"MUTEX_NREF",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_OMIT
|
||||
"MUTEX_OMIT",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_PTHREADS
|
||||
"MUTEX_PTHREADS",
|
||||
#endif
|
||||
#if SQLITE_MUTEX_W32
|
||||
"MUTEX_W32",
|
||||
#endif
|
||||
#if SQLITE_NEED_ERR_NAME
|
||||
"NEED_ERR_NAME",
|
||||
#endif
|
||||
#if SQLITE_NOINLINE
|
||||
"NOINLINE",
|
||||
#endif
|
||||
#if SQLITE_NO_SYNC
|
||||
"NO_SYNC",
|
||||
#endif
|
||||
@@ -251,6 +499,9 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_OMIT_COMPOUND_SELECT
|
||||
"OMIT_COMPOUND_SELECT",
|
||||
#endif
|
||||
#if SQLITE_OMIT_CONFLICT_CLAUSE
|
||||
"OMIT_CONFLICT_CLAUSE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_CTE
|
||||
"OMIT_CTE",
|
||||
#endif
|
||||
@@ -281,6 +532,9 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_OMIT_GET_TABLE
|
||||
"OMIT_GET_TABLE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_HEX_INTEGER
|
||||
"OMIT_HEX_INTEGER",
|
||||
#endif
|
||||
#if SQLITE_OMIT_INCRBLOB
|
||||
"OMIT_INCRBLOB",
|
||||
#endif
|
||||
@@ -308,6 +562,12 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_OMIT_PAGER_PRAGMAS
|
||||
"OMIT_PAGER_PRAGMAS",
|
||||
#endif
|
||||
#if SQLITE_OMIT_PARSER_TRACE
|
||||
"OMIT_PARSER_TRACE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_POPEN
|
||||
"OMIT_POPEN",
|
||||
#endif
|
||||
#if SQLITE_OMIT_PRAGMA
|
||||
"OMIT_PRAGMA",
|
||||
#endif
|
||||
@@ -329,6 +589,9 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_OMIT_SHARED_CACHE
|
||||
"OMIT_SHARED_CACHE",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
||||
"OMIT_SHUTDOWN_DIRECTORIES",
|
||||
#endif
|
||||
#if SQLITE_OMIT_SUBQUERY
|
||||
"OMIT_SUBQUERY",
|
||||
#endif
|
||||
@@ -338,6 +601,9 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_OMIT_TEMPDB
|
||||
"OMIT_TEMPDB",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TEST_CONTROL
|
||||
"OMIT_TEST_CONTROL",
|
||||
#endif
|
||||
#if SQLITE_OMIT_TRACE
|
||||
"OMIT_TRACE",
|
||||
#endif
|
||||
@@ -368,12 +634,24 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_OMIT_XFER_OPT
|
||||
"OMIT_XFER_OPT",
|
||||
#endif
|
||||
#if SQLITE_PCACHE_SEPARATE_HEADER
|
||||
"PCACHE_SEPARATE_HEADER",
|
||||
#endif
|
||||
#if SQLITE_PERFORMANCE_TRACE
|
||||
"PERFORMANCE_TRACE",
|
||||
#endif
|
||||
#if SQLITE_POWERSAFE_OVERWRITE
|
||||
"POWERSAFE_OVERWRITE",
|
||||
#endif
|
||||
#if SQLITE_PREFER_PROXY_LOCKING
|
||||
"PREFER_PROXY_LOCKING",
|
||||
#endif
|
||||
#if SQLITE_PROXY_DEBUG
|
||||
"PROXY_DEBUG",
|
||||
#endif
|
||||
#if SQLITE_REVERSE_UNORDERED_SELECTS
|
||||
"REVERSE_UNORDERED_SELECTS",
|
||||
#endif
|
||||
#if SQLITE_RTREE_INT_ONLY
|
||||
"RTREE_INT_ONLY",
|
||||
#endif
|
||||
@@ -383,16 +661,28 @@ static const char * const azCompileOpt[] = {
|
||||
#if SQLITE_SMALL_STACK
|
||||
"SMALL_STACK",
|
||||
#endif
|
||||
#ifdef SQLITE_SORTER_PMASZ
|
||||
"SORTER_PMASZ=" CTIMEOPT_VAL(SQLITE_SORTER_PMASZ),
|
||||
#endif
|
||||
#if SQLITE_SOUNDEX
|
||||
"SOUNDEX",
|
||||
#endif
|
||||
#ifdef SQLITE_STAT4_SAMPLES
|
||||
"STAT4_SAMPLES=" CTIMEOPT_VAL(SQLITE_STAT4_SAMPLES),
|
||||
#endif
|
||||
#ifdef SQLITE_STMTJRNL_SPILL
|
||||
"STMTJRNL_SPILL=" CTIMEOPT_VAL(SQLITE_STMTJRNL_SPILL),
|
||||
#endif
|
||||
#if SQLITE_SUBSTR_COMPATIBILITY
|
||||
"SUBSTR_COMPATIBILITY",
|
||||
#endif
|
||||
#if SQLITE_SYSTEM_MALLOC
|
||||
"SYSTEM_MALLOC",
|
||||
#endif
|
||||
#if SQLITE_TCL
|
||||
"TCL",
|
||||
#endif
|
||||
#if defined(SQLITE_TEMP_STORE) && !defined(SQLITE_TEMP_STORE_xc)
|
||||
#ifdef SQLITE_TEMP_STORE
|
||||
"TEMP_STORE=" CTIMEOPT_VAL(SQLITE_TEMP_STORE),
|
||||
#endif
|
||||
#if SQLITE_TEST
|
||||
@@ -400,64 +690,47 @@ static const char * const azCompileOpt[] = {
|
||||
#endif
|
||||
#if defined(SQLITE_THREADSAFE)
|
||||
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
|
||||
#elif defined(THREADSAFE)
|
||||
"THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
|
||||
#else
|
||||
"THREADSAFE=1"
|
||||
#endif
|
||||
#if SQLITE_UNLINK_AFTER_CLOSE
|
||||
"UNLINK_AFTER_CLOSE",
|
||||
#endif
|
||||
#if SQLITE_UNTESTABLE
|
||||
"UNTESTABLE"
|
||||
"UNTESTABLE",
|
||||
#endif
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
"USER_AUTHENTICATION",
|
||||
#endif
|
||||
#if SQLITE_USE_ALLOCA
|
||||
"USE_ALLOCA",
|
||||
#endif
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
"USER_AUTHENTICATION",
|
||||
#if SQLITE_USE_FCNTL_TRACE
|
||||
"USE_FCNTL_TRACE",
|
||||
#endif
|
||||
#if SQLITE_USE_URI
|
||||
"USE_URI",
|
||||
#endif
|
||||
#if SQLITE_VDBE_COVERAGE
|
||||
"VDBE_COVERAGE",
|
||||
#endif
|
||||
#if SQLITE_WIN32_MALLOC
|
||||
"WIN32_MALLOC",
|
||||
#endif
|
||||
#if SQLITE_ZERO_MALLOC
|
||||
"ZERO_MALLOC"
|
||||
"ZERO_MALLOC",
|
||||
#endif
|
||||
/*
|
||||
** END CODE GENERATED BY tool/mkctime.tcl
|
||||
*/
|
||||
};
|
||||
|
||||
/*
|
||||
** Given the name of a compile-time option, return true if that option
|
||||
** was used and false if not.
|
||||
**
|
||||
** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
|
||||
** is not required for a match.
|
||||
*/
|
||||
int sqlite3_compileoption_used(const char *zOptName){
|
||||
int i, n;
|
||||
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
if( zOptName==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
|
||||
n = sqlite3Strlen30(zOptName);
|
||||
|
||||
/* Since ArraySize(azCompileOpt) is normally in single digits, a
|
||||
** linear search is adequate. No need for a binary search. */
|
||||
for(i=0; i<ArraySize(azCompileOpt); i++){
|
||||
if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
|
||||
&& sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the N-th compile-time option string. If N is out of range,
|
||||
** return a NULL pointer.
|
||||
*/
|
||||
const char *sqlite3_compileoption_get(int N){
|
||||
if( N>=0 && N<ArraySize(azCompileOpt) ){
|
||||
return azCompileOpt[N];
|
||||
}
|
||||
return 0;
|
||||
const char **sqlite3CompileOptions(int *pnOpt){
|
||||
*pnOpt = sizeof(azCompileOpt) / sizeof(azCompileOpt[0]);
|
||||
return (const char**)azCompileOpt;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
|
||||
|
||||
+2
-2
@@ -353,7 +353,7 @@ void sqlite3DeleteFrom(
|
||||
** API function sqlite3_count_changes) to be set incorrectly.
|
||||
**
|
||||
** The "rcauth==SQLITE_OK" terms is the
|
||||
** IMPLEMENATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and
|
||||
** IMPLEMENTATION-OF: R-17228-37124 If the action code is SQLITE_DELETE and
|
||||
** the callback returns SQLITE_IGNORE then the DELETE operation proceeds but
|
||||
** the truncate optimization is disabled and all rows are deleted
|
||||
** individually.
|
||||
@@ -459,7 +459,7 @@ void sqlite3DeleteFrom(
|
||||
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iEphCur, iKey, iPk, nPk);
|
||||
}else{
|
||||
/* Add the rowid of the row to be deleted to the RowSet */
|
||||
nKey = 1; /* OP_Seek always uses a single rowid */
|
||||
nKey = 1; /* OP_DeferredSeek always uses a single rowid */
|
||||
sqlite3VdbeAddOp2(v, OP_RowSetAdd, iRowSet, iKey);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-10
@@ -1488,7 +1488,9 @@ ExprList *sqlite3ExprListAppend(
|
||||
pList->nAlloc *= 2;
|
||||
}
|
||||
pItem = &pList->a[pList->nExpr++];
|
||||
memset(pItem, 0, sizeof(*pItem));
|
||||
assert( offsetof(struct ExprList_item,zName)==sizeof(pItem->pExpr) );
|
||||
assert( offsetof(struct ExprList_item,pExpr)==0 );
|
||||
memset(&pItem->zName,0,sizeof(*pItem)-offsetof(struct ExprList_item,zName));
|
||||
pItem->pExpr = pExpr;
|
||||
return pList;
|
||||
|
||||
@@ -1740,10 +1742,12 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
|
||||
testcase( pExpr->op==TK_AGG_COLUMN );
|
||||
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
|
||||
return WRC_Continue;
|
||||
}else{
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
}
|
||||
/* Fall through */
|
||||
case TK_IF_NULL_ROW:
|
||||
testcase( pExpr->op==TK_IF_NULL_ROW );
|
||||
pWalker->eCode = 0;
|
||||
return WRC_Abort;
|
||||
case TK_VARIABLE:
|
||||
if( pWalker->eCode==5 ){
|
||||
/* Silently convert bound parameters that appear inside of CREATE
|
||||
@@ -1770,10 +1774,12 @@ static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
|
||||
}
|
||||
static int exprIsConst(Expr *p, int initFlag, int iCur){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = initFlag;
|
||||
w.xExprCallback = exprNodeIsConstant;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
w.u.iCur = iCur;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode;
|
||||
@@ -1861,9 +1867,9 @@ static int exprNodeIsConstantOrGroupBy(Walker *pWalker, Expr *pExpr){
|
||||
*/
|
||||
int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = 1;
|
||||
w.xExprCallback = exprNodeIsConstantOrGroupBy;
|
||||
w.xSelectCallback = 0;
|
||||
w.u.pGroupBy = pGroupBy;
|
||||
w.pParse = pParse;
|
||||
sqlite3WalkExpr(&w, p);
|
||||
@@ -1891,10 +1897,12 @@ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
|
||||
*/
|
||||
int sqlite3ExprContainsSubquery(Expr *p){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.eCode = 1;
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.xSelectCallback = selectNodeIsConstant;
|
||||
#ifdef SQLITE_DEBUG
|
||||
w.xSelectCallback2 = sqlite3SelectWalkAssert2;
|
||||
#endif
|
||||
sqlite3WalkExpr(&w, p);
|
||||
return w.eCode==0;
|
||||
}
|
||||
@@ -4899,8 +4907,8 @@ int sqlite3FunctionUsesThisSrc(Expr *pExpr, SrcList *pSrcList){
|
||||
Walker w;
|
||||
struct SrcCount cnt;
|
||||
assert( pExpr->op==TK_AGG_FUNCTION );
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = exprSrcCount;
|
||||
w.xSelectCallback = 0;
|
||||
w.u.pSrcCount = &cnt;
|
||||
cnt.pSrc = pSrcList;
|
||||
cnt.nThis = 0;
|
||||
@@ -5072,10 +5080,14 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
|
||||
return WRC_Continue;
|
||||
}
|
||||
static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
|
||||
UNUSED_PARAMETER(pWalker);
|
||||
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
|
||||
@@ -5088,9 +5100,10 @@ static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){
|
||||
*/
|
||||
void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = analyzeAggregate;
|
||||
w.xSelectCallback = analyzeAggregatesInSelect;
|
||||
w.xSelectCallback2 = analyzeAggregatesInSelectEnd;
|
||||
w.walkerDepth = 0;
|
||||
w.u.pNC = pNC;
|
||||
assert( pNC->pSrcList!=0 );
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
|
||||
+1
-1
@@ -521,10 +521,10 @@ void sqlite3Insert(
|
||||
#endif
|
||||
|
||||
db = pParse->db;
|
||||
memset(&dest, 0, sizeof(dest));
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
dest.iSDParm = 0; /* Suppress a harmless compiler warning */
|
||||
|
||||
/* If the Select object is really just a simple VALUES() list with a
|
||||
** single row (the common case) then keep that one row of values
|
||||
|
||||
+59
@@ -867,6 +867,7 @@ static int binCollFunc(
|
||||
/* EVIDENCE-OF: R-65033-28449 The built-in BINARY collation compares
|
||||
** strings byte by byte using the memcmp() function from the standard C
|
||||
** library. */
|
||||
assert( pKey1 && pKey2 );
|
||||
rc = memcmp(pKey1, pKey2, n);
|
||||
if( rc==0 ){
|
||||
if( padFlag
|
||||
@@ -3337,6 +3338,12 @@ int sqlite3CantopenError(int lineno){
|
||||
return reportError(SQLITE_CANTOPEN, lineno, "cannot open file");
|
||||
}
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3CorruptPgnoError(int lineno, Pgno pgno){
|
||||
char zMsg[100];
|
||||
sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno);
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
return reportError(SQLITE_CORRUPT, lineno, zMsg);
|
||||
}
|
||||
int sqlite3NomemError(int lineno){
|
||||
testcase( sqlite3GlobalConfig.xLog!=0 );
|
||||
return reportError(SQLITE_NOMEM, lineno, "OOM");
|
||||
@@ -4095,3 +4102,55 @@ void sqlite3_snapshot_free(sqlite3_snapshot *pSnapshot){
|
||||
sqlite3_free(pSnapshot);
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
||||
/*
|
||||
** Given the name of a compile-time option, return true if that option
|
||||
** was used and false if not.
|
||||
**
|
||||
** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
|
||||
** is not required for a match.
|
||||
*/
|
||||
int sqlite3_compileoption_used(const char *zOptName){
|
||||
int i, n;
|
||||
int nOpt;
|
||||
const char **azCompileOpt;
|
||||
|
||||
#if SQLITE_ENABLE_API_ARMOR
|
||||
if( zOptName==0 ){
|
||||
(void)SQLITE_MISUSE_BKPT;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
azCompileOpt = sqlite3CompileOptions(&nOpt);
|
||||
|
||||
if( sqlite3StrNICmp(zOptName, "SQLITE_", 7)==0 ) zOptName += 7;
|
||||
n = sqlite3Strlen30(zOptName);
|
||||
|
||||
/* Since nOpt is normally in single digits, a linear search is
|
||||
** adequate. No need for a binary search. */
|
||||
for(i=0; i<nOpt; i++){
|
||||
if( sqlite3StrNICmp(zOptName, azCompileOpt[i], n)==0
|
||||
&& sqlite3IsIdChar((unsigned char)azCompileOpt[i][n])==0
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the N-th compile-time option string. If N is out of range,
|
||||
** return a NULL pointer.
|
||||
*/
|
||||
const char *sqlite3_compileoption_get(int N){
|
||||
int nOpt;
|
||||
const char **azCompileOpt;
|
||||
azCompileOpt = sqlite3CompileOptions(&nOpt);
|
||||
if( N>=0 && N<nOpt ){
|
||||
return azCompileOpt[N];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
||||
|
||||
+18
-25
@@ -3253,7 +3253,7 @@ static int pagerPagecount(Pager *pPager, Pgno *pnPage){
|
||||
nPage = sqlite3WalDbsize(pPager->pWal);
|
||||
|
||||
/* If the number of pages in the database is not available from the
|
||||
** WAL sub-system, determine the page counte based on the size of
|
||||
** WAL sub-system, determine the page count based on the size of
|
||||
** the database file. If the size of the database file is not an
|
||||
** integer multiple of the page-size, round up the result.
|
||||
*/
|
||||
@@ -3304,23 +3304,21 @@ static int pagerOpenWalIfPresent(Pager *pPager){
|
||||
|
||||
if( !pPager->tempFile ){
|
||||
int isWal; /* True if WAL file exists */
|
||||
Pgno nPage; /* Size of the database file */
|
||||
|
||||
rc = pagerPagecount(pPager, &nPage);
|
||||
if( rc ) return rc;
|
||||
if( nPage==0 ){
|
||||
rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
|
||||
if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK;
|
||||
isWal = 0;
|
||||
}else{
|
||||
rc = sqlite3OsAccess(
|
||||
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
|
||||
);
|
||||
}
|
||||
rc = sqlite3OsAccess(
|
||||
pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( isWal ){
|
||||
testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
|
||||
rc = sqlite3PagerOpenWal(pPager, 0);
|
||||
Pgno nPage; /* Size of the database file */
|
||||
|
||||
rc = pagerPagecount(pPager, &nPage);
|
||||
if( rc ) return rc;
|
||||
if( nPage==0 ){
|
||||
rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0);
|
||||
}else{
|
||||
testcase( sqlite3PcachePagecount(pPager->pPCache)==0 );
|
||||
rc = sqlite3PagerOpenWal(pPager, 0);
|
||||
}
|
||||
}else if( pPager->journalMode==PAGER_JOURNALMODE_WAL ){
|
||||
pPager->journalMode = PAGER_JOURNALMODE_DELETE;
|
||||
}
|
||||
@@ -5263,19 +5261,14 @@ int sqlite3PagerSharedLock(Pager *pPager){
|
||||
** detected. The chance of an undetected change is so small that
|
||||
** it can be neglected.
|
||||
*/
|
||||
Pgno nPage = 0;
|
||||
char dbFileVers[sizeof(pPager->dbFileVers)];
|
||||
|
||||
rc = pagerPagecount(pPager, &nPage);
|
||||
if( rc ) goto failed;
|
||||
|
||||
if( nPage>0 ){
|
||||
IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
|
||||
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
|
||||
if( rc!=SQLITE_OK && rc!=SQLITE_IOERR_SHORT_READ ){
|
||||
IOTRACE(("CKVERS %p %d\n", pPager, sizeof(dbFileVers)));
|
||||
rc = sqlite3OsRead(pPager->fd, &dbFileVers, sizeof(dbFileVers), 24);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc!=SQLITE_IOERR_SHORT_READ ){
|
||||
goto failed;
|
||||
}
|
||||
}else{
|
||||
memset(dbFileVers, 0, sizeof(dbFileVers));
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -26,6 +26,7 @@ struct PgHdr {
|
||||
sqlite3_pcache_page *pPage; /* Pcache object page handle */
|
||||
void *pData; /* Page data */
|
||||
void *pExtra; /* Extra content */
|
||||
PCache *pCache; /* PRIVATE: Cache that owns this page */
|
||||
PgHdr *pDirty; /* Transient list of dirty sorted by pgno */
|
||||
Pager *pPager; /* The pager this page is part of */
|
||||
Pgno pgno; /* Page number for this page */
|
||||
@@ -35,12 +36,11 @@ struct PgHdr {
|
||||
u16 flags; /* PGHDR flags defined below */
|
||||
|
||||
/**********************************************************************
|
||||
** Elements above are public. All that follows is private to pcache.c
|
||||
** and should not be accessed by other modules.
|
||||
** Elements above, except pCache, are public. All that follow are
|
||||
** private to pcache.c and should not be accessed by other modules.
|
||||
** pCache is grouped with the public elements for efficiency.
|
||||
*/
|
||||
i16 nRef; /* Number of users of this page */
|
||||
PCache *pCache; /* Cache that owns this page */
|
||||
|
||||
PgHdr *pDirtyNext; /* Next element in list of dirty pages */
|
||||
PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */
|
||||
};
|
||||
|
||||
+10
-18
@@ -1430,37 +1430,29 @@ int sqlite3ResolveExprNames(
|
||||
u16 savedHasAgg;
|
||||
Walker w;
|
||||
|
||||
if( pExpr==0 ) return 0;
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
{
|
||||
Parse *pParse = pNC->pParse;
|
||||
if( sqlite3ExprCheckHeight(pParse, pExpr->nHeight+pNC->pParse->nHeight) ){
|
||||
return 1;
|
||||
}
|
||||
pParse->nHeight += pExpr->nHeight;
|
||||
}
|
||||
#endif
|
||||
if( pExpr==0 ) return SQLITE_OK;
|
||||
savedHasAgg = pNC->ncFlags & (NC_HasAgg|NC_MinMaxAgg);
|
||||
pNC->ncFlags &= ~(NC_HasAgg|NC_MinMaxAgg);
|
||||
w.pParse = pNC->pParse;
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
w.xSelectCallback2 = 0;
|
||||
w.walkerDepth = 0;
|
||||
w.eCode = 0;
|
||||
w.u.pNC = pNC;
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
w.pParse->nHeight += pExpr->nHeight;
|
||||
if( sqlite3ExprCheckHeight(w.pParse, w.pParse->nHeight) ){
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
sqlite3WalkExpr(&w, pExpr);
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
pNC->pParse->nHeight -= pExpr->nHeight;
|
||||
w.pParse->nHeight -= pExpr->nHeight;
|
||||
#endif
|
||||
if( pNC->nErr>0 || w.pParse->nErr>0 ){
|
||||
ExprSetProperty(pExpr, EP_Error);
|
||||
}
|
||||
if( pNC->ncFlags & NC_HasAgg ){
|
||||
ExprSetProperty(pExpr, EP_Agg);
|
||||
}
|
||||
pNC->ncFlags |= savedHasAgg;
|
||||
return ExprHasProperty(pExpr, EP_Error);
|
||||
return pNC->nErr>0 || w.pParse->nErr>0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1501,9 +1493,9 @@ void sqlite3ResolveSelectNames(
|
||||
Walker w;
|
||||
|
||||
assert( p!=0 );
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = resolveExprStep;
|
||||
w.xSelectCallback = resolveSelectStep;
|
||||
w.xSelectCallback2 = 0;
|
||||
w.pParse = pParse;
|
||||
w.u.pNC = pOuterNC;
|
||||
sqlite3WalkSelect(&w, p);
|
||||
|
||||
+34
-4
@@ -1031,7 +1031,7 @@ static void selectInnerLoop(
|
||||
** X extra columns.
|
||||
*/
|
||||
KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
|
||||
int nExtra = (N+X)*(sizeof(CollSeq*)+1);
|
||||
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];
|
||||
@@ -3511,6 +3511,14 @@ static int flattenSubquery(
|
||||
return 0; /* Restriction (3) */
|
||||
}
|
||||
}
|
||||
#ifdef SQLITE_EXTRA_IFNULLROW
|
||||
else if( iFrom>0 && !isAgg ){
|
||||
/* Setting isLeftJoin to -1 causes OP_IfNullRow opcodes to be generated for
|
||||
** every reference to any result column from subquery in a join, even though
|
||||
** they are not necessary. This will stress-test the OP_IfNullRow opcode. */
|
||||
isLeftJoin = -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Restriction 17: If the sub-query is a compound SELECT, then it must
|
||||
** use only the UNION ALL operator. And none of the simple select queries
|
||||
@@ -3764,7 +3772,7 @@ static int flattenSubquery(
|
||||
pSub->pOrderBy = 0;
|
||||
}
|
||||
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
|
||||
if( isLeftJoin ){
|
||||
if( isLeftJoin>0 ){
|
||||
setJoinExpr(pWhere, iNewParent);
|
||||
}
|
||||
if( subqueryIsAgg ){
|
||||
@@ -4602,6 +4610,25 @@ int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
/*
|
||||
** No-op routine for the parse-tree walker for SELECT statements.
|
||||
** subquery in the parser tree.
|
||||
*/
|
||||
int sqlite3SelectWalkNoop(Walker *NotUsed, Select *NotUsed2){
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
#if SQLITE_DEBUG
|
||||
/*
|
||||
** Always assert. This xSelectCallback2 implementation proves that the
|
||||
** xSelectCallback2 is never invoked.
|
||||
*/
|
||||
void sqlite3SelectWalkAssert2(Walker *NotUsed, Select *NotUsed2){
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
assert( 0 );
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
** This routine "expands" a SELECT statement and all of its subqueries.
|
||||
** For additional information on what it means to "expand" a SELECT
|
||||
@@ -4617,11 +4644,11 @@ int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
|
||||
*/
|
||||
static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.pParse = pParse;
|
||||
if( pParse->hasCompound ){
|
||||
w.xSelectCallback = convertCompoundSelectToSubquery;
|
||||
w.xSelectCallback2 = 0;
|
||||
sqlite3WalkSelect(&w, pSelect);
|
||||
}
|
||||
w.xSelectCallback = selectExpander;
|
||||
@@ -4681,7 +4708,7 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
|
||||
static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
Walker w;
|
||||
memset(&w, 0, sizeof(w));
|
||||
w.xSelectCallback = sqlite3SelectWalkNoop;
|
||||
w.xSelectCallback2 = selectAddSubqueryTypeInfo;
|
||||
w.xExprCallback = sqlite3ExprWalkNoop;
|
||||
w.pParse = pParse;
|
||||
@@ -5262,6 +5289,9 @@ int sqlite3Select(
|
||||
pPrior = isSelfJoinView(pTabList, pItem);
|
||||
if( pPrior ){
|
||||
sqlite3VdbeAddOp2(v, OP_OpenDup, pItem->iCursor, pPrior->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, pPrior->iSelectId);
|
||||
assert( pPrior->pSelect!=0 );
|
||||
pSub->nSelectRow = pPrior->pSelect->nSelectRow;
|
||||
}else{
|
||||
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
|
||||
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
|
||||
|
||||
+264
-145
@@ -18,11 +18,25 @@
|
||||
#endif
|
||||
|
||||
/*
|
||||
** If requested, include the SQLite compiler options file for MSVC.
|
||||
** Warning pragmas copied from msvc.h in the core.
|
||||
*/
|
||||
#if defined(INCLUDE_MSVC_H)
|
||||
#include "msvc.h"
|
||||
#endif
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning(disable : 4054)
|
||||
#pragma warning(disable : 4055)
|
||||
#pragma warning(disable : 4100)
|
||||
#pragma warning(disable : 4127)
|
||||
#pragma warning(disable : 4130)
|
||||
#pragma warning(disable : 4152)
|
||||
#pragma warning(disable : 4189)
|
||||
#pragma warning(disable : 4206)
|
||||
#pragma warning(disable : 4210)
|
||||
#pragma warning(disable : 4232)
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4305)
|
||||
#pragma warning(disable : 4306)
|
||||
#pragma warning(disable : 4702)
|
||||
#pragma warning(disable : 4706)
|
||||
#endif /* defined(_MSC_VER) */
|
||||
|
||||
/*
|
||||
** No support for loadable extensions in VxWorks.
|
||||
@@ -495,6 +509,18 @@ static int strlen30(const char *z){
|
||||
return 0x3fffffff & (int)(z2 - z);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the length of a string in characters. Multibyte UTF8 characters
|
||||
** count as a single character.
|
||||
*/
|
||||
static int strlenChar(const char *z){
|
||||
int n = 0;
|
||||
while( *z ){
|
||||
if( (0xc0&*(z++))!=0x80 ) n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine reads a line of text from FILE in, stores
|
||||
** the text in memory obtained from malloc() and returns a pointer
|
||||
@@ -703,6 +729,61 @@ static char quoteChar(const char *zName){
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** SQL function: shell_add_schema(S,X)
|
||||
**
|
||||
** Add the schema name X to the CREATE statement in S and return the result.
|
||||
** Examples:
|
||||
**
|
||||
** CREATE TABLE t1(x) -> CREATE TABLE xyz.t1(x);
|
||||
**
|
||||
** Also works on
|
||||
**
|
||||
** CREATE INDEX
|
||||
** CREATE UNIQUE INDEX
|
||||
** CREATE VIEW
|
||||
** CREATE TRIGGER
|
||||
** CREATE VIRTUAL TABLE
|
||||
**
|
||||
** This UDF is used by the .schema command to insert the schema name of
|
||||
** attached databases into the middle of the sqlite_master.sql field.
|
||||
*/
|
||||
static void shellAddSchemaName(
|
||||
sqlite3_context *pCtx,
|
||||
int nVal,
|
||||
sqlite3_value **apVal
|
||||
){
|
||||
static const char *aPrefix[] = {
|
||||
"TABLE",
|
||||
"INDEX",
|
||||
"UNIQUE INDEX",
|
||||
"VIEW",
|
||||
"TRIGGER",
|
||||
"VIRTUAL TABLE"
|
||||
};
|
||||
int i = 0;
|
||||
const char *zIn = (const char*)sqlite3_value_text(apVal[0]);
|
||||
const char *zSchema = (const char*)sqlite3_value_text(apVal[1]);
|
||||
assert( nVal==2 );
|
||||
if( zIn!=0 && strncmp(zIn, "CREATE ", 7)==0 ){
|
||||
for(i=0; i<sizeof(aPrefix)/sizeof(aPrefix[0]); i++){
|
||||
int n = strlen30(aPrefix[i]);
|
||||
if( strncmp(zIn+7, aPrefix[i], n)==0 && zIn[n+7]==' ' ){
|
||||
char cQuote = quoteChar(zSchema);
|
||||
char *z;
|
||||
if( cQuote ){
|
||||
z = sqlite3_mprintf("%.*s \"%w\".%s", n+7, zIn, zSchema, zIn+n+8);
|
||||
}else{
|
||||
z = sqlite3_mprintf("%.*s %s.%s", n+7, zIn, zSchema, zIn+n+8);
|
||||
}
|
||||
sqlite3_result_text(pCtx, z, -1, sqlite3_free);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
sqlite3_result_value(pCtx, apVal[0]);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
** SHA3 hash implementation copied from ../ext/misc/shathree.c
|
||||
*/
|
||||
@@ -1163,7 +1244,7 @@ static unsigned char *SHA3Final(SHA3Context *p){
|
||||
** Implementation of the sha3(X,SIZE) function.
|
||||
**
|
||||
** Return a BLOB which is the SIZE-bit SHA3 hash of X. The default
|
||||
** size is 256. If X is a BLOB, it is hashed as is.
|
||||
** size is 256. If X is a BLOB, it is hashed as is.
|
||||
** For all other non-NULL types of input, X is converted into a UTF-8 string
|
||||
** and the string is hashed without the trailing 0x00 terminator. The hash
|
||||
** of a NULL value is NULL.
|
||||
@@ -1903,9 +1984,9 @@ static int shell_callback(
|
||||
w = 0;
|
||||
}
|
||||
if( w==0 ){
|
||||
w = strlen30(azCol[i] ? azCol[i] : "");
|
||||
w = strlenChar(azCol[i] ? azCol[i] : "");
|
||||
if( w<10 ) w = 10;
|
||||
n = strlen30(azArg && azArg[i] ? azArg[i] : p->nullValue);
|
||||
n = strlenChar(azArg && azArg[i] ? azArg[i] : p->nullValue);
|
||||
if( w<n ) w = n;
|
||||
}
|
||||
if( i<ArraySize(p->actualWidth) ){
|
||||
@@ -1940,8 +2021,8 @@ static int shell_callback(
|
||||
}else{
|
||||
w = 10;
|
||||
}
|
||||
if( p->cMode==MODE_Explain && azArg[i] && strlen30(azArg[i])>w ){
|
||||
w = strlen30(azArg[i]);
|
||||
if( p->cMode==MODE_Explain && azArg[i] && strlenChar(azArg[i])>w ){
|
||||
w = strlenChar(azArg[i]);
|
||||
}
|
||||
if( i==1 && p->aiIndent && p->pStmt ){
|
||||
if( p->iIndent<p->nIndent ){
|
||||
@@ -2997,7 +3078,7 @@ static char **tableColumnList(ShellState *p, const char *zTab){
|
||||
nPK++;
|
||||
if( nPK==1
|
||||
&& sqlite3_stricmp((const char*)sqlite3_column_text(pStmt,2),
|
||||
"INTEGER")==0
|
||||
"INTEGER")==0
|
||||
){
|
||||
isIPK = 1;
|
||||
}else{
|
||||
@@ -3234,6 +3315,7 @@ static char zHelp[] =
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".binary on|off Turn binary output on or off. Default OFF\n"
|
||||
".cd DIRECTORY Change the working directory to DIRECTORY\n"
|
||||
".changes on|off Show number of rows changed by SQL\n"
|
||||
".check GLOB Fail if output since .testcase does not match\n"
|
||||
".clone NEWDB Clone data into NEWDB from the existing database\n"
|
||||
@@ -3279,8 +3361,8 @@ static char zHelp[] =
|
||||
" tcl TCL list elements\n"
|
||||
".nullvalue STRING Use STRING in place of NULL values\n"
|
||||
".once FILENAME Output for the next SQL command only to FILENAME\n"
|
||||
".open ?--new? ?FILE? Close existing database and reopen FILE\n"
|
||||
" The --new starts with an empty file\n"
|
||||
".open ?OPTIONS? ?FILE? Close existing database and reopen FILE\n"
|
||||
" The --new option starts with an empty file\n"
|
||||
".output ?FILENAME? Send output to FILENAME or stdout\n"
|
||||
".print STRING... Print literal STRING\n"
|
||||
".prompt MAIN CONTINUE Replace the standard prompts\n"
|
||||
@@ -3345,8 +3427,8 @@ static int process_input(ShellState *p, FILE *in);
|
||||
|
||||
/*
|
||||
** Read the content of file zName into memory obtained from sqlite3_malloc64()
|
||||
** and return a pointer to the buffer. The caller is responsible for freeing
|
||||
** the memory.
|
||||
** and return a pointer to the buffer. The caller is responsible for freeing
|
||||
** the memory.
|
||||
**
|
||||
** If parameter pnByte is not NULL, (*pnByte) is set to the number of bytes
|
||||
** read.
|
||||
@@ -3509,6 +3591,9 @@ static void open_db(ShellState *p, int keepAlive){
|
||||
sha3QueryFunc, 0, 0);
|
||||
sqlite3_create_function(p->db, "sha3_query", 2, SQLITE_UTF8, 0,
|
||||
sha3QueryFunc, 0, 0);
|
||||
sqlite3_create_function(p->db, "shell_add_schema", 2, SQLITE_UTF8, 0,
|
||||
shellAddSchemaName, 0, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4353,15 +4438,15 @@ int shellDeleteFile(const char *zFilename){
|
||||
** fkey_collate_clause('parent-tab', 'parent-col', 'child-tab', 'child-col')
|
||||
**
|
||||
** If either of the named tables or columns do not exist, this function
|
||||
** returns an empty string. An empty string is also returned if both tables
|
||||
** returns an empty string. An empty string is also returned if both tables
|
||||
** and columns exist but have the same default collation sequence. Or,
|
||||
** if both exist but the default collation sequences are different, this
|
||||
** function returns the string " COLLATE <parent-collation>", where
|
||||
** <parent-collation> is the default collation sequence of the parent column.
|
||||
*/
|
||||
static void shellFkeyCollateClause(
|
||||
sqlite3_context *pCtx,
|
||||
int nVal,
|
||||
sqlite3_context *pCtx,
|
||||
int nVal,
|
||||
sqlite3_value **apVal
|
||||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(pCtx);
|
||||
@@ -4372,7 +4457,7 @@ static void shellFkeyCollateClause(
|
||||
const char *zChildCol;
|
||||
const char *zChildSeq = 0; /* Initialize to avoid false-positive warning */
|
||||
int rc;
|
||||
|
||||
|
||||
assert( nVal==4 );
|
||||
zParent = (const char*)sqlite3_value_text(apVal[0]);
|
||||
zParentCol = (const char*)sqlite3_value_text(apVal[1]);
|
||||
@@ -4494,7 +4579,7 @@ static int lintFkeyIndexes(
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Register the fkey_collate_clause() SQL function */
|
||||
rc = sqlite3_create_function(db, "fkey_collate_clause", 4, SQLITE_UTF8,
|
||||
0, shellFkeyCollateClause, 0, 0
|
||||
@@ -4537,9 +4622,9 @@ static int lintFkeyIndexes(
|
||||
raw_printf(stderr, "Error: internal error");
|
||||
break;
|
||||
}else{
|
||||
if( bGroupByParent
|
||||
if( bGroupByParent
|
||||
&& (bVerbose || res==0)
|
||||
&& (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
|
||||
&& (zPrev==0 || sqlite3_stricmp(zParent, zPrev))
|
||||
){
|
||||
raw_printf(out, "-- Parent table %s\n", zParent);
|
||||
sqlite3_free(zPrev);
|
||||
@@ -4549,7 +4634,7 @@ static int lintFkeyIndexes(
|
||||
if( res==0 ){
|
||||
raw_printf(out, "%s%s --> %s\n", zIndent, zCI, zTarget);
|
||||
}else if( bVerbose ){
|
||||
raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
|
||||
raw_printf(out, "%s/* no extra indexes required for %s -> %s */\n",
|
||||
zIndent, zFrom, zTarget
|
||||
);
|
||||
}
|
||||
@@ -4731,6 +4816,25 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='c' && strcmp(azArg[0],"cd")==0 ){
|
||||
if( nArg==2 ){
|
||||
#if defined(_WIN32) || defined(WIN32)
|
||||
wchar_t *z = sqlite3_win32_utf8_to_unicode(azArg[1]);
|
||||
rc = !SetCurrentDirectoryW(z);
|
||||
sqlite3_free(z);
|
||||
#else
|
||||
rc = chdir(azArg[1]);
|
||||
#endif
|
||||
if( rc ){
|
||||
utf8_printf(stderr, "Cannot change to directory \"%s\"\n", azArg[1]);
|
||||
rc = 1;
|
||||
}
|
||||
}else{
|
||||
raw_printf(stderr, "Usage: .cd DIRECTORY\n");
|
||||
rc = 1;
|
||||
}
|
||||
}else
|
||||
|
||||
/* The undocumented ".breakpoint" command causes a call to the no-op
|
||||
** routine named test_breakpoint().
|
||||
*/
|
||||
@@ -5643,12 +5747,17 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "schema", n)==0 ){
|
||||
ShellText sSelect;
|
||||
ShellState data;
|
||||
char *zErrMsg = 0;
|
||||
const char *zDiv = 0;
|
||||
int iSchema = 0;
|
||||
|
||||
open_db(p, 0);
|
||||
memcpy(&data, p, sizeof(data));
|
||||
data.showHeader = 0;
|
||||
data.cMode = data.mode = MODE_Semi;
|
||||
initText(&sSelect);
|
||||
if( nArg>=2 && optionMatch(azArg[1], "indent") ){
|
||||
data.cMode = data.mode = MODE_Pretty;
|
||||
nArg--;
|
||||
@@ -5686,33 +5795,62 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
callback(&data, 1, new_argv, new_colv);
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
char *zSql;
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT sql FROM "
|
||||
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
|
||||
" FROM sqlite_master UNION ALL"
|
||||
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
|
||||
"WHERE lower(tbl_name) LIKE %Q"
|
||||
" AND type!='meta' AND sql NOTNULL "
|
||||
"ORDER BY rowid", azArg[1]);
|
||||
rc = sqlite3_exec(p->db, zSql, callback, &data, &zErrMsg);
|
||||
sqlite3_free(zSql);
|
||||
zDiv = "(";
|
||||
}
|
||||
}else if( nArg==1 ){
|
||||
rc = sqlite3_exec(p->db,
|
||||
"SELECT sql FROM "
|
||||
" (SELECT sql sql, type type, tbl_name tbl_name, name name, rowid x"
|
||||
" FROM sqlite_master UNION ALL"
|
||||
" SELECT sql, type, tbl_name, name, rowid FROM sqlite_temp_master) "
|
||||
"WHERE type!='meta' AND sql NOTNULL AND name NOT LIKE 'sqlite_%' "
|
||||
"ORDER BY rowid",
|
||||
callback, &data, &zErrMsg
|
||||
);
|
||||
zDiv = "(";
|
||||
}else{
|
||||
raw_printf(stderr, "Usage: .schema ?--indent? ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
if( zDiv ){
|
||||
sqlite3_stmt *pStmt = 0;
|
||||
sqlite3_prepare_v2(p->db, "SELECT name FROM pragma_database_list",
|
||||
-1, &pStmt, 0);
|
||||
appendText(&sSelect, "SELECT sql FROM", 0);
|
||||
iSchema = 0;
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
const char *zDb = (const char*)sqlite3_column_text(pStmt, 0);
|
||||
char zScNum[30];
|
||||
sqlite3_snprintf(sizeof(zScNum), zScNum, "%d", ++iSchema);
|
||||
appendText(&sSelect, zDiv, 0);
|
||||
zDiv = " UNION ALL ";
|
||||
if( strcmp(zDb, "main")!=0 ){
|
||||
appendText(&sSelect, "SELECT shell_add_schema(sql,", 0);
|
||||
appendText(&sSelect, zDb, '"');
|
||||
appendText(&sSelect, ") AS sql, type, tbl_name, name, rowid,", 0);
|
||||
appendText(&sSelect, zScNum, 0);
|
||||
appendText(&sSelect, " AS snum, ", 0);
|
||||
appendText(&sSelect, zDb, '\'');
|
||||
appendText(&sSelect, " AS sname FROM ", 0);
|
||||
appendText(&sSelect, zDb, '"');
|
||||
appendText(&sSelect, ".sqlite_master", 0);
|
||||
}else{
|
||||
appendText(&sSelect, "SELECT sql, type, tbl_name, name, rowid, ", 0);
|
||||
appendText(&sSelect, zScNum, 0);
|
||||
appendText(&sSelect, " AS snum, 'main' AS sname FROM sqlite_master",0);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
appendText(&sSelect, ") WHERE ", 0);
|
||||
if( nArg>1 ){
|
||||
char *zQarg = sqlite3_mprintf("%Q", azArg[1]);
|
||||
if( strchr(azArg[1], '.') ){
|
||||
appendText(&sSelect, "lower(printf('%s.%s',sname,tbl_name))", 0);
|
||||
}else{
|
||||
appendText(&sSelect, "lower(tbl_name)", 0);
|
||||
}
|
||||
appendText(&sSelect, strchr(azArg[1], '*') ? " GLOB " : " LIKE ", 0);
|
||||
appendText(&sSelect, zQarg, 0);
|
||||
appendText(&sSelect, " AND ", 0);
|
||||
sqlite3_free(zQarg);
|
||||
}
|
||||
appendText(&sSelect, "type!='meta' AND sql IS NOT NULL"
|
||||
" ORDER BY snum, rowid", 0);
|
||||
rc = sqlite3_exec(p->db, sSelect.z, callback, &data, &zErrMsg);
|
||||
freeText(&sSelect);
|
||||
}
|
||||
if( zErrMsg ){
|
||||
utf8_printf(stderr,"Error: %s\n", zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
@@ -5954,19 +6092,11 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
int bIsInit = 0; /* True to initialize the SELFTEST table */
|
||||
int bVerbose = 0; /* Verbose output */
|
||||
int bSelftestExists; /* True if SELFTEST already exists */
|
||||
char **azTest = 0; /* Content of the SELFTEST table */
|
||||
int nRow = 0; /* Number of rows in the SELFTEST table */
|
||||
int nCol = 4; /* Number of columns in the SELFTEST table */
|
||||
int i; /* Loop counter */
|
||||
int i, k; /* Loop counters */
|
||||
int nTest = 0; /* Number of tests runs */
|
||||
int nErr = 0; /* Number of errors seen */
|
||||
ShellText str; /* Answer for a query */
|
||||
static char *azDefaultTest[] = {
|
||||
0, 0, 0, 0,
|
||||
"0", "memo", "Missing SELFTEST table - default checks only", "",
|
||||
"1", "run", "PRAGMA integrity_check", "ok"
|
||||
};
|
||||
static const int nDefaultRow = 2;
|
||||
sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */
|
||||
|
||||
open_db(p,0);
|
||||
for(i=1; i<nArg; i++){
|
||||
@@ -5996,70 +6126,71 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
createSelftestTable(p);
|
||||
bSelftestExists = 1;
|
||||
}
|
||||
if( bSelftestExists ){
|
||||
rc = sqlite3_get_table(p->db,
|
||||
"SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
|
||||
&azTest, &nRow, &nCol, 0);
|
||||
initText(&str);
|
||||
appendText(&str, "x", 0);
|
||||
for(k=bSelftestExists; k>=0; k--){
|
||||
if( k==1 ){
|
||||
rc = sqlite3_prepare_v2(p->db,
|
||||
"SELECT tno,op,cmd,ans FROM selftest ORDER BY tno",
|
||||
-1, &pStmt, 0);
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(p->db,
|
||||
"VALUES(0,'memo','Missing SELFTEST table - default checks only',''),"
|
||||
" (1,'run','PRAGMA integrity_check','ok')",
|
||||
-1, &pStmt, 0);
|
||||
}
|
||||
if( rc ){
|
||||
raw_printf(stderr, "Error querying the selftest table\n");
|
||||
rc = 1;
|
||||
sqlite3_free_table(azTest);
|
||||
sqlite3_finalize(pStmt);
|
||||
goto meta_command_exit;
|
||||
}else if( nRow==0 ){
|
||||
sqlite3_free_table(azTest);
|
||||
azTest = azDefaultTest;
|
||||
nRow = nDefaultRow;
|
||||
}
|
||||
}else{
|
||||
azTest = azDefaultTest;
|
||||
nRow = nDefaultRow;
|
||||
}
|
||||
initText(&str);
|
||||
appendText(&str, "x", 0);
|
||||
for(i=1; i<=nRow; i++){
|
||||
int tno = atoi(azTest[i*nCol]);
|
||||
const char *zOp = azTest[i*nCol+1];
|
||||
const char *zSql = azTest[i*nCol+2];
|
||||
const char *zAns = azTest[i*nCol+3];
|
||||
|
||||
if( bVerbose>0 ){
|
||||
char *zQuote = sqlite3_mprintf("%q", zSql);
|
||||
printf("%d: %s %s\n", tno, zOp, zSql);
|
||||
sqlite3_free(zQuote);
|
||||
}
|
||||
if( strcmp(zOp,"memo")==0 ){
|
||||
utf8_printf(p->out, "%s\n", zSql);
|
||||
}else
|
||||
if( strcmp(zOp,"run")==0 ){
|
||||
char *zErrMsg = 0;
|
||||
str.n = 0;
|
||||
str.z[0] = 0;
|
||||
rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
|
||||
nTest++;
|
||||
if( bVerbose ){
|
||||
utf8_printf(p->out, "Result: %s\n", str.z);
|
||||
for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){
|
||||
int tno = sqlite3_column_int(pStmt, 0);
|
||||
const char *zOp = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
const char *zSql = (const char*)sqlite3_column_text(pStmt, 2);
|
||||
const char *zAns = (const char*)sqlite3_column_text(pStmt, 3);
|
||||
|
||||
k = 0;
|
||||
if( bVerbose>0 ){
|
||||
char *zQuote = sqlite3_mprintf("%q", zSql);
|
||||
printf("%d: %s %s\n", tno, zOp, zSql);
|
||||
sqlite3_free(zQuote);
|
||||
}
|
||||
if( rc || zErrMsg ){
|
||||
nErr++;
|
||||
if( strcmp(zOp,"memo")==0 ){
|
||||
utf8_printf(p->out, "%s\n", zSql);
|
||||
}else
|
||||
if( strcmp(zOp,"run")==0 ){
|
||||
char *zErrMsg = 0;
|
||||
str.n = 0;
|
||||
str.z[0] = 0;
|
||||
rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg);
|
||||
nTest++;
|
||||
if( bVerbose ){
|
||||
utf8_printf(p->out, "Result: %s\n", str.z);
|
||||
}
|
||||
if( rc || zErrMsg ){
|
||||
nErr++;
|
||||
rc = 1;
|
||||
utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
}else if( strcmp(zAns,str.z)!=0 ){
|
||||
nErr++;
|
||||
rc = 1;
|
||||
utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
|
||||
utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
|
||||
}
|
||||
}else
|
||||
{
|
||||
utf8_printf(stderr,
|
||||
"Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
|
||||
rc = 1;
|
||||
utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg);
|
||||
sqlite3_free(zErrMsg);
|
||||
}else if( strcmp(zAns,str.z)!=0 ){
|
||||
nErr++;
|
||||
rc = 1;
|
||||
utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns);
|
||||
utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z);
|
||||
break;
|
||||
}
|
||||
}else
|
||||
{
|
||||
utf8_printf(stderr,
|
||||
"Unknown operation \"%s\" on selftest line %d\n", zOp, tno);
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* End loop over rows of content from SELFTEST */
|
||||
sqlite3_finalize(pStmt);
|
||||
} /* End loop over k */
|
||||
freeText(&str);
|
||||
if( azTest!=azDefaultTest ) sqlite3_free_table(azTest);
|
||||
utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest);
|
||||
}else
|
||||
|
||||
@@ -6099,8 +6230,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
if( strcmp(z,"schema")==0 ){
|
||||
bSchema = 1;
|
||||
}else
|
||||
if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
|
||||
|| strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
|
||||
if( strcmp(z,"sha3-224")==0 || strcmp(z,"sha3-256")==0
|
||||
|| strcmp(z,"sha3-384")==0 || strcmp(z,"sha3-512")==0
|
||||
){
|
||||
iSize = atoi(&z[5]);
|
||||
}else
|
||||
@@ -6268,59 +6399,47 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_stmt *pStmt;
|
||||
char **azResult;
|
||||
int nRow, nAlloc;
|
||||
char *zSql = 0;
|
||||
int ii;
|
||||
ShellText s;
|
||||
initText(&s);
|
||||
open_db(p, 0);
|
||||
rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0);
|
||||
if( rc ) return shellDatabaseError(p->db);
|
||||
|
||||
/* Create an SQL statement to query for the list of tables in the
|
||||
** main and all attached databases where the table name matches the
|
||||
** LIKE pattern bound to variable "?1". */
|
||||
if( c=='t' ){
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT name FROM sqlite_master"
|
||||
" WHERE type IN ('table','view')"
|
||||
" AND name NOT LIKE 'sqlite_%%'"
|
||||
" AND name LIKE ?1");
|
||||
}else if( nArg>2 ){
|
||||
if( nArg>2 && c=='i' ){
|
||||
/* It is an historical accident that the .indexes command shows an error
|
||||
** when called with the wrong number of arguments whereas the .tables
|
||||
** command does not. */
|
||||
raw_printf(stderr, "Usage: .indexes ?LIKE-PATTERN?\n");
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}else{
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT name FROM sqlite_master"
|
||||
" WHERE type='index'"
|
||||
" AND tbl_name LIKE ?1");
|
||||
}
|
||||
for(ii=0; zSql && sqlite3_step(pStmt)==SQLITE_ROW; ii++){
|
||||
for(ii=0; sqlite3_step(pStmt)==SQLITE_ROW; ii++){
|
||||
const char *zDbName = (const char*)sqlite3_column_text(pStmt, 1);
|
||||
if( zDbName==0 || ii==0 ) continue;
|
||||
if( c=='t' ){
|
||||
zSql = sqlite3_mprintf(
|
||||
"%z UNION ALL "
|
||||
"SELECT '%q.' || name FROM \"%w\".sqlite_master"
|
||||
" WHERE type IN ('table','view')"
|
||||
" AND name NOT LIKE 'sqlite_%%'"
|
||||
" AND name LIKE ?1", zSql, zDbName, zDbName);
|
||||
if( zDbName==0 ) continue;
|
||||
if( s.z && s.z[0] ) appendText(&s, " UNION ALL ", 0);
|
||||
if( sqlite3_stricmp(zDbName, "main")==0 ){
|
||||
appendText(&s, "SELECT name FROM ", 0);
|
||||
}else{
|
||||
zSql = sqlite3_mprintf(
|
||||
"%z UNION ALL "
|
||||
"SELECT '%q.' || name FROM \"%w\".sqlite_master"
|
||||
" WHERE type='index'"
|
||||
" AND tbl_name LIKE ?1", zSql, zDbName, zDbName);
|
||||
appendText(&s, "SELECT ", 0);
|
||||
appendText(&s, zDbName, '\'');
|
||||
appendText(&s, "||'.'||name FROM ", 0);
|
||||
}
|
||||
appendText(&s, zDbName, '"');
|
||||
appendText(&s, ".sqlite_master ", 0);
|
||||
if( c=='t' ){
|
||||
appendText(&s," WHERE type IN ('table','view')"
|
||||
" AND name NOT LIKE 'sqlite_%'"
|
||||
" AND name LIKE ?1", 0);
|
||||
}else{
|
||||
appendText(&s," WHERE type='index'"
|
||||
" AND tbl_name LIKE ?1", 0);
|
||||
}
|
||||
}
|
||||
rc = sqlite3_finalize(pStmt);
|
||||
if( zSql && rc==SQLITE_OK ){
|
||||
zSql = sqlite3_mprintf("%z ORDER BY 1", zSql);
|
||||
if( zSql ) rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
if( !zSql ) return shellNomemError();
|
||||
appendText(&s, " ORDER BY 1", 0);
|
||||
rc = sqlite3_prepare_v2(p->db, s.z, -1, &pStmt, 0);
|
||||
freeText(&s);
|
||||
if( rc ) return shellDatabaseError(p->db);
|
||||
|
||||
/* Run the SQL statement prepared by the above block. Store the results
|
||||
|
||||
+10
-1
@@ -5620,7 +5620,9 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
|
||||
** ^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
|
||||
** does not.
|
||||
** does not. If the table name parameter T in a call to
|
||||
** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is
|
||||
** undefined behavior.
|
||||
**
|
||||
** ^The column is identified by the second, third and fourth parameters to
|
||||
** this function. ^(The second parameter is either the name of the database
|
||||
@@ -7133,6 +7135,12 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
** used as a proxy for the total work done by the prepared statement.
|
||||
** If the number of virtual machine operations exceeds 2147483647
|
||||
** then the value returned by this statement status code is undefined.
|
||||
**
|
||||
** [[SQLITE_STMTSTATUS_MEMUSED]] <dt>SQLITE_STMTSTATUS_MEMUSED</dt>
|
||||
** <dd>^This is the approximate number of bytes of heap memory
|
||||
** used to store the prepared statement. ^This value is not actually
|
||||
** a counter, and so the resetFlg parameter to sqlite3_stmt_status()
|
||||
** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
@@ -7140,6 +7148,7 @@ int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
|
||||
#define SQLITE_STMTSTATUS_SORT 2
|
||||
#define SQLITE_STMTSTATUS_AUTOINDEX 3
|
||||
#define SQLITE_STMTSTATUS_VM_STEP 4
|
||||
#define SQLITE_STMTSTATUS_MEMUSED 5
|
||||
|
||||
/*
|
||||
** CAPI3REF: Custom Page Cache Object
|
||||
|
||||
+16
-5
@@ -274,6 +274,11 @@
|
||||
**
|
||||
** Older versions of SQLite used an optional THREADSAFE macro.
|
||||
** We support that for legacy.
|
||||
**
|
||||
** To ensure that the correct value of "THREADSAFE" is reported when querying
|
||||
** for compile-time options at runtime (e.g. "PRAGMA compile_options"), this
|
||||
** logic is partially replicated in ctime.c. If it is updated here, it should
|
||||
** also be updated there.
|
||||
*/
|
||||
#if !defined(SQLITE_THREADSAFE)
|
||||
# if defined(THREADSAFE)
|
||||
@@ -589,7 +594,6 @@
|
||||
*/
|
||||
#ifndef SQLITE_TEMP_STORE
|
||||
# define SQLITE_TEMP_STORE 1
|
||||
# define SQLITE_TEMP_STORE_xc 1 /* Exclude from ctime.c */
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -890,7 +894,6 @@ typedef INT16_TYPE LogEst;
|
||||
# else
|
||||
# define SQLITE_MAX_MMAP_SIZE 0
|
||||
# endif
|
||||
# define SQLITE_MAX_MMAP_SIZE_xc 1 /* exclude from ctime.c */
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -900,7 +903,6 @@ typedef INT16_TYPE LogEst;
|
||||
*/
|
||||
#ifndef SQLITE_DEFAULT_MMAP_SIZE
|
||||
# define SQLITE_DEFAULT_MMAP_SIZE 0
|
||||
# define SQLITE_DEFAULT_MMAP_SIZE_xc 1 /* Exclude from ctime.c */
|
||||
#endif
|
||||
#if SQLITE_DEFAULT_MMAP_SIZE>SQLITE_MAX_MMAP_SIZE
|
||||
# undef SQLITE_DEFAULT_MMAP_SIZE
|
||||
@@ -2364,7 +2366,7 @@ struct Expr {
|
||||
#define EP_FromJoin 0x000001 /* Originates in ON/USING clause of outer join */
|
||||
#define EP_Agg 0x000002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x000004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x000008 /* Expression contains one or more errors */
|
||||
/* 0x000008 // available for use */
|
||||
#define EP_Distinct 0x000010 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x000020 /* pSelect is correlated, not constant */
|
||||
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
|
||||
@@ -2831,10 +2833,10 @@ struct Select {
|
||||
*/
|
||||
struct SelectDest {
|
||||
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
|
||||
char *zAffSdst; /* Affinity used when eDest==SRT_Set */
|
||||
int iSDParm; /* A parameter used by the eDest disposal method */
|
||||
int iSdst; /* Base register where results are written */
|
||||
int nSdst; /* Number of registers allocated */
|
||||
char *zAffSdst; /* Affinity used when eDest==SRT_Set */
|
||||
ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */
|
||||
};
|
||||
|
||||
@@ -3337,6 +3339,10 @@ int sqlite3WalkSelect(Walker*, Select*);
|
||||
int sqlite3WalkSelectExpr(Walker*, Select*);
|
||||
int sqlite3WalkSelectFrom(Walker*, Select*);
|
||||
int sqlite3ExprWalkNoop(Walker*, Expr*);
|
||||
int sqlite3SelectWalkNoop(Walker*, Select*);
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3SelectWalkAssert2(Walker*, Select*);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Return code from the parse-tree walking primitives and their
|
||||
@@ -3398,11 +3404,14 @@ int sqlite3CantopenError(int);
|
||||
#ifdef SQLITE_DEBUG
|
||||
int sqlite3NomemError(int);
|
||||
int sqlite3IoerrnomemError(int);
|
||||
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
|
||||
# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__)
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -4363,4 +4372,6 @@ Expr *sqlite3VectorFieldSubexpr(Expr*, int);
|
||||
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
|
||||
void sqlite3VectorErrorMsg(Parse*, Expr*);
|
||||
|
||||
const char **sqlite3CompileOptions(int *pnOpt);
|
||||
|
||||
#endif /* SQLITEINT_H */
|
||||
|
||||
+5
-1
@@ -306,7 +306,11 @@ static int SQLITE_TCLAPI btree_next(
|
||||
}
|
||||
pCur = sqlite3TestTextToPtr(argv[1]);
|
||||
sqlite3BtreeEnter(pCur->pBtree);
|
||||
rc = sqlite3BtreeNext(pCur, &res);
|
||||
rc = sqlite3BtreeNext(pCur, 0);
|
||||
if( rc==SQLITE_DONE ){
|
||||
res = 1;
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
sqlite3BtreeLeave(pCur->pBtree);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
|
||||
@@ -545,6 +545,7 @@ static int fstreeFilter(
|
||||
zDir = zQuery;
|
||||
}
|
||||
}
|
||||
if( nDir==0 ) nDir = 1;
|
||||
|
||||
sqlite3_bind_text(pCsr->pStmt, 1, zDir, nDir, SQLITE_TRANSIENT);
|
||||
sqlite3_bind_text(pCsr->pStmt, 2, zRoot, nRoot, SQLITE_TRANSIENT);
|
||||
|
||||
@@ -306,6 +306,7 @@ void sqlite3FinishTrigger(
|
||||
if( v==0 ) goto triggerfinish_cleanup;
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n);
|
||||
testcase( z==0 );
|
||||
sqlite3NestedParse(pParse,
|
||||
"INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')",
|
||||
db->aDb[iDb].zDbSName, MASTER_NAME, zName,
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
|
||||
extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);
|
||||
int nKey;
|
||||
char *zKey;
|
||||
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
|
||||
sqlite3CodecGetKey(db, iDb, (void**)&zKey, &nKey);
|
||||
if( nKey ) db->nextPagesize = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
+41
-28
@@ -573,7 +573,7 @@ int sqlite3VdbeExec(
|
||||
int iCompare = 0; /* Result of last comparison */
|
||||
unsigned nVmStep = 0; /* Number of virtual machine steps */
|
||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
unsigned nProgressLimit = 0;/* Invoke xProgress() when nVmStep reaches this */
|
||||
unsigned nProgressLimit; /* Invoke xProgress() when nVmStep reaches this */
|
||||
#endif
|
||||
Mem *aMem = p->aMem; /* Copy of p->aMem */
|
||||
Mem *pIn1 = 0; /* 1st input operand */
|
||||
@@ -605,6 +605,8 @@ int sqlite3VdbeExec(
|
||||
u32 iPrior = p->aCounter[SQLITE_STMTSTATUS_VM_STEP];
|
||||
assert( 0 < db->nProgressOps );
|
||||
nProgressLimit = db->nProgressOps - (iPrior % db->nProgressOps);
|
||||
}else{
|
||||
nProgressLimit = 0xffffffff;
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -782,7 +784,7 @@ check_for_interrupt:
|
||||
** If the progress callback returns non-zero, exit the virtual machine with
|
||||
** a return code SQLITE_ABORT.
|
||||
*/
|
||||
if( db->xProgress!=0 && nVmStep>=nProgressLimit ){
|
||||
if( nVmStep>=nProgressLimit && db->xProgress!=0 ){
|
||||
assert( db->nProgressOps!=0 );
|
||||
nProgressLimit = nVmStep + db->nProgressOps - (nVmStep%db->nProgressOps);
|
||||
if( db->xProgress(db->pProgressArg) ){
|
||||
@@ -1324,7 +1326,7 @@ case OP_ResultRow: {
|
||||
/* Run the progress counter just before returning.
|
||||
*/
|
||||
if( db->xProgress!=0
|
||||
&& nVmStep>=nProgressLimit
|
||||
&& nVmStep>=nProgressLimit
|
||||
&& db->xProgress(db->pProgressArg)!=0
|
||||
){
|
||||
rc = SQLITE_INTERRUPT;
|
||||
@@ -2495,7 +2497,9 @@ case OP_Column: {
|
||||
pC = p->apCsr[pOp->p1];
|
||||
p2 = pOp->p2;
|
||||
|
||||
/* If the cursor cache is stale, bring it up-to-date */
|
||||
/* If the cursor cache is stale (meaning it is not currently point at
|
||||
** the correct row) then bring it up-to-date by doing the necessary
|
||||
** B-Tree seek. */
|
||||
rc = sqlite3VdbeCursorMoveto(&pC, &p2);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
|
||||
@@ -3977,8 +3981,15 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT );
|
||||
if( res<0 || (res==0 && oc==OP_SeekGT) ){
|
||||
res = 0;
|
||||
rc = sqlite3BtreeNext(pC->uc.pCursor, &res);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
rc = sqlite3BtreeNext(pC->uc.pCursor, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
res = 1;
|
||||
}else{
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
res = 0;
|
||||
}
|
||||
@@ -3986,8 +3997,15 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
assert( oc==OP_SeekLT || oc==OP_SeekLE );
|
||||
if( res>0 || (res==0 && oc==OP_SeekLT) ){
|
||||
res = 0;
|
||||
rc = sqlite3BtreePrevious(pC->uc.pCursor, &res);
|
||||
if( rc!=SQLITE_OK ) goto abort_due_to_error;
|
||||
rc = sqlite3BtreePrevious(pC->uc.pCursor, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_DONE ){
|
||||
rc = SQLITE_OK;
|
||||
res = 1;
|
||||
}else{
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* res might be negative because the table is empty. Check to
|
||||
** see if this is the case.
|
||||
@@ -5093,12 +5111,10 @@ case OP_Rewind: { /* jump */
|
||||
*/
|
||||
case OP_SorterNext: { /* jump */
|
||||
VdbeCursor *pC;
|
||||
int res;
|
||||
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( isSorter(pC) );
|
||||
res = 0;
|
||||
rc = sqlite3VdbeSorterNext(db, pC, &res);
|
||||
rc = sqlite3VdbeSorterNext(db, pC);
|
||||
goto next_tail;
|
||||
case OP_PrevIfOpen: /* jump */
|
||||
case OP_NextIfOpen: /* jump */
|
||||
@@ -5109,12 +5125,9 @@ case OP_Next: /* jump */
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
assert( pOp->p5<ArraySize(p->aCounter) );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
res = pOp->p3;
|
||||
assert( pC!=0 );
|
||||
assert( pC->deferredMoveto==0 );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( res==0 || (res==1 && pC->isTable==0) );
|
||||
testcase( res==1 );
|
||||
assert( pOp->opcode!=OP_Next || pOp->p4.xAdvance==sqlite3BtreeNext );
|
||||
assert( pOp->opcode!=OP_Prev || pOp->p4.xAdvance==sqlite3BtreePrevious );
|
||||
assert( pOp->opcode!=OP_NextIfOpen || pOp->p4.xAdvance==sqlite3BtreeNext );
|
||||
@@ -5129,21 +5142,21 @@ case OP_Next: /* jump */
|
||||
|| pC->seekOp==OP_SeekLT || pC->seekOp==OP_SeekLE
|
||||
|| pC->seekOp==OP_Last );
|
||||
|
||||
rc = pOp->p4.xAdvance(pC->uc.pCursor, &res);
|
||||
rc = pOp->p4.xAdvance(pC->uc.pCursor, pOp->p3);
|
||||
next_tail:
|
||||
pC->cacheStatus = CACHE_STALE;
|
||||
VdbeBranchTaken(res==0,2);
|
||||
if( rc ) goto abort_due_to_error;
|
||||
if( res==0 ){
|
||||
VdbeBranchTaken(rc==SQLITE_OK,2);
|
||||
if( rc==SQLITE_OK ){
|
||||
pC->nullRow = 0;
|
||||
p->aCounter[pOp->p5]++;
|
||||
#ifdef SQLITE_TEST
|
||||
sqlite3_search_count++;
|
||||
#endif
|
||||
goto jump_to_p2_and_check_for_interrupt;
|
||||
}else{
|
||||
pC->nullRow = 1;
|
||||
}
|
||||
if( rc!=SQLITE_DONE ) goto abort_due_to_error;
|
||||
rc = SQLITE_OK;
|
||||
pC->nullRow = 1;
|
||||
goto check_for_interrupt;
|
||||
}
|
||||
|
||||
@@ -5254,8 +5267,8 @@ case OP_IdxDelete: {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: Seek P1 * P3 P4 *
|
||||
** Synopsis: Move P3 to P1.rowid
|
||||
/* Opcode: DeferredSeek P1 * P3 P4 *
|
||||
** Synopsis: Move P3 to P1.rowid if needed
|
||||
**
|
||||
** P1 is an open index cursor and P3 is a cursor on the corresponding
|
||||
** table. This opcode does a deferred seek of the P3 table cursor
|
||||
@@ -5282,11 +5295,11 @@ case OP_IdxDelete: {
|
||||
**
|
||||
** See also: Rowid, MakeRecord.
|
||||
*/
|
||||
case OP_Seek:
|
||||
case OP_IdxRowid: { /* out2 */
|
||||
VdbeCursor *pC; /* The P1 index cursor */
|
||||
VdbeCursor *pTabCur; /* The P2 table cursor (OP_Seek only) */
|
||||
i64 rowid; /* Rowid that P1 current points to */
|
||||
case OP_DeferredSeek:
|
||||
case OP_IdxRowid: { /* out2 */
|
||||
VdbeCursor *pC; /* The P1 index cursor */
|
||||
VdbeCursor *pTabCur; /* The P2 table cursor (OP_DeferredSeek only) */
|
||||
i64 rowid; /* Rowid that P1 current points to */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
@@ -5312,7 +5325,7 @@ case OP_IdxRowid: { /* out2 */
|
||||
if( rc!=SQLITE_OK ){
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
if( pOp->opcode==OP_Seek ){
|
||||
if( pOp->opcode==OP_DeferredSeek ){
|
||||
assert( pOp->p3>=0 && pOp->p3<p->nCursor );
|
||||
pTabCur = p->apCsr[pOp->p3];
|
||||
assert( pTabCur!=0 );
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ struct VdbeOp {
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
Expr *pExpr; /* Used when p4type is P4_EXPR */
|
||||
#endif
|
||||
int (*xAdvance)(BtCursor *, int *);
|
||||
int (*xAdvance)(BtCursor *, int);
|
||||
} p4;
|
||||
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
|
||||
char *zComment; /* Comment to improve readability */
|
||||
|
||||
+1
-1
@@ -506,7 +506,7 @@ int sqlite3VdbeSorterInit(sqlite3 *, int, VdbeCursor *);
|
||||
void sqlite3VdbeSorterReset(sqlite3 *, VdbeSorter *);
|
||||
void sqlite3VdbeSorterClose(sqlite3 *, VdbeCursor *);
|
||||
int sqlite3VdbeSorterRowkey(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterNext(sqlite3 *, const VdbeCursor *);
|
||||
int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
||||
|
||||
+17
-4
@@ -1303,8 +1303,10 @@ static int bindText(
|
||||
if( rc==SQLITE_OK && encoding!=0 ){
|
||||
rc = sqlite3VdbeChangeEncoding(pVar, ENC(p->db));
|
||||
}
|
||||
sqlite3Error(p->db, rc);
|
||||
rc = sqlite3ApiExit(p->db, rc);
|
||||
if( rc ){
|
||||
sqlite3Error(p->db, rc);
|
||||
rc = sqlite3ApiExit(p->db, rc);
|
||||
}
|
||||
}
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}else if( xDel!=SQLITE_STATIC && xDel!=SQLITE_TRANSIENT ){
|
||||
@@ -1611,8 +1613,19 @@ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
v = pVdbe->aCounter[op];
|
||||
if( resetFlag ) pVdbe->aCounter[op] = 0;
|
||||
if( op==SQLITE_STMTSTATUS_MEMUSED ){
|
||||
sqlite3 *db = pVdbe->db;
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
v = 0;
|
||||
db->pnBytesFreed = (int*)&v;
|
||||
sqlite3VdbeClearObject(db, pVdbe);
|
||||
sqlite3DbFree(db, pVdbe);
|
||||
db->pnBytesFreed = 0;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
}else{
|
||||
v = pVdbe->aCounter[op];
|
||||
if( resetFlag ) pVdbe->aCounter[op] = 0;
|
||||
}
|
||||
return (int)v;
|
||||
}
|
||||
|
||||
|
||||
+15
-13
@@ -2160,17 +2160,18 @@ static void Cleanup(Vdbe *p){
|
||||
** be called on an SQL statement before sqlite3_step().
|
||||
*/
|
||||
void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
|
||||
Mem *pColName;
|
||||
int n;
|
||||
sqlite3 *db = p->db;
|
||||
|
||||
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
||||
sqlite3DbFree(db, p->aColName);
|
||||
if( p->nResColumn ){
|
||||
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
||||
sqlite3DbFree(db, p->aColName);
|
||||
}
|
||||
n = nResColumn*COLNAME_N;
|
||||
p->nResColumn = (u16)nResColumn;
|
||||
p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
|
||||
p->aColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
|
||||
if( p->aColName==0 ) return;
|
||||
initMemArray(p->aColName, n, p->db, MEM_Null);
|
||||
initMemArray(p->aColName, n, db, MEM_Null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2820,10 +2821,10 @@ int sqlite3VdbeTransferError(Vdbe *p){
|
||||
sqlite3ValueSetStr(db->pErr, -1, p->zErrMsg, SQLITE_UTF8, SQLITE_TRANSIENT);
|
||||
sqlite3EndBenignMalloc();
|
||||
db->bBenignMalloc--;
|
||||
db->errCode = rc;
|
||||
}else{
|
||||
sqlite3Error(db, rc);
|
||||
}else if( db->pErr ){
|
||||
sqlite3ValueSetNull(db->pErr);
|
||||
}
|
||||
db->errCode = rc;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3731,7 +3732,6 @@ static int vdbeCompareMemString(
|
||||
}else{
|
||||
int rc;
|
||||
const void *v1, *v2;
|
||||
int n1, n2;
|
||||
Mem c1;
|
||||
Mem c2;
|
||||
sqlite3VdbeMemInit(&c1, pMem1->db, MEM_Null);
|
||||
@@ -3739,11 +3739,13 @@ static int vdbeCompareMemString(
|
||||
sqlite3VdbeMemShallowCopy(&c1, pMem1, MEM_Ephem);
|
||||
sqlite3VdbeMemShallowCopy(&c2, pMem2, MEM_Ephem);
|
||||
v1 = sqlite3ValueText((sqlite3_value*)&c1, pColl->enc);
|
||||
n1 = v1==0 ? 0 : c1.n;
|
||||
v2 = sqlite3ValueText((sqlite3_value*)&c2, pColl->enc);
|
||||
n2 = v2==0 ? 0 : c2.n;
|
||||
rc = pColl->xCmp(pColl->pUser, n1, v1, n2, v2);
|
||||
if( (v1==0 || v2==0) && prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
|
||||
if( (v1==0 || v2==0) ){
|
||||
if( prcErr ) *prcErr = SQLITE_NOMEM_BKPT;
|
||||
rc = 0;
|
||||
}else{
|
||||
rc = pColl->xCmp(pColl->pUser, c1.n, v1, c2.n, v2);
|
||||
}
|
||||
sqlite3VdbeMemRelease(&c1);
|
||||
sqlite3VdbeMemRelease(&c2);
|
||||
return rc;
|
||||
|
||||
+1
-1
@@ -1325,7 +1325,7 @@ static int valueFromExpr(
|
||||
}
|
||||
}else if( op==TK_UMINUS ) {
|
||||
/* This branch happens for multiple negative signs. Ex: -(-5) */
|
||||
if( SQLITE_OK==sqlite3ValueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal)
|
||||
if( SQLITE_OK==valueFromExpr(db,pExpr->pLeft,enc,affinity,&pVal,pCtx)
|
||||
&& pVal!=0
|
||||
){
|
||||
sqlite3VdbeMemNumerify(pVal);
|
||||
|
||||
+14
-9
@@ -815,9 +815,9 @@ static int vdbeSorterCompareText(
|
||||
int n2;
|
||||
int res;
|
||||
|
||||
getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
|
||||
getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
|
||||
res = memcmp(v1, v2, MIN(n1, n2));
|
||||
getVarint32(&p1[1], n1);
|
||||
getVarint32(&p2[1], n2);
|
||||
res = memcmp(v1, v2, (MIN(n1, n2) - 13)/2);
|
||||
if( res==0 ){
|
||||
res = n1 - n2;
|
||||
}
|
||||
@@ -2612,9 +2612,13 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *pCsr, int *pbEof){
|
||||
}
|
||||
|
||||
/*
|
||||
** Advance to the next element in the sorter.
|
||||
** Advance to the next element in the sorter. Return value:
|
||||
**
|
||||
** SQLITE_OK success
|
||||
** SQLITE_DONE end of data
|
||||
** otherwise some kind of error.
|
||||
*/
|
||||
int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
|
||||
int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr){
|
||||
VdbeSorter *pSorter;
|
||||
int rc; /* Return code */
|
||||
|
||||
@@ -2628,21 +2632,22 @@ int sqlite3VdbeSorterNext(sqlite3 *db, const VdbeCursor *pCsr, int *pbEof){
|
||||
#if SQLITE_MAX_WORKER_THREADS>0
|
||||
if( pSorter->bUseThreads ){
|
||||
rc = vdbePmaReaderNext(pSorter->pReader);
|
||||
*pbEof = (pSorter->pReader->pFd==0);
|
||||
if( rc==SQLITE_OK && pSorter->pReader->pFd==0 ) rc = SQLITE_DONE;
|
||||
}else
|
||||
#endif
|
||||
/*if( !pSorter->bUseThreads )*/ {
|
||||
int res = 0;
|
||||
assert( pSorter->pMerger!=0 );
|
||||
assert( pSorter->pMerger->pTask==(&pSorter->aTask[0]) );
|
||||
rc = vdbeMergeEngineStep(pSorter->pMerger, pbEof);
|
||||
rc = vdbeMergeEngineStep(pSorter->pMerger, &res);
|
||||
if( rc==SQLITE_OK && res ) rc = SQLITE_DONE;
|
||||
}
|
||||
}else{
|
||||
SorterRecord *pFree = pSorter->list.pList;
|
||||
pSorter->list.pList = pFree->u.pNext;
|
||||
pFree->u.pNext = 0;
|
||||
if( pSorter->list.aMemory==0 ) vdbeSorterRecordFree(db, pFree);
|
||||
*pbEof = !pSorter->list.pList;
|
||||
rc = SQLITE_OK;
|
||||
rc = pSorter->list.pList ? SQLITE_OK : SQLITE_DONE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
+9
-16
@@ -124,8 +124,9 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
||||
**
|
||||
** If it is not NULL, the xSelectCallback() callback is invoked before
|
||||
** the walk of the expressions and FROM clause. The xSelectCallback2()
|
||||
** method, if it is not NULL, is invoked following the walk of the
|
||||
** expressions and FROM clause.
|
||||
** method is invoked following the walk of the expressions and FROM clause,
|
||||
** but only if both xSelectCallback and xSelectCallback2 are both non-NULL
|
||||
** and if the expressions and FROM clause both return WRC_Continue;
|
||||
**
|
||||
** Return WRC_Continue under normal conditions. Return WRC_Abort if
|
||||
** there is an abort request.
|
||||
@@ -135,27 +136,19 @@ int sqlite3WalkSelectFrom(Walker *pWalker, Select *p){
|
||||
*/
|
||||
int sqlite3WalkSelect(Walker *pWalker, Select *p){
|
||||
int rc;
|
||||
if( p==0 || (pWalker->xSelectCallback==0 && pWalker->xSelectCallback2==0) ){
|
||||
return WRC_Continue;
|
||||
}
|
||||
rc = WRC_Continue;
|
||||
pWalker->walkerDepth++;
|
||||
while( p ){
|
||||
if( pWalker->xSelectCallback ){
|
||||
rc = pWalker->xSelectCallback(pWalker, p);
|
||||
if( rc ) break;
|
||||
}
|
||||
if( p==0 || pWalker->xSelectCallback==0 ) return WRC_Continue;
|
||||
do{
|
||||
rc = pWalker->xSelectCallback(pWalker, p);
|
||||
if( rc ) return rc & WRC_Abort;
|
||||
if( sqlite3WalkSelectExpr(pWalker, p)
|
||||
|| sqlite3WalkSelectFrom(pWalker, p)
|
||||
){
|
||||
pWalker->walkerDepth--;
|
||||
return WRC_Abort;
|
||||
}
|
||||
if( pWalker->xSelectCallback2 ){
|
||||
pWalker->xSelectCallback2(pWalker, p);
|
||||
}
|
||||
p = p->pPrior;
|
||||
}
|
||||
pWalker->walkerDepth--;
|
||||
return rc & WRC_Abort;
|
||||
}while( p!=0 );
|
||||
return WRC_Continue;
|
||||
}
|
||||
|
||||
+37
-24
@@ -1192,7 +1192,7 @@ static int whereKeyStats(
|
||||
iGap = iGap/3;
|
||||
}
|
||||
aStat[0] = iLower + iGap;
|
||||
aStat[1] = pIdx->aAvgEq[iCol];
|
||||
aStat[1] = pIdx->aAvgEq[nField-1];
|
||||
}
|
||||
|
||||
/* Restore the pRec->nField value before returning. */
|
||||
@@ -1945,16 +1945,17 @@ static void whereLoopAdjustCost(const WhereLoop *p, WhereLoop *pTemplate){
|
||||
|
||||
/*
|
||||
** Search the list of WhereLoops in *ppPrev looking for one that can be
|
||||
** supplanted by pTemplate.
|
||||
** replaced by pTemplate.
|
||||
**
|
||||
** Return NULL if the WhereLoop list contains an entry that can supplant
|
||||
** pTemplate, in other words if pTemplate does not belong on the list.
|
||||
** Return NULL if pTemplate does not belong on the WhereLoop list.
|
||||
** In other words if pTemplate ought to be dropped from further consideration.
|
||||
**
|
||||
** If pX is a WhereLoop that pTemplate can supplant, then return the
|
||||
** If pX is a WhereLoop that pTemplate can replace, then return the
|
||||
** link that points to pX.
|
||||
**
|
||||
** If pTemplate cannot supplant any existing element of the list but needs
|
||||
** to be added to the list, then return a pointer to the tail of the list.
|
||||
** If pTemplate cannot replace any existing element of the list but needs
|
||||
** to be added to the list as a new entry, then return a pointer to the
|
||||
** tail of the list.
|
||||
*/
|
||||
static WhereLoop **whereLoopFindLesser(
|
||||
WhereLoop **ppPrev,
|
||||
@@ -2099,8 +2100,10 @@ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){
|
||||
if( p!=0 ){
|
||||
sqlite3DebugPrintf("replace: ");
|
||||
whereLoopPrint(p, pBuilder->pWC);
|
||||
sqlite3DebugPrintf(" with: ");
|
||||
}else{
|
||||
sqlite3DebugPrintf(" add: ");
|
||||
}
|
||||
sqlite3DebugPrintf(" add: ");
|
||||
whereLoopPrint(pTemplate, pBuilder->pWC);
|
||||
}
|
||||
#endif
|
||||
@@ -4000,8 +4003,8 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
** this candidate as not viable. */
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
sqlite3DebugPrintf("Skip %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
@@ -4019,26 +4022,36 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pTo = &aTo[jj];
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf("New %s cost=%-3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
sqlite3DebugPrintf("New %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
}else{
|
||||
/* Control reaches here if best-so-far path pTo=aTo[jj] covers the
|
||||
** same set of loops and has the sam isOrdered setting as the
|
||||
** same set of loops and has the same isOrdered setting as the
|
||||
** candidate path. Check to see if the candidate should replace
|
||||
** pTo or if the candidate should be skipped */
|
||||
if( pTo->rCost<rCost || (pTo->rCost==rCost && pTo->nRow<=nOut) ){
|
||||
** pTo or if the candidate should be skipped.
|
||||
**
|
||||
** The conditional is an expanded vector comparison equivalent to:
|
||||
** (pTo->rCost,pTo->nRow,pTo->rUnsorted) <= (rCost,nOut,rUnsorted)
|
||||
*/
|
||||
if( pTo->rCost<rCost
|
||||
|| (pTo->rCost==rCost
|
||||
&& (pTo->nRow<nOut
|
||||
|| (pTo->nRow==nOut && pTo->rUnsorted<=rUnsorted)
|
||||
)
|
||||
)
|
||||
){
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
"Skip %s cost=%-3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
"Skip %s cost=%-3d,%3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
sqlite3DebugPrintf(" vs %s cost=%-3d,%d order=%c\n",
|
||||
sqlite3DebugPrintf(" vs %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
|
||||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
/* Discard the candidate path from further consideration */
|
||||
@@ -4051,12 +4064,12 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
#ifdef WHERETRACE_ENABLED /* 0x4 */
|
||||
if( sqlite3WhereTrace&0x4 ){
|
||||
sqlite3DebugPrintf(
|
||||
"Update %s cost=%-3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut,
|
||||
"Update %s cost=%-3d,%3d,%3d order=%c",
|
||||
wherePathName(pFrom, iLoop, pWLoop), rCost, nOut, rUnsorted,
|
||||
isOrdered>=0 ? isOrdered+'0' : '?');
|
||||
sqlite3DebugPrintf(" was %s cost=%-3d,%3d order=%c\n",
|
||||
sqlite3DebugPrintf(" was %s cost=%-3d,%3d,%3d order=%c\n",
|
||||
wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow,
|
||||
pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
pTo->rUnsorted, pTo->isOrdered>=0 ? pTo->isOrdered+'0' : '?');
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -4564,7 +4577,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
static const char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
||||
for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){
|
||||
p->cId = zLabel[i%sizeof(zLabel)];
|
||||
p->cId = zLabel[i%(sizeof(zLabel)-1)];
|
||||
whereLoopPrint(p, sWLB.pWC);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -966,10 +966,10 @@ static void codeCursorHint(
|
||||
**
|
||||
** Normally, this is just:
|
||||
**
|
||||
** OP_Seek $iCur $iRowid
|
||||
** OP_DeferredSeek $iCur $iRowid
|
||||
**
|
||||
** However, if the scan currently being coded is a branch of an OR-loop and
|
||||
** the statement currently being coded is a SELECT, then P3 of the OP_Seek
|
||||
** the statement currently being coded is a SELECT, then P3 of OP_DeferredSeek
|
||||
** is set to iIdxCur and P4 is set to point to an array of integers
|
||||
** containing one entry for each column of the table cursor iCur is open
|
||||
** on. For each table column, if the column is the i'th column of the
|
||||
@@ -988,7 +988,7 @@ static void codeDeferredSeek(
|
||||
assert( iIdxCur>0 );
|
||||
assert( pIdx->aiColumn[pIdx->nColumn-1]==-1 );
|
||||
|
||||
sqlite3VdbeAddOp3(v, OP_Seek, iIdxCur, 0, iCur);
|
||||
sqlite3VdbeAddOp3(v, OP_DeferredSeek, iIdxCur, 0, iCur);
|
||||
if( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
|
||||
&& DbMaskAllZero(sqlite3ParseToplevel(pParse)->writeMask)
|
||||
){
|
||||
|
||||
+3
-3
@@ -1375,11 +1375,11 @@ Bitmask sqlite3WhereExprUsage(WhereMaskSet *pMaskSet, Expr *p){
|
||||
Bitmask mask;
|
||||
if( p==0 ) return 0;
|
||||
if( p->op==TK_COLUMN ){
|
||||
mask = sqlite3WhereGetMask(pMaskSet, p->iTable);
|
||||
return mask;
|
||||
return sqlite3WhereGetMask(pMaskSet, p->iTable);
|
||||
}
|
||||
mask = (p->op==TK_IF_NULL_ROW) ? sqlite3WhereGetMask(pMaskSet, p->iTable) : 0;
|
||||
assert( !ExprHasProperty(p, EP_TokenOnly) );
|
||||
mask = p->pRight ? sqlite3WhereExprUsage(pMaskSet, p->pRight) : 0;
|
||||
if( p->pRight ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pRight);
|
||||
if( p->pLeft ) mask |= sqlite3WhereExprUsage(pMaskSet, p->pLeft);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
mask |= exprSelectUsage(pMaskSet, p->x.pSelect);
|
||||
|
||||
@@ -705,5 +705,12 @@ do_test autovacuum-9.5 {
|
||||
file size test.db
|
||||
} $::sqlite_pending_byte
|
||||
|
||||
do_execsql_test autovacuum-10.1 {
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(25, randomblob(104));
|
||||
REPLACE INTO t1 VALUES(25, randomblob(1117));
|
||||
PRAGMA integrity_check;
|
||||
} {ok}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -61,6 +61,24 @@ do_test ctime-1.2.2 {
|
||||
list [ lindex $ans 0 ] [ expr { [lsort [lindex $ans 1]]==[lindex $ans 1] } ]
|
||||
} {0 1}
|
||||
|
||||
# Check the THREADSAFE option for SQLITE_THREADSAFE=2 builds (there are
|
||||
# a couple of these configurations in releasetest.tcl).
|
||||
#
|
||||
ifcapable threadsafe2 {
|
||||
foreach {tn opt res} {
|
||||
1 SQLITE_THREADSAFE 1
|
||||
2 THREADSAFE 1
|
||||
3 THREADSAFE=0 0
|
||||
4 THREADSAFE=1 0
|
||||
5 THREADSAFE=2 1
|
||||
6 THREADSAFE= 0
|
||||
} {
|
||||
do_execsql_test ctime-1.3.$tn {
|
||||
SELECT sqlite_compileoption_used($opt)
|
||||
} $res
|
||||
}
|
||||
}
|
||||
|
||||
# SQLITE_THREADSAFE should pretty much always be defined
|
||||
# one way or the other, and it must have a value of 0 or 1.
|
||||
do_test ctime-1.4.1 {
|
||||
|
||||
@@ -384,7 +384,9 @@ foreach T $tokenizers {
|
||||
do_isspace_test 6.$T.13 $T 8200
|
||||
do_isspace_test 6.$T.14 $T 8201
|
||||
do_isspace_test 6.$T.15 $T 8202
|
||||
do_isspace_test 6.$T.16 $T 8239
|
||||
if {$T!="icu"} {
|
||||
do_isspace_test 6.$T.16 $T 8239
|
||||
}
|
||||
do_isspace_test 6.$T.17 $T 8287
|
||||
do_isspace_test 6.$T.18 $T 12288
|
||||
|
||||
|
||||
@@ -743,4 +743,24 @@ do_execsql_test join-14.5 {
|
||||
SELECT * FROM (SELECT 111) LEFT JOIN (SELECT c+222 FROM t1) GROUP BY 1;
|
||||
} {111 {}}
|
||||
|
||||
# Verify the fix to ticket
|
||||
# https://www.sqlite.org/src/tktview/7fde638e94287d2c948cd9389
|
||||
#
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
do_execsql_test join-14.10 {
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(1),(2),(3);
|
||||
CREATE VIEW v2 AS SELECT a, 1 AS b FROM t1;
|
||||
CREATE TABLE t3(x);
|
||||
INSERT INTO t3 VALUES(2),(4);
|
||||
SELECT *, '|' FROM t3 LEFT JOIN v2 ON a=x WHERE b=1;
|
||||
} {2 2 1 |}
|
||||
do_execsql_test join-14.11 {
|
||||
SELECT *, '|' FROM t3 LEFT JOIN v2 ON a=x WHERE b+1=x;
|
||||
} {2 2 1 |}
|
||||
do_execsql_test join-14.12 {
|
||||
SELECT *, '|' FROM t3 LEFT JOIN v2 ON a=x ORDER BY b;
|
||||
} {4 {} {} | 2 2 1 |}
|
||||
|
||||
finish_test
|
||||
|
||||
+355
-86
@@ -71,14 +71,21 @@ static const char zHelp[] =
|
||||
"\n"
|
||||
" --variance V Randomly vary M by plus or minus V\n"
|
||||
"\n"
|
||||
" kvtest export DBFILE DIRECTORY\n"
|
||||
" kvtest export DBFILE DIRECTORY [--tree]\n"
|
||||
"\n"
|
||||
" Export all the blobs in the kv table of DBFILE into separate\n"
|
||||
" files in DIRECTORY.\n"
|
||||
" files in DIRECTORY. DIRECTORY is created if it does not previously\n"
|
||||
" exist. If the --tree option is used, then the blobs are written\n"
|
||||
" into a hierarchy of directories, using names like 00/00/00,\n"
|
||||
" 00/00/01, 00/00/02, and so forth. Without the --tree option, all\n"
|
||||
" files are in the top-level directory with names like 000000, 000001,\n"
|
||||
" 000002, and so forth.\n"
|
||||
"\n"
|
||||
" kvtest stat DBFILE\n"
|
||||
" kvtest stat DBFILE [options]\n"
|
||||
"\n"
|
||||
" Display summary information about DBFILE\n"
|
||||
" Display summary information about DBFILE. Options:\n"
|
||||
"\n"
|
||||
" --vacuum Run VACUUM on the database file\n"
|
||||
"\n"
|
||||
" kvtest run DBFILE [options]\n"
|
||||
"\n"
|
||||
@@ -90,12 +97,18 @@ static const char zHelp[] =
|
||||
" --cache-size N Database cache size\n"
|
||||
" --count N Read N blobs\n"
|
||||
" --desc Read blobs in descending order\n"
|
||||
" --fsync Synchronous file writes\n"
|
||||
" --integrity-check Run \"PRAGMA integrity_check\" after test\n"
|
||||
" --max-id N Maximum blob key to use\n"
|
||||
" --mmap N Mmap as much as N bytes of DBFILE\n"
|
||||
" --multitrans Each read or write in its own transaction\n"
|
||||
" --nocheckpoint Omit the checkpoint on WAL mode writes\n"
|
||||
" --nosync Set \"PRAGMA synchronous=OFF\"\n"
|
||||
" --jmode MODE Set MODE journal mode prior to starting\n"
|
||||
" --random Read blobs in a random order\n"
|
||||
" --start N Start reading with this blob key\n"
|
||||
" --stats Output operating stats before exiting\n"
|
||||
" --update Do an overwrite test\n"
|
||||
;
|
||||
|
||||
/* Reference resources used */
|
||||
@@ -111,6 +124,7 @@ static const char zHelp[] =
|
||||
# include <unistd.h>
|
||||
#else
|
||||
/* Provide Windows equivalent for the needed parts of unistd.h */
|
||||
# include <direct.h>
|
||||
# include <io.h>
|
||||
# define R_OK 2
|
||||
# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
|
||||
@@ -118,6 +132,31 @@ static const char zHelp[] =
|
||||
# define access _access
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
** The following macros are used to cast pointers to integers and
|
||||
** integers to pointers. The way you do this varies from one compiler
|
||||
** to the next, so we have developed the following set of #if statements
|
||||
** to generate appropriate macros for a wide range of compilers.
|
||||
**
|
||||
** The correct "ANSI" way to do this is to use the intptr_t type.
|
||||
** Unfortunately, that typedef is not available on all compilers, or
|
||||
** if it is available, it requires an #include of specific headers
|
||||
** that vary from one machine to the next.
|
||||
**
|
||||
** Ticket #3860: The llvm-gcc-4.2 compiler from Apple chokes on
|
||||
** the ((void*)&((char*)0)[X]) construct. But MSVC chokes on ((void*)(X)).
|
||||
** So we have to define the macros in different ways depending on the
|
||||
** compiler.
|
||||
*/
|
||||
#if 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) ((sqlite3_int64)(__PTRDIFF_TYPE__)(X))
|
||||
#else
|
||||
# define SQLITE_INT_TO_PTR(X) ((void*)(intptr_t)(X))
|
||||
# define SQLITE_PTR_TO_INT(X) ((sqlite3_int64)(intptr_t)(X))
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Show thqe help text and quit.
|
||||
@@ -201,13 +240,23 @@ static int integerValue(const char *zArg){
|
||||
/*
|
||||
** Check the filesystem object zPath. Determine what it is:
|
||||
**
|
||||
** PATH_DIR A directory
|
||||
** PATH_DIR A single directory holding many files
|
||||
** PATH_TREE A directory hierarchy with files at the leaves
|
||||
** PATH_DB An SQLite database
|
||||
** PATH_NEXIST Does not exist
|
||||
** PATH_OTHER Something else
|
||||
**
|
||||
** PATH_DIR means all of the separate files are grouped together
|
||||
** into a single directory with names like 000000, 000001, 000002, and
|
||||
** so forth. PATH_TREE means there is a hierarchy of directories so
|
||||
** that no single directory has too many entries. The files have names
|
||||
** like 00/00/00, 00/00/01, 00/00/02 and so forth. The decision between
|
||||
** PATH_DIR and PATH_TREE is determined by the presence of a subdirectory
|
||||
** named "00" at the top-level.
|
||||
*/
|
||||
#define PATH_DIR 1
|
||||
#define PATH_DB 2
|
||||
#define PATH_TREE 2
|
||||
#define PATH_DB 3
|
||||
#define PATH_NEXIST 0
|
||||
#define PATH_OTHER 99
|
||||
static int pathType(const char *zPath){
|
||||
@@ -217,7 +266,15 @@ static int pathType(const char *zPath){
|
||||
memset(&x, 0, sizeof(x));
|
||||
rc = stat(zPath, &x);
|
||||
if( rc<0 ) return PATH_OTHER;
|
||||
if( S_ISDIR(x.st_mode) ) return PATH_DIR;
|
||||
if( S_ISDIR(x.st_mode) ){
|
||||
char *zLayer1 = sqlite3_mprintf("%s/00", zPath);
|
||||
memset(&x, 0, sizeof(x));
|
||||
rc = stat(zLayer1, &x);
|
||||
sqlite3_free(zLayer1);
|
||||
if( rc<0 ) return PATH_DIR;
|
||||
if( S_ISDIR(x.st_mode) ) return PATH_TREE;
|
||||
return PATH_DIR;
|
||||
}
|
||||
if( (x.st_size%512)==0 ) return PATH_DB;
|
||||
return PATH_OTHER;
|
||||
}
|
||||
@@ -328,6 +385,7 @@ static int statMain(int argc, char **argv){
|
||||
sqlite3 *db;
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt;
|
||||
int doVacuum = 0;
|
||||
|
||||
assert( strcmp(argv[1],"stat")==0 );
|
||||
assert( argc>=3 );
|
||||
@@ -336,12 +394,21 @@ static int statMain(int argc, char **argv){
|
||||
char *z = argv[i];
|
||||
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
|
||||
if( z[1]=='-' ) z++;
|
||||
if( strcmp(z, "-vacuum")==0 ){
|
||||
doVacuum = 1;
|
||||
continue;
|
||||
}
|
||||
fatalError("unknown option: \"%s\"", argv[i]);
|
||||
}
|
||||
rc = sqlite3_open(zDb, &db);
|
||||
if( rc ){
|
||||
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
|
||||
}
|
||||
if( doVacuum ){
|
||||
printf("Vacuuming...."); fflush(stdout);
|
||||
sqlite3_exec(db, "VACUUM", 0, 0, 0);
|
||||
printf(" done\n");
|
||||
}
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT count(*), min(length(v)), max(length(v)), avg(length(v))"
|
||||
" FROM kv"
|
||||
@@ -374,39 +441,53 @@ static int statMain(int argc, char **argv){
|
||||
printf("Page-count: %8d\n", sqlite3_column_int(pStmt, 0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
zSql = sqlite3_mprintf("PRAGMA freelist_count");
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc ) fatalError("cannot prepare SQL [%s]: %s", zSql, sqlite3_errmsg(db));
|
||||
sqlite3_free(zSql);
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
printf("Freelist-count: %8d\n", sqlite3_column_int(pStmt, 0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check(10)", -1, &pStmt, 0);
|
||||
if( rc ) fatalError("cannot prepare integrity check: %s", sqlite3_errmsg(db));
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
printf("Integrity-check: %s\n", sqlite3_column_text(pStmt, 0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the "writefile(X,Y)" SQL function. The argument Y
|
||||
** is written into file X. The number of bytes written is returned. Or
|
||||
** NULL is returned if something goes wrong, such as being unable to open
|
||||
** file X for writing.
|
||||
** remember(V,PTR)
|
||||
**
|
||||
** Return the integer value V. Also save the value of V in a
|
||||
** C-language variable whose address is PTR.
|
||||
*/
|
||||
static void writefileFunc(
|
||||
sqlite3_context *context,
|
||||
static void rememberFunc(
|
||||
sqlite3_context *pCtx,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
FILE *out;
|
||||
const char *z;
|
||||
sqlite3_int64 rc;
|
||||
const char *zFile;
|
||||
sqlite3_int64 v;
|
||||
sqlite3_int64 ptr;
|
||||
assert( argc==2 );
|
||||
v = sqlite3_value_int64(argv[0]);
|
||||
ptr = sqlite3_value_int64(argv[1]);
|
||||
*(sqlite3_int64*)SQLITE_INT_TO_PTR(ptr) = v;
|
||||
sqlite3_result_int64(pCtx, v);
|
||||
}
|
||||
|
||||
zFile = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zFile==0 ) return;
|
||||
out = fopen(zFile, "wb");
|
||||
if( out==0 ) return;
|
||||
z = (const char*)sqlite3_value_blob(argv[1]);
|
||||
if( z==0 ){
|
||||
rc = 0;
|
||||
}else{
|
||||
rc = fwrite(z, 1, sqlite3_value_bytes(argv[1]), out);
|
||||
}
|
||||
fclose(out);
|
||||
printf("\r%s ", zFile); fflush(stdout);
|
||||
sqlite3_result_int64(context, rc);
|
||||
/*
|
||||
** Make sure a directory named zDir exists.
|
||||
*/
|
||||
static void kvtest_mkdir(const char *zDir){
|
||||
#if defined(_WIN32)
|
||||
(void)mkdir(zDir);
|
||||
#else
|
||||
(void)mkdir(zDir, 0755);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -416,32 +497,77 @@ static int exportMain(int argc, char **argv){
|
||||
char *zDb;
|
||||
char *zDir;
|
||||
sqlite3 *db;
|
||||
char *zSql;
|
||||
sqlite3_stmt *pStmt;
|
||||
int rc;
|
||||
char *zErrMsg = 0;
|
||||
int ePathType;
|
||||
int nFN;
|
||||
char *zFN;
|
||||
char *zTail;
|
||||
size_t nWrote;
|
||||
int i;
|
||||
|
||||
assert( strcmp(argv[1],"export")==0 );
|
||||
assert( argc>=3 );
|
||||
if( argc<4 ) fatalError("Usage: kvtest export DATABASE DIRECTORY [OPTIONS]");
|
||||
zDb = argv[2];
|
||||
if( argc!=4 ) fatalError("Usage: kvtest export DATABASE DIRECTORY");
|
||||
zDir = argv[3];
|
||||
if( pathType(zDir)!=PATH_DIR ){
|
||||
kvtest_mkdir(zDir);
|
||||
for(i=4; i<argc; i++){
|
||||
const char *z = argv[i];
|
||||
if( z[0]=='-' && z[1]=='-' ) z++;
|
||||
if( strcmp(z,"-tree")==0 ){
|
||||
zFN = sqlite3_mprintf("%s/00", zDir);
|
||||
kvtest_mkdir(zFN);
|
||||
sqlite3_free(zFN);
|
||||
continue;
|
||||
}
|
||||
fatalError("unknown argument: \"%s\"\n", argv[i]);
|
||||
}
|
||||
ePathType = pathType(zDir);
|
||||
if( ePathType!=PATH_DIR && ePathType!=PATH_TREE ){
|
||||
fatalError("object \"%s\" is not a directory", zDir);
|
||||
}
|
||||
rc = sqlite3_open(zDb, &db);
|
||||
if( rc ){
|
||||
fatalError("cannot open database \"%s\": %s", zDb, sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
|
||||
writefileFunc, 0, 0);
|
||||
zSql = sqlite3_mprintf(
|
||||
"SELECT writefile(printf('%s/%%06d',k),v) FROM kv;",
|
||||
zDir
|
||||
);
|
||||
rc = sqlite3_exec(db, zSql, 0, 0, &zErrMsg);
|
||||
if( rc ) fatalError("database create failed: %s", zErrMsg);
|
||||
sqlite3_free(zSql);
|
||||
rc = sqlite3_prepare_v2(db, "SELECT k, v FROM kv ORDER BY k", -1, &pStmt, 0);
|
||||
if( rc ){
|
||||
fatalError("prepare_v2 failed: %s\n", sqlite3_errmsg(db));
|
||||
}
|
||||
nFN = (int)strlen(zDir);
|
||||
zFN = sqlite3_mprintf("%s/00/00/00.extra---------------------", zDir);
|
||||
if( zFN==0 ){
|
||||
fatalError("malloc failed\n");
|
||||
}
|
||||
zTail = zFN + nFN + 1;
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
int iKey = sqlite3_column_int(pStmt, 0);
|
||||
sqlite3_int64 nData = sqlite3_column_bytes(pStmt, 1);
|
||||
const void *pData = sqlite3_column_blob(pStmt, 1);
|
||||
FILE *out;
|
||||
if( ePathType==PATH_DIR ){
|
||||
sqlite3_snprintf(20, zTail, "%06d", iKey);
|
||||
}else{
|
||||
sqlite3_snprintf(20, zTail, "%02d", iKey/10000);
|
||||
kvtest_mkdir(zFN);
|
||||
sqlite3_snprintf(20, zTail, "%02d/%02d", iKey/10000, (iKey/100)%100);
|
||||
kvtest_mkdir(zFN);
|
||||
sqlite3_snprintf(20, zTail, "%02d/%02d/%02d",
|
||||
iKey/10000, (iKey/100)%100, iKey%100);
|
||||
}
|
||||
out = fopen(zFN, "wb");
|
||||
nWrote = fwrite(pData, 1, nData, out);
|
||||
fclose(out);
|
||||
printf("\r%s ", zTail); fflush(stdout);
|
||||
if( nWrote!=nData ){
|
||||
fatalError("Wrote only %d of %d bytes to %s\n",
|
||||
(int)nWrote, nData, zFN);
|
||||
}
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
sqlite3_free(zFN);
|
||||
printf("\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -461,7 +587,7 @@ static int exportMain(int argc, char **argv){
|
||||
** NULL is returned if any error is encountered. The final value of *pnByte
|
||||
** is undefined in this case.
|
||||
*/
|
||||
static unsigned char *readFile(const char *zName, int *pnByte){
|
||||
static unsigned char *readFile(const char *zName, sqlite3_int64 *pnByte){
|
||||
FILE *in; /* FILE from which to read content of zName */
|
||||
sqlite3_int64 nIn; /* Size of zName in bytes */
|
||||
size_t nRead; /* Number of bytes actually read */
|
||||
@@ -479,10 +605,55 @@ static unsigned char *readFile(const char *zName, int *pnByte){
|
||||
sqlite3_free(pBuf);
|
||||
return 0;
|
||||
}
|
||||
if( pnByte ) *pnByte = (int)nIn;
|
||||
if( pnByte ) *pnByte = nIn;
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
/*
|
||||
** Overwrite a file with randomness. Do not change the size of the
|
||||
** file.
|
||||
*/
|
||||
static void updateFile(const char *zName, sqlite3_int64 *pnByte, int doFsync){
|
||||
FILE *out; /* FILE from which to read content of zName */
|
||||
sqlite3_int64 sz; /* Size of zName in bytes */
|
||||
size_t nWritten; /* Number of bytes actually read */
|
||||
unsigned char *pBuf; /* Content to store on disk */
|
||||
const char *zMode = "wb"; /* Mode for fopen() */
|
||||
|
||||
sz = fileSize(zName);
|
||||
if( sz<0 ){
|
||||
fatalError("No such file: \"%s\"", zName);
|
||||
}
|
||||
*pnByte = sz;
|
||||
if( sz==0 ) return;
|
||||
pBuf = sqlite3_malloc64( sz );
|
||||
if( pBuf==0 ){
|
||||
fatalError("Cannot allocate %lld bytes\n", sz);
|
||||
}
|
||||
sqlite3_randomness((int)sz, pBuf);
|
||||
#if defined(_WIN32)
|
||||
if( doFsync ) zMode = "wbc";
|
||||
#endif
|
||||
out = fopen(zName, zMode);
|
||||
if( out==0 ){
|
||||
fatalError("Cannot open \"%s\" for writing\n", zName);
|
||||
}
|
||||
nWritten = fwrite(pBuf, 1, (size_t)sz, out);
|
||||
if( doFsync ){
|
||||
#if defined(_WIN32)
|
||||
fflush(out);
|
||||
#else
|
||||
fsync(fileno(out));
|
||||
#endif
|
||||
}
|
||||
fclose(out);
|
||||
if( nWritten!=(size_t)sz ){
|
||||
fatalError("Wrote only %d of %d bytes to \"%s\"\n",
|
||||
(int)nWritten, (int)sz, zName);
|
||||
}
|
||||
sqlite3_free(pBuf);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time in milliseconds since the beginning of
|
||||
** the Julian epoch.
|
||||
@@ -637,16 +808,22 @@ static int runMain(int argc, char **argv){
|
||||
int bBlobApi = 0; /* Use the incremental blob I/O API */
|
||||
int bStats = 0; /* Print stats before exiting */
|
||||
int eOrder = ORDER_ASC; /* Access order */
|
||||
int isUpdateTest = 0; /* Do in-place updates rather than reads */
|
||||
int doIntegrityCk = 0; /* Run PRAGMA integrity_check after the test */
|
||||
int noSync = 0; /* Disable synchronous mode */
|
||||
int doFsync = 0; /* Update disk files synchronously */
|
||||
int doMultiTrans = 0; /* Each operation in its own transaction */
|
||||
int noCheckpoint = 0; /* Omit the checkpoint in WAL mode */
|
||||
sqlite3 *db = 0; /* Database connection */
|
||||
sqlite3_stmt *pStmt = 0; /* Prepared statement for SQL access */
|
||||
sqlite3_blob *pBlob = 0; /* Handle for incremental Blob I/O */
|
||||
sqlite3_int64 tmStart; /* Start time */
|
||||
sqlite3_int64 tmElapsed; /* Elapsed time */
|
||||
int mmapSize = 0; /* --mmap N argument */
|
||||
int nData = 0; /* Bytes of data */
|
||||
sqlite3_int64 nData = 0; /* Bytes of data */
|
||||
sqlite3_int64 nTotal = 0; /* Total data read */
|
||||
unsigned char *pData = 0; /* Content of the blob */
|
||||
int nAlloc = 0; /* Space allocated for pData[] */
|
||||
sqlite3_int64 nAlloc = 0; /* Space allocated for pData[] */
|
||||
const char *zJMode = 0; /* Journal mode */
|
||||
|
||||
|
||||
@@ -660,12 +837,42 @@ static int runMain(int argc, char **argv){
|
||||
char *z = argv[i];
|
||||
if( z[0]!='-' ) fatalError("unknown argument: \"%s\"", z);
|
||||
if( z[1]=='-' ) z++;
|
||||
if( strcmp(z, "-asc")==0 ){
|
||||
eOrder = ORDER_ASC;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-blob-api")==0 ){
|
||||
bBlobApi = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-cache-size")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
iCache = integerValue(argv[++i]);
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-count")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
nCount = integerValue(argv[++i]);
|
||||
if( nCount<1 ) fatalError("the --count must be positive");
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-desc")==0 ){
|
||||
eOrder = ORDER_DESC;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-fsync")==0 ){
|
||||
doFsync = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-integrity-check")==0 ){
|
||||
doIntegrityCk = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-jmode")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
zJMode = argv[++i];
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-mmap")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
mmapSize = integerValue(argv[++i]);
|
||||
@@ -677,44 +884,45 @@ static int runMain(int argc, char **argv){
|
||||
iMax = integerValue(argv[++i]);
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-start")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
iKey = integerValue(argv[++i]);
|
||||
if( iKey<1 ) fatalError("the --start must be positive");
|
||||
if( strcmp(z, "-multitrans")==0 ){
|
||||
doMultiTrans = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-cache-size")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
iCache = integerValue(argv[++i]);
|
||||
if( strcmp(z, "-nocheckpoint")==0 ){
|
||||
noCheckpoint = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-jmode")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
zJMode = argv[++i];
|
||||
if( strcmp(z, "-nosync")==0 ){
|
||||
noSync = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-random")==0 ){
|
||||
eOrder = ORDER_RANDOM;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-asc")==0 ){
|
||||
eOrder = ORDER_ASC;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-desc")==0 ){
|
||||
eOrder = ORDER_DESC;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-blob-api")==0 ){
|
||||
bBlobApi = 1;
|
||||
if( strcmp(z, "-start")==0 ){
|
||||
if( i==argc-1 ) fatalError("missing argument on \"%s\"", argv[i]);
|
||||
iKey = integerValue(argv[++i]);
|
||||
if( iKey<1 ) fatalError("the --start must be positive");
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-stats")==0 ){
|
||||
bStats = 1;
|
||||
continue;
|
||||
}
|
||||
if( strcmp(z, "-update")==0 ){
|
||||
isUpdateTest = 1;
|
||||
continue;
|
||||
}
|
||||
fatalError("unknown option: \"%s\"", argv[i]);
|
||||
}
|
||||
if( eType==PATH_DB ){
|
||||
/* Recover any prior crashes prior to starting the timer */
|
||||
sqlite3_open(zDb, &db);
|
||||
sqlite3_exec(db, "SELECT rowid FROM sqlite_master LIMIT 1", 0, 0, 0);
|
||||
sqlite3_close(db);
|
||||
db = 0;
|
||||
}
|
||||
tmStart = timeOfDay();
|
||||
if( eType==PATH_DB ){
|
||||
char *zSql;
|
||||
@@ -724,9 +932,13 @@ static int runMain(int argc, char **argv){
|
||||
}
|
||||
zSql = sqlite3_mprintf("PRAGMA mmap_size=%d", mmapSize);
|
||||
sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
zSql = sqlite3_mprintf("PRAGMA cache_size=%d", iCache);
|
||||
sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( noSync ){
|
||||
sqlite3_exec(db, "PRAGMA synchronous=OFF", 0, 0, 0);
|
||||
}
|
||||
pStmt = 0;
|
||||
sqlite3_prepare_v2(db, "PRAGMA page_size", -1, &pStmt, 0);
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
@@ -745,6 +957,9 @@ static int runMain(int argc, char **argv){
|
||||
zSql = sqlite3_mprintf("PRAGMA journal_mode=%Q", zJMode);
|
||||
sqlite3_exec(db, zSql, 0, 0, 0);
|
||||
sqlite3_free(zSql);
|
||||
if( noCheckpoint ){
|
||||
sqlite3_exec(db, "PRAGMA wal_autocheckpoint=0", 0, 0, 0);
|
||||
}
|
||||
}
|
||||
sqlite3_prepare_v2(db, "PRAGMA journal_mode", -1, &pStmt, 0);
|
||||
if( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
@@ -761,22 +976,32 @@ static int runMain(int argc, char **argv){
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
pStmt = 0;
|
||||
sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
if( !doMultiTrans ) sqlite3_exec(db, "BEGIN", 0, 0, 0);
|
||||
}
|
||||
if( iMax<=0 ) iMax = 1000;
|
||||
for(i=0; i<nCount; i++){
|
||||
if( eType==PATH_DIR ){
|
||||
/* CASE 1: Reading blobs out of separate files */
|
||||
if( eType==PATH_DIR || eType==PATH_TREE ){
|
||||
/* CASE 1: Reading or writing blobs out of separate files */
|
||||
char *zKey;
|
||||
zKey = sqlite3_mprintf("%s/%06d", zDb, iKey);
|
||||
if( eType==PATH_DIR ){
|
||||
zKey = sqlite3_mprintf("%s/%06d", zDb, iKey);
|
||||
}else{
|
||||
zKey = sqlite3_mprintf("%s/%02d/%02d/%02d", zDb, iKey/10000,
|
||||
(iKey/100)%100, iKey%100);
|
||||
}
|
||||
nData = 0;
|
||||
pData = readFile(zKey, &nData);
|
||||
if( isUpdateTest ){
|
||||
updateFile(zKey, &nData, doFsync);
|
||||
}else{
|
||||
pData = readFile(zKey, &nData);
|
||||
sqlite3_free(pData);
|
||||
}
|
||||
sqlite3_free(zKey);
|
||||
sqlite3_free(pData);
|
||||
}else if( bBlobApi ){
|
||||
/* CASE 2: Reading from database using the incremental BLOB I/O API */
|
||||
if( pBlob==0 ){
|
||||
rc = sqlite3_blob_open(db, "main", "kv", "v", iKey, 0, &pBlob);
|
||||
rc = sqlite3_blob_open(db, "main", "kv", "v", iKey,
|
||||
isUpdateTest, &pBlob);
|
||||
if( rc ){
|
||||
fatalError("could not open sqlite3_blob handle: %s",
|
||||
sqlite3_errmsg(db));
|
||||
@@ -788,20 +1013,39 @@ static int runMain(int argc, char **argv){
|
||||
nData = sqlite3_blob_bytes(pBlob);
|
||||
if( nAlloc<nData+1 ){
|
||||
nAlloc = nData+100;
|
||||
pData = sqlite3_realloc(pData, nAlloc);
|
||||
pData = sqlite3_realloc64(pData, nAlloc);
|
||||
}
|
||||
if( pData==0 ) fatalError("cannot allocate %d bytes", nData+1);
|
||||
rc = sqlite3_blob_read(pBlob, pData, nData, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fatalError("could not read the blob at %d: %s", iKey,
|
||||
sqlite3_errmsg(db));
|
||||
if( isUpdateTest ){
|
||||
sqlite3_randomness((int)nData, pData);
|
||||
rc = sqlite3_blob_write(pBlob, pData, (int)nData, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fatalError("could not write the blob at %d: %s", iKey,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
}else{
|
||||
rc = sqlite3_blob_read(pBlob, pData, (int)nData, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
fatalError("could not read the blob at %d: %s", iKey,
|
||||
sqlite3_errmsg(db));
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* CASE 3: Reading from database using SQL */
|
||||
if( pStmt==0 ){
|
||||
rc = sqlite3_prepare_v2(db,
|
||||
"SELECT v FROM kv WHERE k=?1", -1, &pStmt, 0);
|
||||
if( isUpdateTest ){
|
||||
sqlite3_create_function(db, "remember", 2, SQLITE_UTF8, 0,
|
||||
rememberFunc, 0, 0);
|
||||
|
||||
rc = sqlite3_prepare_v2(db,
|
||||
"UPDATE kv SET v=randomblob(remember(length(v),?2))"
|
||||
" WHERE k=?1", -1, &pStmt, 0);
|
||||
sqlite3_bind_int64(pStmt, 2, SQLITE_PTR_TO_INT(&nData));
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(db,
|
||||
"SELECT v FROM kv WHERE k=?1", -1, &pStmt, 0);
|
||||
}
|
||||
if( rc ){
|
||||
fatalError("cannot prepare query: %s", sqlite3_errmsg(db));
|
||||
}
|
||||
@@ -809,12 +1053,11 @@ static int runMain(int argc, char **argv){
|
||||
sqlite3_reset(pStmt);
|
||||
}
|
||||
sqlite3_bind_int(pStmt, 1, iKey);
|
||||
nData = 0;
|
||||
rc = sqlite3_step(pStmt);
|
||||
if( rc==SQLITE_ROW ){
|
||||
nData = sqlite3_column_bytes(pStmt, 0);
|
||||
pData = (unsigned char*)sqlite3_column_blob(pStmt, 0);
|
||||
}else{
|
||||
nData = 0;
|
||||
}
|
||||
}
|
||||
if( eOrder==ORDER_ASC ){
|
||||
@@ -835,13 +1078,33 @@ static int runMain(int argc, char **argv){
|
||||
if( bStats ){
|
||||
display_stats(db, 0);
|
||||
}
|
||||
if( db ) sqlite3_close(db);
|
||||
if( db ){
|
||||
if( !doMultiTrans ) sqlite3_exec(db, "COMMIT", 0, 0, 0);
|
||||
if( !noCheckpoint ){
|
||||
sqlite3_close(db);
|
||||
db = 0;
|
||||
}
|
||||
}
|
||||
tmElapsed = timeOfDay() - tmStart;
|
||||
if( db && noCheckpoint ){
|
||||
sqlite3_close(db);
|
||||
db = 0;
|
||||
}
|
||||
if( nExtra ){
|
||||
printf("%d cycles due to %d misses\n", nCount, nExtra);
|
||||
}
|
||||
if( eType==PATH_DB ){
|
||||
printf("SQLite version: %s\n", sqlite3_libversion());
|
||||
if( doIntegrityCk ){
|
||||
sqlite3_open(zDb, &db);
|
||||
sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &pStmt, 0);
|
||||
while( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||
printf("integrity-check: %s\n", sqlite3_column_text(pStmt, 0));
|
||||
}
|
||||
sqlite3_finalize(pStmt);
|
||||
sqlite3_close(db);
|
||||
db = 0;
|
||||
}
|
||||
}
|
||||
printf("--count %d --max-id %d", nCount-nExtra, iMax);
|
||||
switch( eOrder ){
|
||||
@@ -852,11 +1115,17 @@ static int runMain(int argc, char **argv){
|
||||
if( eType==PATH_DB ){
|
||||
printf("--cache-size %d --jmode %s\n", iCache, zJMode);
|
||||
printf("--mmap %d%s\n", mmapSize, bBlobApi ? " --blob-api" : "");
|
||||
if( noSync ) printf("--nosync\n");
|
||||
}
|
||||
if( iPagesize ) printf("Database page size: %d\n", iPagesize);
|
||||
printf("Total elapsed time: %.3f\n", tmElapsed/1000.0);
|
||||
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
|
||||
printf("Content read rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
|
||||
if( isUpdateTest ){
|
||||
printf("Microseconds per BLOB write: %.3f\n", tmElapsed*1000.0/nCount);
|
||||
printf("Content write rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
|
||||
}else{
|
||||
printf("Microseconds per BLOB read: %.3f\n", tmElapsed*1000.0/nCount);
|
||||
printf("Content read rate: %.1f MB/s\n", nTotal/(1000.0*tmElapsed));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -179,7 +179,7 @@ array set ::Configs [strip_comments {
|
||||
-DSQLITE_ENABLE_LOCKING_STYLE=1
|
||||
}
|
||||
"Apple" {
|
||||
-O1 # Avoid a compiler bug in gcc 4.2.1 build 5658
|
||||
-Os
|
||||
-DHAVE_GMTIME_R=1
|
||||
-DHAVE_ISNAN=1
|
||||
-DHAVE_LOCALTIME_R=1
|
||||
@@ -1036,7 +1036,7 @@ proc main {argv} {
|
||||
regsub -all {fuzzoomtest} $xtarget fuzztest xtarget
|
||||
if {$debug_idx < 0} {
|
||||
incr NTEST
|
||||
append config_options " -DSQLITE_DEBUG=1"
|
||||
append config_options " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1"
|
||||
add_test_suite all "${zConfig}_debug" $xtarget $config_options
|
||||
} else {
|
||||
incr NTEST
|
||||
|
||||
+22
-18
@@ -216,24 +216,28 @@ if {$tcl_platform(platform)!="windows" || \
|
||||
} {}
|
||||
|
||||
set pwd [pwd]
|
||||
do_execsql_test 3.5 {
|
||||
SELECT path, size FROM fstree WHERE path GLOB $pwd || '/subdir/*' ORDER BY 1
|
||||
} [list \
|
||||
"$pwd/subdir/x1.txt" 143 \
|
||||
"$pwd/subdir/x2.txt" 153 \
|
||||
]
|
||||
do_execsql_test 3.6 {
|
||||
SELECT path, size FROM fstree WHERE path LIKE $pwd || '/subdir/%' ORDER BY 1
|
||||
} [list \
|
||||
"$pwd/subdir/x1.txt" 143 \
|
||||
"$pwd/subdir/x2.txt" 153 \
|
||||
]
|
||||
do_execsql_test 3.7 {
|
||||
SELECT sum(size) FROM fstree WHERE path LIKE $pwd || '/subdir/%'
|
||||
} 296
|
||||
do_execsql_test 3.8 {
|
||||
SELECT size FROM fstree WHERE path = $pwd || '/subdir/x1.txt'
|
||||
} 143
|
||||
if {![string match {*[_%]*} $pwd]} {
|
||||
do_execsql_test 3.5 {
|
||||
SELECT path, size FROM fstree
|
||||
WHERE path GLOB $pwd || '/subdir/*' ORDER BY 1
|
||||
} [list \
|
||||
"$pwd/subdir/x1.txt" 143 \
|
||||
"$pwd/subdir/x2.txt" 153 \
|
||||
]
|
||||
do_execsql_test 3.6 {
|
||||
SELECT path, size FROM fstree
|
||||
WHERE path LIKE $pwd || '/subdir/%' ORDER BY 1
|
||||
} [list \
|
||||
"$pwd/subdir/x1.txt" 143 \
|
||||
"$pwd/subdir/x2.txt" 153 \
|
||||
]
|
||||
do_execsql_test 3.7 {
|
||||
SELECT sum(size) FROM fstree WHERE path LIKE $pwd || '/subdir/%'
|
||||
} 296
|
||||
do_execsql_test 3.8 {
|
||||
SELECT size FROM fstree WHERE path = $pwd || '/subdir/x1.txt'
|
||||
} 143
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -990,5 +990,19 @@ do_execsql_test 18.2 {
|
||||
SELECT 1 FROM xyz;
|
||||
} 1
|
||||
|
||||
# EXPLAIN QUERY PLAN on a self-join of a CTE
|
||||
#
|
||||
do_execsql_test 19.1 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(x);
|
||||
EXPLAIN QUERY PLAN
|
||||
WITH
|
||||
x1(a) AS (values(100))
|
||||
INSERT INTO t1(x)
|
||||
SELECT * FROM (WITH x2(y) AS (SELECT * FROM x1) SELECT y+a FROM x1, x2);
|
||||
SELECT * FROM t1;
|
||||
} {0 0 0 {SCAN SUBQUERY 1} 0 1 1 {SCAN SUBQUERY 1}}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -51,7 +51,6 @@ cp sqlite3.h $TMPSPACE
|
||||
cp sqlite3ext.h $TMPSPACE
|
||||
cp $TOP/sqlite3.1 $TMPSPACE
|
||||
cp $TOP/sqlite3.pc.in $TMPSPACE
|
||||
cp $TOP/src/msvc.h $TMPSPACE
|
||||
cp $TOP/src/shell.c $TMPSPACE
|
||||
cp $TOP/src/sqlite3.rc $TMPSPACE
|
||||
cp $TOP/tool/Replace.cs $TMPSPACE
|
||||
|
||||
@@ -0,0 +1,311 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# To build the
|
||||
#
|
||||
# const char **azCompileOpt[]
|
||||
#
|
||||
# declaration used in src/ctime.c, run this script.
|
||||
#
|
||||
|
||||
# All Boolean compile time options.
|
||||
#
|
||||
set boolean_options {
|
||||
SQLITE_32BIT_ROWID
|
||||
SQLITE_4_BYTE_ALIGNED_MALLOC
|
||||
SQLITE_64BIT_STATS
|
||||
SQLITE_ALLOW_COVERING_INDEX_SCAN
|
||||
SQLITE_ALLOW_URI_AUTHORITY
|
||||
SQLITE_BUG_COMPATIBLE_20160819
|
||||
SQLITE_CASE_SENSITIVE_LIKE
|
||||
SQLITE_CHECK_PAGES
|
||||
SQLITE_COVERAGE_TEST
|
||||
SQLITE_DEBUG
|
||||
SQLITE_DEFAULT_AUTOMATIC_INDEX
|
||||
SQLITE_DEFAULT_AUTOVACUUM
|
||||
SQLITE_DEFAULT_CKPTFULLFSYNC
|
||||
SQLITE_DEFAULT_FOREIGN_KEYS
|
||||
SQLITE_DEFAULT_LOCKING_MODE
|
||||
SQLITE_DEFAULT_MEMSTATUS
|
||||
SQLITE_DEFAULT_RECURSIVE_TRIGGERS
|
||||
SQLITE_DEFAULT_SYNCHRONOUS
|
||||
SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
SQLITE_DIRECT_OVERFLOW_READ
|
||||
SQLITE_DISABLE_DIRSYNC
|
||||
SQLITE_DISABLE_FTS3_UNICODE
|
||||
SQLITE_DISABLE_FTS4_DEFERRED
|
||||
SQLITE_DISABLE_INTRINSIC
|
||||
SQLITE_DISABLE_LFS
|
||||
SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
|
||||
SQLITE_DISABLE_SKIPAHEAD_DISTINCT
|
||||
SQLITE_ENABLE_8_3_NAMES
|
||||
SQLITE_ENABLE_API_ARMOR
|
||||
SQLITE_ENABLE_ATOMIC_WRITE
|
||||
SQLITE_ENABLE_CEROD
|
||||
SQLITE_ENABLE_COLUMN_METADATA
|
||||
SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
SQLITE_ENABLE_COSTMULT
|
||||
SQLITE_ENABLE_CURSOR_HINTS
|
||||
SQLITE_ENABLE_DBSTAT_VTAB
|
||||
SQLITE_ENABLE_EXPENSIVE_ASSERT
|
||||
SQLITE_ENABLE_FTS1
|
||||
SQLITE_ENABLE_FTS2
|
||||
SQLITE_ENABLE_FTS3
|
||||
SQLITE_ENABLE_FTS3_PARENTHESIS
|
||||
SQLITE_ENABLE_FTS3_TOKENIZER
|
||||
SQLITE_ENABLE_FTS4
|
||||
SQLITE_ENABLE_FTS5
|
||||
SQLITE_ENABLE_HIDDEN_COLUMNS
|
||||
SQLITE_ENABLE_ICU
|
||||
SQLITE_ENABLE_IOTRACE
|
||||
SQLITE_ENABLE_JSON1
|
||||
SQLITE_ENABLE_LOAD_EXTENSION
|
||||
SQLITE_ENABLE_LOCKING_STYLE
|
||||
SQLITE_ENABLE_MEMORY_MANAGEMENT
|
||||
SQLITE_ENABLE_MEMSYS3
|
||||
SQLITE_ENABLE_MEMSYS5
|
||||
SQLITE_ENABLE_MULTIPLEX
|
||||
SQLITE_ENABLE_NULL_TRIM
|
||||
SQLITE_ENABLE_OVERSIZE_CELL_CHECK
|
||||
SQLITE_ENABLE_PREUPDATE_HOOK
|
||||
SQLITE_ENABLE_RBU
|
||||
SQLITE_ENABLE_RTREE
|
||||
SQLITE_ENABLE_SELECTTRACE
|
||||
SQLITE_ENABLE_SESSION
|
||||
SQLITE_ENABLE_SNAPSHOT
|
||||
SQLITE_ENABLE_SQLLOG
|
||||
SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
||||
SQLITE_ENABLE_UNLOCK_NOTIFY
|
||||
SQLITE_ENABLE_UPDATE_DELETE_LIMIT
|
||||
SQLITE_ENABLE_URI_00_ERROR
|
||||
SQLITE_ENABLE_VFSTRACE
|
||||
SQLITE_ENABLE_WHERETRACE
|
||||
SQLITE_ENABLE_ZIPVFS
|
||||
SQLITE_EXPLAIN_ESTIMATED_ROWS
|
||||
SQLITE_EXTRA_IFNULLROW
|
||||
SQLITE_FTS5_ENABLE_TEST_MI
|
||||
SQLITE_FTS5_NO_WITHOUT_ROWID
|
||||
SQLITE_HAS_CODEC
|
||||
SQLITE_HOMEGROWN_RECURSIVE_MUTEX
|
||||
SQLITE_IGNORE_AFP_LOCK_ERRORS
|
||||
SQLITE_IGNORE_FLOCK_LOCK_ERRORS
|
||||
SQLITE_INLINE_MEMCPY
|
||||
SQLITE_INT64_TYPE
|
||||
SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
||||
SQLITE_LOCK_TRACE
|
||||
SQLITE_LOG_CACHE_SPILL
|
||||
SQLITE_MEMDEBUG
|
||||
SQLITE_MIXED_ENDIAN_64BIT_FLOAT
|
||||
SQLITE_MMAP_READWRITE
|
||||
SQLITE_MUTEX_NOOP
|
||||
SQLITE_MUTEX_NREF
|
||||
SQLITE_MUTEX_OMIT
|
||||
SQLITE_MUTEX_PTHREADS
|
||||
SQLITE_MUTEX_W32
|
||||
SQLITE_NEED_ERR_NAME
|
||||
SQLITE_NOINLINE
|
||||
SQLITE_NO_SYNC
|
||||
SQLITE_OMIT_ALTERTABLE
|
||||
SQLITE_OMIT_ANALYZE
|
||||
SQLITE_OMIT_ATTACH
|
||||
SQLITE_OMIT_AUTHORIZATION
|
||||
SQLITE_OMIT_AUTOINCREMENT
|
||||
SQLITE_OMIT_AUTOINIT
|
||||
SQLITE_OMIT_AUTOMATIC_INDEX
|
||||
SQLITE_OMIT_AUTORESET
|
||||
SQLITE_OMIT_AUTOVACUUM
|
||||
SQLITE_OMIT_BETWEEN_OPTIMIZATION
|
||||
SQLITE_OMIT_BLOB_LITERAL
|
||||
SQLITE_OMIT_BTREECOUNT
|
||||
SQLITE_OMIT_CAST
|
||||
SQLITE_OMIT_CHECK
|
||||
SQLITE_OMIT_COMPLETE
|
||||
SQLITE_OMIT_COMPOUND_SELECT
|
||||
SQLITE_OMIT_CONFLICT_CLAUSE
|
||||
SQLITE_OMIT_CTE
|
||||
SQLITE_OMIT_DATETIME_FUNCS
|
||||
SQLITE_OMIT_DECLTYPE
|
||||
SQLITE_OMIT_DEPRECATED
|
||||
SQLITE_OMIT_DISKIO
|
||||
SQLITE_OMIT_EXPLAIN
|
||||
SQLITE_OMIT_FLAG_PRAGMAS
|
||||
SQLITE_OMIT_FLOATING_POINT
|
||||
SQLITE_OMIT_FOREIGN_KEY
|
||||
SQLITE_OMIT_GET_TABLE
|
||||
SQLITE_OMIT_HEX_INTEGER
|
||||
SQLITE_OMIT_INCRBLOB
|
||||
SQLITE_OMIT_INTEGRITY_CHECK
|
||||
SQLITE_OMIT_LIKE_OPTIMIZATION
|
||||
SQLITE_OMIT_LOAD_EXTENSION
|
||||
SQLITE_OMIT_LOCALTIME
|
||||
SQLITE_OMIT_LOOKASIDE
|
||||
SQLITE_OMIT_MEMORYDB
|
||||
SQLITE_OMIT_OR_OPTIMIZATION
|
||||
SQLITE_OMIT_PAGER_PRAGMAS
|
||||
SQLITE_OMIT_PARSER_TRACE
|
||||
SQLITE_OMIT_POPEN
|
||||
SQLITE_OMIT_PRAGMA
|
||||
SQLITE_OMIT_PROGRESS_CALLBACK
|
||||
SQLITE_OMIT_QUICKBALANCE
|
||||
SQLITE_OMIT_REINDEX
|
||||
SQLITE_OMIT_SCHEMA_PRAGMAS
|
||||
SQLITE_OMIT_SCHEMA_VERSION_PRAGMAS
|
||||
SQLITE_OMIT_SHARED_CACHE
|
||||
SQLITE_OMIT_SHUTDOWN_DIRECTORIES
|
||||
SQLITE_OMIT_SUBQUERY
|
||||
SQLITE_OMIT_TCL_VARIABLE
|
||||
SQLITE_OMIT_TEMPDB
|
||||
SQLITE_OMIT_TEST_CONTROL
|
||||
SQLITE_OMIT_TRACE
|
||||
SQLITE_OMIT_TRIGGER
|
||||
SQLITE_OMIT_TRUNCATE_OPTIMIZATION
|
||||
SQLITE_OMIT_UTF16
|
||||
SQLITE_OMIT_VACUUM
|
||||
SQLITE_OMIT_VIEW
|
||||
SQLITE_OMIT_VIRTUALTABLE
|
||||
SQLITE_OMIT_WAL
|
||||
SQLITE_OMIT_WSD
|
||||
SQLITE_OMIT_XFER_OPT
|
||||
SQLITE_PCACHE_SEPARATE_HEADER
|
||||
SQLITE_PERFORMANCE_TRACE
|
||||
SQLITE_POWERSAFE_OVERWRITE
|
||||
SQLITE_PREFER_PROXY_LOCKING
|
||||
SQLITE_PROXY_DEBUG
|
||||
SQLITE_REVERSE_UNORDERED_SELECTS
|
||||
SQLITE_RTREE_INT_ONLY
|
||||
SQLITE_SECURE_DELETE
|
||||
SQLITE_SMALL_STACK
|
||||
SQLITE_SOUNDEX
|
||||
SQLITE_SUBSTR_COMPATIBILITY
|
||||
SQLITE_SYSTEM_MALLOC
|
||||
SQLITE_TCL
|
||||
SQLITE_TEST
|
||||
SQLITE_UNLINK_AFTER_CLOSE
|
||||
SQLITE_UNTESTABLE
|
||||
SQLITE_USE_ALLOCA
|
||||
SQLITE_USE_FCNTL_TRACE
|
||||
SQLITE_USER_AUTHENTICATION
|
||||
SQLITE_USE_URI
|
||||
SQLITE_VDBE_COVERAGE
|
||||
SQLITE_WIN32_MALLOC
|
||||
SQLITE_ZERO_MALLOC
|
||||
}
|
||||
|
||||
# All compile time options for which the assigned value is other than boolean.
|
||||
#
|
||||
set value_options {
|
||||
SQLITE_BITMASK_TYPE
|
||||
SQLITE_DEFAULT_CACHE_SIZE
|
||||
SQLITE_DEFAULT_FILE_FORMAT
|
||||
SQLITE_DEFAULT_FILE_PERMISSIONS
|
||||
SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT
|
||||
SQLITE_DEFAULT_LOCKING_MODE
|
||||
SQLITE_DEFAULT_LOOKASIDE
|
||||
SQLITE_DEFAULT_MMAP_SIZE
|
||||
SQLITE_DEFAULT_PAGE_SIZE
|
||||
SQLITE_DEFAULT_PCACHE_INITSZ
|
||||
SQLITE_DEFAULT_PROXYDIR_PERMISSIONS
|
||||
SQLITE_DEFAULT_ROWEST
|
||||
SQLITE_DEFAULT_SECTOR_SIZE
|
||||
SQLITE_DEFAULT_SYNCHRONOUS
|
||||
SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
|
||||
SQLITE_DEFAULT_WAL_SYNCHRONOUS
|
||||
SQLITE_DEFAULT_WORKER_THREADS
|
||||
SQLITE_ENABLE_8_3_NAMES
|
||||
SQLITE_ENABLE_LOCKING_STYLE
|
||||
SQLITE_EXTRA_INIT
|
||||
SQLITE_EXTRA_SHUTDOWN
|
||||
SQLITE_FTS3_MAX_EXPR_DEPTH
|
||||
SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
||||
SQLITE_MALLOC_SOFT_LIMIT
|
||||
SQLITE_MAX_ATTACHED
|
||||
SQLITE_MAX_COLUMN
|
||||
SQLITE_MAX_COMPOUND_SELECT
|
||||
SQLITE_MAX_DEFAULT_PAGE_SIZE
|
||||
SQLITE_MAX_EXPR_DEPTH
|
||||
SQLITE_MAX_FUNCTION_ARG
|
||||
SQLITE_MAX_LENGTH
|
||||
SQLITE_MAX_LIKE_PATTERN_LENGTH
|
||||
SQLITE_MAX_MEMORY
|
||||
SQLITE_MAX_MMAP_SIZE
|
||||
SQLITE_MAX_MMAP_SIZE_
|
||||
SQLITE_MAX_PAGE_COUNT
|
||||
SQLITE_MAX_PAGE_SIZE
|
||||
SQLITE_MAX_SCHEMA_RETRY
|
||||
SQLITE_MAX_SQL_LENGTH
|
||||
SQLITE_MAX_TRIGGER_DEPTH
|
||||
SQLITE_MAX_VARIABLE_NUMBER
|
||||
SQLITE_MAX_VDBE_OP
|
||||
SQLITE_MAX_WORKER_THREADS
|
||||
SQLITE_SORTER_PMASZ
|
||||
SQLITE_STAT4_SAMPLES
|
||||
SQLITE_STMTJRNL_SPILL
|
||||
SQLITE_TEMP_STORE
|
||||
}
|
||||
|
||||
# Options that require custom code.
|
||||
#
|
||||
set options(ENABLE_STAT3) {
|
||||
#if defined(SQLITE_ENABLE_STAT4)
|
||||
"ENABLE_STAT4",
|
||||
#elif defined(SQLITE_ENABLE_STAT3)
|
||||
"ENABLE_STAT3",
|
||||
#endif
|
||||
}
|
||||
set options(COMPILER) {
|
||||
#if defined(__clang__) && defined(__clang_major__)
|
||||
"COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
|
||||
CTIMEOPT_VAL(__clang_minor__) "."
|
||||
CTIMEOPT_VAL(__clang_patchlevel__),
|
||||
#elif defined(_MSC_VER)
|
||||
"COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
|
||||
#elif defined(__GNUC__) && defined(__VERSION__)
|
||||
"COMPILER=gcc-" __VERSION__,
|
||||
#endif
|
||||
}
|
||||
set options(HAVE_ISNAN) {
|
||||
#if HAVE_ISNAN || SQLITE_HAVE_ISNAN
|
||||
"HAVE_ISNAN",
|
||||
#endif
|
||||
}
|
||||
set options(THREADSAFE) {
|
||||
#if defined(SQLITE_THREADSAFE)
|
||||
"THREADSAFE=" CTIMEOPT_VAL(SQLITE_THREADSAFE),
|
||||
#elif defined(THREADSAFE)
|
||||
"THREADSAFE=" CTIMEOPT_VAL(THREADSAFE),
|
||||
#else
|
||||
"THREADSAFE=1"
|
||||
#endif
|
||||
}
|
||||
|
||||
proc trim_name {in} {
|
||||
set ret $in
|
||||
if {[string range $in 0 6]=="SQLITE_"} {
|
||||
set ret [string range $in 7 end]
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
foreach b $boolean_options {
|
||||
set name [trim_name $b]
|
||||
set options($name) [subst {
|
||||
#if $b
|
||||
"$name",
|
||||
#endif
|
||||
}]
|
||||
}
|
||||
|
||||
foreach v $value_options {
|
||||
set name [trim_name $v]
|
||||
set options($name) [subst {
|
||||
#ifdef $v
|
||||
"$name=" CTIMEOPT_VAL($v),
|
||||
#endif
|
||||
}]
|
||||
}
|
||||
|
||||
foreach o [lsort [array names options]] {
|
||||
puts [string trim $options($o)]
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -282,10 +282,10 @@ proc copy_file {filename} {
|
||||
# inlining opportunities.
|
||||
#
|
||||
foreach file {
|
||||
ctime.c
|
||||
sqliteInt.h
|
||||
|
||||
global.c
|
||||
ctime.c
|
||||
status.c
|
||||
date.c
|
||||
os.c
|
||||
|
||||
@@ -424,6 +424,7 @@ proc subreport {title where showFrag} {
|
||||
# avg_payload: Average payload per btree entry.
|
||||
# avg_fanout: Average fanout for internal pages.
|
||||
# avg_unused: Average unused bytes per btree entry.
|
||||
# avg_meta: Average metadata overhead per entry.
|
||||
# ovfl_cnt_percent: Percentage of btree entries that use overflow pages.
|
||||
#
|
||||
set total_pages [expr {$leaf_pages+$int_pages+$ovfl_pages}]
|
||||
@@ -433,6 +434,10 @@ proc subreport {title where showFrag} {
|
||||
set total_unused [expr {$ovfl_unused+$int_unused+$leaf_unused}]
|
||||
set avg_payload [divide $payload $nentry]
|
||||
set avg_unused [divide $total_unused $nentry]
|
||||
set total_meta [expr {$storage - $payload - $total_unused}]
|
||||
set total_meta [expr {$total_meta + 4*($ovfl_pages - $ovfl_cnt)}]
|
||||
set meta_percent [percent $total_meta $storage {of metadata}]
|
||||
set avg_meta [divide $total_meta $nentry]
|
||||
if {$int_pages>0} {
|
||||
# TODO: Is this formula correct?
|
||||
set nTab [mem eval "
|
||||
@@ -460,9 +465,11 @@ proc subreport {title where showFrag} {
|
||||
statline {Bytes used after compression} $compressed_size $pct
|
||||
}
|
||||
statline {Bytes of payload} $payload $payload_percent
|
||||
statline {Bytes of metadata} $total_meta $meta_percent
|
||||
if {$cnt==1} {statline {B-tree depth} $depth}
|
||||
statline {Average payload per entry} $avg_payload
|
||||
statline {Average unused bytes per entry} $avg_unused
|
||||
statline {Average metadata per entry} $avg_meta
|
||||
if {[info exists avg_fanout]} {
|
||||
statline {Average fanout} $avg_fanout
|
||||
}
|
||||
@@ -757,6 +764,16 @@ Bytes of payload
|
||||
at the right is the bytes of payload divided by the bytes of storage
|
||||
consumed.
|
||||
|
||||
Bytes of metadata
|
||||
|
||||
The amount of formatting and structural information stored in the
|
||||
table or index. Metadata includes the btree page header, the cell pointer
|
||||
array, the size field for each cell, the left child pointer or non-leaf
|
||||
cells, the overflow pointers for overflow cells, and the rowid value for
|
||||
rowid table cells. In other words, metadata is everything that is neither
|
||||
unused space nor content. The record header in the payload is counted as
|
||||
content, not metadata.
|
||||
|
||||
Average payload per entry
|
||||
|
||||
The average amount of payload on each entry. This is just the bytes of
|
||||
|
||||
+1
-1
@@ -1667,7 +1667,7 @@ static void changeset_one_table(const char *zTab, FILE *out){
|
||||
|
||||
putc('T', out);
|
||||
putsVarint(out, (sqlite3_uint64)nCol);
|
||||
for(i=0; i<nCol; i++) putc(aiFlg[i]!=0, out);
|
||||
for(i=0; i<nCol; i++) putc(aiFlg[i], out);
|
||||
fwrite(zTab, 1, strlen(zTab), out);
|
||||
putc(0, out);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user