Snapshot of upstream SQLite 3.33.0

This commit is contained in:
Stephen Lombardo
2020-08-17 13:03:40 -04:00
parent ed8f99586a
commit 56e56568ce
188 changed files with 8867 additions and 1893 deletions
+16 -4
View File
@@ -443,6 +443,7 @@ TESTSRC += \
$(TOP)/ext/misc/carray.c \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/eval.c \
$(TOP)/ext/misc/explain.c \
$(TOP)/ext/misc/fileio.c \
@@ -1067,6 +1068,12 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE)
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
sqlite3rc.h: $(TOP)/src/sqlite3.rc $(TOP)/VERSION
echo '#ifndef SQLITE_RESOURCE_VERSION' >$@
echo -n '#define SQLITE_RESOURCE_VERSION ' >>$@
cat $(TOP)/VERSION | $(TCLSH_CMD) $(TOP)/tool/replace.tcl exact . , >>$@
echo '#endif' >>sqlite3rc.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
./mkkeywordhash$(BEXE) >keywordhash.h
@@ -1075,9 +1082,11 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
SHELL_SRC = \
$(TOP)/src/shell.c.in \
$(TOP)/ext/misc/appendvfs.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/completion.c \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/sqlar.c \
$(TOP)/ext/misc/uint.c \
$(TOP)/ext/expert/sqlite3expert.c \
@@ -1286,6 +1295,9 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
./testfixture$(TEXT) $(TOP)/test/permutations.test shell
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
@@ -1388,10 +1400,10 @@ checksymbols: sqlite3.o
# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz.
# The snapshot-tarball target builds a tarball named by the SHA1 hash
#
amalgamation-tarball: sqlite3.c
amalgamation-tarball: sqlite3.c sqlite3rc.h
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal
snapshot-tarball: sqlite3.c
snapshot-tarball: sqlite3.c sqlite3rc.h
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot
# The next two rules are used to support the "threadtest" target. Building
+28 -11
View File
@@ -1495,7 +1495,7 @@ SRC12 =
# All source code files.
#
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11) $(SRC12)
# Source code to the test files.
#
@@ -1560,6 +1560,7 @@ TESTEXT = \
$(TOP)\ext\misc\carray.c \
$(TOP)\ext\misc\closure.c \
$(TOP)\ext\misc\csv.c \
$(TOP)\ext\misc\decimal.c \
$(TOP)\ext\misc\eval.c \
$(TOP)\ext\misc\explain.c \
$(TOP)\ext\misc\fileio.c \
@@ -1846,15 +1847,16 @@ mptest: mptester.exe
for %i in ($(SRC11)) do copy /Y %i tsrc
for %i in ($(SRC12)) do copy /Y %i tsrc
copy /Y fts5.c tsrc
copy /B tsrc\fts5.c +,,
copy /Y fts5.h tsrc
copy /B tsrc\fts5.h +,,
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
$(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl $(OPTS) < tsrc\vdbe.c > vdbe.new
move vdbe.new tsrc\vdbe.c
echo > .target_source
sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
sqlite3.c: .target_source sqlite3ext.h sqlite3session.h $(MKSQLITE3C_TOOL)
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
copy $(TOP)\ext\session\sqlite3session.h .
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
@@ -1869,7 +1871,8 @@ sqlite3.lo: $(SQLITE3C)
# Rules to build the LEMON compiler generator
#
lempar.c: $(TOP)\tool\lempar.c
copy $(TOP)\tool\lempar.c .
copy /Y $(TOP)\tool\lempar.c .
copy /B lempar.c +,,
lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
@@ -2169,7 +2172,8 @@ parse.h: parse.c
parse.c: $(TOP)\src\parse.y lemon.exe
del /Q parse.y parse.h parse.h.temp 2>NUL
copy $(TOP)\src\parse.y .
copy /Y $(TOP)\src\parse.y .
copy /B parse.y +,,
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S parse.y
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
@@ -2182,8 +2186,13 @@ sqlite3ext.h: .target_source
copy /Y sqlite3ext.h tsrc\sqlite3ext.h
!ELSE
copy /Y tsrc\sqlite3ext.h sqlite3ext.h
copy /B sqlite3ext.h +,,
!ENDIF
sqlite3session.h: $(TOP)\ext\session\sqlite3session.h
copy /Y $(TOP)\ext\session\sqlite3session.h .
copy /B sqlite3session.h +,,
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
$(TOP)\tool\mkkeywordhash.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
@@ -2195,10 +2204,12 @@ keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
SHELL_SRC = \
$(TOP)\src\shell.c.in \
$(TOP)\ext\misc\appendvfs.c \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\completion.c \
$(TOP)\ext\misc\uint.c \
$(TOP)\ext\misc\decimal.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\uint.c \
$(TOP)\ext\expert\sqlite3expert.c \
$(TOP)\ext\expert\sqlite3expert.h \
$(TOP)\ext\misc\memtrace.c \
@@ -2329,7 +2340,8 @@ LSM1_SRC = \
$(TOP)\ext\lsm1\lsm_win32.c
fts5parse.c: $(TOP)\ext\fts5\fts5parse.y lemon.exe
copy $(TOP)\ext\fts5\fts5parse.y .
copy /Y $(TOP)\ext\fts5\fts5parse.y .
copy /B fts5parse.y +,,
del /Q fts5parse.h 2>NUL
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) -S fts5parse.y
@@ -2337,11 +2349,13 @@ fts5parse.h: fts5parse.c
fts5.c: $(FTS5_SRC)
$(TCLSH_CMD) $(TOP)\ext\fts5\tool\mkfts5c.tcl
copy $(TOP)\ext\fts5\fts5.h .
copy /Y $(TOP)\ext\fts5\fts5.h .
copy /B fts5.h +,,
lsm1.c: $(LSM1_SRC)
$(TCLSH_CMD) $(TOP)\ext\lsm1\tool\mklsm1c.tcl
copy $(TOP)\ext\lsm1\lsm.h .
copy /Y $(TOP)\ext\lsm1\lsm.h .
copy /B lsm.h +,,
fts5.lo: fts5.c $(HDR) $(EXTHDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) $(NO_WARN) -DSQLITE_CORE -c fts5.c
@@ -2452,6 +2466,9 @@ smoketest: $(TESTPROGS)
@set PATH=$(LIBTCLPATH);$(PATH)
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
.\testfixture.exe $(TOP)\test\permutations.test shell
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
+1 -1
View File
@@ -1 +1 @@
3.32.3
3.33.0
+1 -1
View File
@@ -13,7 +13,7 @@ sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_D
include_HEADERS = sqlite3.h sqlite3ext.h
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc sqlite3rc.h README.txt Replace.cs Makefile.fallback
pkgconfigdir = ${libdir}/pkgconfig
pkgconfig_DATA = sqlite3.pc
Vendored
+11 -11
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.32.3.
# Generated by GNU Autoconf 2.69 for sqlite 3.33.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.32.3'
PACKAGE_STRING='sqlite 3.32.3'
PACKAGE_VERSION='3.33.0'
PACKAGE_STRING='sqlite 3.33.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1467,7 +1467,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.32.3 to adapt to many kinds of systems.
\`configure' configures sqlite 3.33.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1532,7 +1532,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.32.3:";;
short | recursive ) echo "Configuration of sqlite 3.33.0:";;
esac
cat <<\_ACEOF
@@ -1659,7 +1659,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.32.3
sqlite configure 3.33.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2078,7 +2078,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.32.3, which was
It was created by sqlite $as_me 3.33.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -11268,7 +11268,7 @@ if test "${enable_amalgamation+set}" = set; then :
enableval=$enable_amalgamation;
fi
if test "${enable_amalgamation}" == "no" ; then
if test "${enable_amalgamation}" = "no" ; then
USE_AMALGAMATION=0
fi
@@ -11619,7 +11619,7 @@ if test "${enable_update_limit+set}" = set; then :
enableval=$enable_update_limit;
fi
if test "${enable_udlimit}" = "yes" ; then
if test "${enable_update_limit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
fi
@@ -12243,7 +12243,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.32.3, which was
This file was extended by sqlite $as_me 3.33.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12309,7 +12309,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.32.3
sqlite config.status 3.33.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+2 -2
View File
@@ -569,7 +569,7 @@ AC_SUBST(TARGET_DEBUG)
# See whether we should use the amalgamation to build
AC_ARG_ENABLE(amalgamation, AC_HELP_STRING([--disable-amalgamation],
[Disable the amalgamation and instead build all files separately]))
if test "${enable_amalgamation}" == "no" ; then
if test "${enable_amalgamation}" = "no" ; then
USE_AMALGAMATION=0
fi
AC_SUBST(USE_AMALGAMATION)
@@ -651,7 +651,7 @@ fi
# statements.
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
[Enable the UPDATE/DELETE LIMIT clause]))
if test "${enable_udlimit}" = "yes" ; then
if test "${enable_update_limit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
fi
+26 -9
View File
@@ -104,9 +104,13 @@ Write all output files into <i>directory</i>. Normally, output files
are written into the directory that contains the input grammar file.
<li><b>-D<i>name</i></b>
Define C preprocessor macro <i>name</i>. This macro is usable by
"<tt><a href='#pifdef'>%ifdef</a></tt>" and
"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
"<tt><a href='#pifdef'>%ifdef</a></tt>",
"<tt><a href='#pifdef'>%ifndef</a></tt>", and
"<tt><a href="#pifdef">%if</a></tt> lines
in the grammar file.
<li><b>-E</b>
Run the "%if" preprocessor step only and print the revised grammar
file.
<li><b>-g</b>
Do not generate a parser. Instead write the input grammar to standard
output with all comments, actions, and other extraneous text removed.
@@ -555,9 +559,11 @@ other than that, the order of directives in Lemon is arbitrary.</p>
<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
<li><tt><a href='#default_type'>%default_type</a></tt>
<li><tt><a href='#destructor'>%destructor</a></tt>
<li><tt><a href='#pifdef'>%else</a></tt>
<li><tt><a href='#pifdef'>%endif</a></tt>
<li><tt><a href='#extraarg'>%extra_argument</a></tt>
<li><tt><a href='#pfallback'>%fallback</a></tt>
<li><tt><a href='#pifdef'>%if</a></tt>
<li><tt><a href='#pifdef'>%ifdef</a></tt>
<li><tt><a href='#pifdef'>%ifndef</a></tt>
<li><tt><a href='#pinclude'>%include</a></tt>
@@ -737,10 +743,11 @@ arguments are tokens which fall back to the token identified by the first
argument.</p>
<a name='pifdef'></a>
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
<h4>The <tt>%if</tt> directive and its friends</h4>
<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
<p>The <tt>%if</tt>, <tt>%ifdef</tt>, <tt>%ifndef</tt>, <tt>%else</tt>,
and <tt>%endif</tt> directives
are similar to #if, #ifdef, #ifndef, #else, and #endif in the C-preprocessor,
just not as general.
Each of these directives must begin at the left margin. No whitespace
is allowed between the "%" and the directive name.</p>
@@ -749,12 +756,22 @@ is allowed between the "%" and the directive name.</p>
"<tt>%endif</tt>" is
ignored unless the "-DMACRO" command-line option is used. Grammar text
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
included except when the "-DMACRO" command-line option is used.</p>
included except when the "-DMACRO" command-line option is used.<p>
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
be a single preprocessor symbol name, not a general expression.
There is no "<tt>%else</tt>" directive.</p>
<p>The text in between "<tt>%if</tt> <i>CONDITIONAL</i>" and its
corresponding <tt>%endif</tt> is included only if <i>CONDITIONAL</i>
is true. The CONDITION is one or more macro names, optionally connected
using the "||" and "&amp;&amp;" binary operators, the "!" unary operator,
and grouped using balanced parentheses. Each term is true if the
corresponding macro exists, and false if it does not exist.</p>
<p>An optional "<tt>%else</tt>" directive can occur anywhere in between a
<tt>%ifdef</tt>, <tt>%ifndef</tt>, or <tt>%if</tt> directive and
its corresponding <tt>%endif</tt>.</p>
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> is
intended to be a single preprocessor symbol name, not a general expression.
Use the "<tt>%if</tt>" directive for general expressions.</p>
<a name='pinclude'></a>
<h4>The <tt>%include</tt> directive</h4>
+88
View File
@@ -0,0 +1,88 @@
# Wal-Mode Blocking Locks
On some Unix-like systems, SQLite may be configured to use POSIX blocking locks
by:
* building the library with SQLITE\_ENABLE\_SETLK\_TIMEOUT defined, and
* configuring a timeout in ms using the sqlite3\_busy\_timeout() API.
Blocking locks may be advantageous as (a) waiting database clients do not
need to continuously poll the database lock, and (b) using blocking locks
facilitates transfer of OS priority between processes when a high priority
process is blocked by a lower priority one.
Only read/write clients use blocking locks. Clients that have read-only access
to the \*-shm file nevery use blocking locks.
Threads or processes that access a single database at a time never deadlock as
a result of blocking database locks. But it is of course possible for threads
that lock multiple databases simultaneously to do so. In most cases the OS will
detect the deadlock and return an error.
## Wal Recovery
Wal database "recovery" is a process required when the number of connected
database clients changes from zero to one. In this case, a client is
considered to connect to the database when it first reads data from it.
Before recovery commences, an exclusive WRITER lock is taken.
Without blocking locks, if two clients attempt recovery simultaneously, one
fails to obtain the WRITER lock and either invokes the busy-handler callback or
returns SQLITE\_BUSY to the user. With blocking locks configured, the second
client blocks on the WRITER lock.
## Database Readers
Usually, read-only are not blocked by any other database clients, so they
have no need of blocking locks.
If a read-only transaction is being opened on a snapshot, the CHECKPOINTER
lock is required briefly as part of opening the transaction (to check that a
checkpointer is not currently overwriting the snapshot being opened). A
blocking lock is used to obtain the CHECKPOINTER lock in this case. A snapshot
opener may therefore block on and transfer priority to a checkpointer in some
cases.
## Database Writers
A database writer must obtain the exclusive WRITER lock. It uses a blocking
lock to do so if any of the following are true:
* the transaction is an implicit one consisting of a single DML or DDL
statement, or
* the transaction is opened using BEGIN IMMEDIATE or BEGIN EXCLUSIVE, or
* the first SQL statement executed following the BEGIN command is a DML or
DDL statement (not a read-only statement like a SELECT).
In other words, in all cases except when an open read-transaction is upgraded
to a write-transaction. In that case a non-blocking lock is used.
## Database Checkpointers
Database checkpointers takes the following locks, in order:
* The exclusive CHECKPOINTER lock.
* The exclusive WRITER lock (FULL, RESTART and TRUNCATE only).
* Exclusive lock on read-mark slots 1-N. These are immediately released after being taken.
* Exclusive lock on read-mark 0.
* Exclusive lock on read-mark slots 1-N again. These are immediately released
after being taken (RESTART and TRUNCATE only).
All of the above use blocking locks.
## Summary
With blocking locks configured, the only cases in which clients should see an
SQLITE\_BUSY error are:
* if the OS does not grant a blocking lock before the configured timeout
expires, and
* when an open read-transaction is upgraded to a write-transaction.
In all other cases the blocking locks implementation should prevent clients
from having to handle SQLITE\_BUSY errors and facilitate appropriate transfer
of priorities between competing clients.
Clients that lock multiple databases simultaneously must be wary of deadlock.
-1
View File
@@ -1704,4 +1704,3 @@ int sqlite3async_control(int op, ...){
}
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_ASYNCIO) */
-1
View File
@@ -220,4 +220,3 @@ int sqlite3async_control(int op, ...);
} /* End of the 'extern "C"' block */
#endif
#endif /* ifndef __SQLITEASYNC_H_ */
+8 -8
View File
@@ -1223,7 +1223,7 @@ static int idxProcessOneTrigger(
IdxTable *pTab = pWrite->pTab;
const char *zTab = pTab->zName;
const char *zSql =
"SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_master "
"SELECT 'CREATE TEMP' || substr(sql, 7) FROM sqlite_schema "
"WHERE tbl_name = %Q AND type IN ('table', 'trigger') "
"ORDER BY type;";
sqlite3_stmt *pSelect = 0;
@@ -1323,12 +1323,12 @@ static int idxCreateVtabSchema(sqlite3expert *p, char **pzErrmsg){
** 2) Create the equivalent virtual table in dbv.
*/
rc = idxPrepareStmt(p->db, &pSchema, pzErrmsg,
"SELECT type, name, sql, 1 FROM sqlite_master "
"SELECT type, name, sql, 1 FROM sqlite_schema "
"WHERE type IN ('table','view') AND name NOT LIKE 'sqlite_%%' "
" UNION ALL "
"SELECT type, name, sql, 2 FROM sqlite_master "
"SELECT type, name, sql, 2 FROM sqlite_schema "
"WHERE type = 'trigger'"
" AND tbl_name IN(SELECT name FROM sqlite_master WHERE type = 'view') "
" AND tbl_name IN(SELECT name FROM sqlite_schema WHERE type = 'view') "
"ORDER BY 4, 1"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSchema) ){
@@ -1498,7 +1498,7 @@ static int idxLargestIndex(sqlite3 *db, int *pnMax, char **pzErr){
int rc = SQLITE_OK;
const char *zMax =
"SELECT max(i.seqno) FROM "
" sqlite_master AS s, "
" sqlite_schema AS s, "
" pragma_index_list(s.name) AS l, "
" pragma_index_info(l.name) AS i "
"WHERE s.type = 'table'";
@@ -1651,7 +1651,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
const char *zAllIndex =
"SELECT s.rowid, s.name, l.name FROM "
" sqlite_master AS s, "
" sqlite_schema AS s, "
" pragma_index_list(s.name) AS l "
"WHERE s.type = 'table'";
const char *zIndexXInfo =
@@ -1725,7 +1725,7 @@ static int idxPopulateStat1(sqlite3expert *p, char **pzErr){
sqlite3_free(pCtx);
if( rc==SQLITE_OK ){
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_master", 0, 0, 0);
rc = sqlite3_exec(p->dbm, "ANALYZE sqlite_schema", 0, 0, 0);
}
sqlite3_exec(p->db, "DROP TABLE IF EXISTS temp."UNIQUE_TABLE_NAME,0,0,0);
@@ -1764,7 +1764,7 @@ sqlite3expert *sqlite3_expert_new(sqlite3 *db, char **pzErrmsg){
if( rc==SQLITE_OK ){
sqlite3_stmt *pSql;
rc = idxPrintfPrepareStmt(pNew->db, &pSql, pzErrmsg,
"SELECT sql FROM sqlite_master WHERE name NOT LIKE 'sqlite_%%'"
"SELECT sql FROM sqlite_schema WHERE name NOT LIKE 'sqlite_%%'"
" AND sql NOT LIKE 'CREATE VIRTUAL %%'"
);
while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pSql) ){
-2
View File
@@ -174,5 +174,3 @@ EXTERNAL CONTENT FTS4 TABLES
only be useful if the full-text index has somehow become corrupt. It is an
error to attempt to rebuild the full-text index maintained by a contentless
FTS4 table.
+18 -8
View File
@@ -2068,7 +2068,7 @@ static void fts3PutDeltaVarint(
sqlite3_int64 *piPrev, /* IN/OUT: Previous value written to list */
sqlite3_int64 iVal /* Write this value to the list */
){
assert( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
assert_fts3_nc( iVal-*piPrev > 0 || (*piPrev==0 && iVal==0) );
*pp += sqlite3Fts3PutVarint(*pp, iVal-*piPrev);
*piPrev = iVal;
}
@@ -3479,7 +3479,7 @@ static int fts3ColumnMethod(
break;
}else{
iCol = p->nColumn;
/* fall-through */
/* no break */ deliberate_fall_through
}
default:
@@ -3722,9 +3722,13 @@ static void fts3SnippetFunc(
switch( nVal ){
case 6: nToken = sqlite3_value_int(apVal[5]);
/* no break */ deliberate_fall_through
case 5: iCol = sqlite3_value_int(apVal[4]);
/* no break */ deliberate_fall_through
case 4: zEllipsis = (const char*)sqlite3_value_text(apVal[3]);
/* no break */ deliberate_fall_through
case 3: zEnd = (const char*)sqlite3_value_text(apVal[2]);
/* no break */ deliberate_fall_through
case 2: zStart = (const char*)sqlite3_value_text(apVal[1]);
}
if( !zEllipsis || !zEnd || !zStart ){
@@ -5208,10 +5212,12 @@ static int fts3EvalNearTrim(
);
if( res ){
nNew = (int)(pOut - pPhrase->doclist.pList) - 1;
assert( pPhrase->doclist.pList[nNew]=='\0' );
assert( nNew<=pPhrase->doclist.nList && nNew>0 );
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
pPhrase->doclist.nList = nNew;
if( nNew>=0 ){
assert( pPhrase->doclist.pList[nNew]=='\0' );
assert( nNew<=pPhrase->doclist.nList && nNew>0 );
memset(&pPhrase->doclist.pList[nNew], 0, pPhrase->doclist.nList - nNew);
pPhrase->doclist.nList = nNew;
}
*paPoslist = pPhrase->doclist.pList;
*pnToken = pPhrase->nToken;
}
@@ -5563,7 +5569,10 @@ static int fts3EvalTestExpr(
}else
#endif
{
bHit = (pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId);
bHit = (
pExpr->bEof==0 && pExpr->iDocid==pCsr->iPrevId
&& pExpr->pPhrase->doclist.nList>0
);
}
break;
}
@@ -5826,7 +5835,8 @@ static int fts3EvalGatherStats(
fts3EvalRestart(pCsr, pRoot, &rc);
do {
fts3EvalNextRow(pCsr, pRoot, &rc);
assert( pRoot->bEof==0 );
assert_fts3_nc( pRoot->bEof==0 );
if( pRoot->bEof ) rc = FTS_CORRUPT_VTAB;
}while( pRoot->iDocid!=iDocid && rc==SQLITE_OK );
}
}
+2
View File
@@ -199,6 +199,8 @@ typedef sqlite3_int64 i64; /* 8-byte signed integer */
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
#define deliberate_fall_through
#endif /* SQLITE_AMALGAMATION */
#ifdef SQLITE_DEBUG
+2 -1
View File
@@ -188,7 +188,8 @@ static int fts3tokConnectMethod(
assert( (rc==SQLITE_OK)==(pMod!=0) );
if( rc==SQLITE_OK ){
const char * const *azArg = (const char * const *)&azDequote[1];
const char * const *azArg = 0;
if( nDequote>1 ) azArg = (const char * const *)&azDequote[1];
rc = pMod->xCreate((nDequote>1 ? nDequote-1 : 0), azArg, &pTok);
}
+23 -11
View File
@@ -341,7 +341,9 @@ static int fts3SqlStmt(
** created by merging the oldest :2 segments from absolute level :1. See
** function sqlite3Fts3Incrmerge() for details. */
/* 29 */ "SELECT 2 * total(1 + leaves_end_block - start_block) "
" FROM %Q.'%q_segdir' WHERE level = ? AND idx < ?",
" FROM (SELECT * FROM %Q.'%q_segdir' "
" WHERE level = ? ORDER BY idx ASC LIMIT ?"
" )",
/* SQL_DELETE_SEGDIR_ENTRY
** Delete the %_segdir entry on absolute level :1 with index :2. */
@@ -2853,6 +2855,19 @@ int sqlite3Fts3MsrIncrRestart(Fts3MultiSegReader *pCsr){
return SQLITE_OK;
}
static int fts3GrowSegReaderBuffer(Fts3MultiSegReader *pCsr, int nReq){
if( nReq>pCsr->nBuffer ){
char *aNew;
pCsr->nBuffer = nReq*2;
aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
if( !aNew ){
return SQLITE_NOMEM;
}
pCsr->aBuffer = aNew;
}
return SQLITE_OK;
}
int sqlite3Fts3SegReaderStep(
Fts3Table *p, /* Virtual table handle */
@@ -2987,15 +3002,9 @@ int sqlite3Fts3SegReaderStep(
}
nByte = sqlite3Fts3VarintLen(iDelta) + (isRequirePos?nList+1:0);
if( nDoclist+nByte>pCsr->nBuffer ){
char *aNew;
pCsr->nBuffer = (nDoclist+nByte)*2;
aNew = sqlite3_realloc(pCsr->aBuffer, pCsr->nBuffer);
if( !aNew ){
return SQLITE_NOMEM;
}
pCsr->aBuffer = aNew;
}
rc = fts3GrowSegReaderBuffer(pCsr, nByte+nDoclist);
if( rc ) return rc;
if( isFirst ){
char *a = &pCsr->aBuffer[nDoclist];
@@ -3020,6 +3029,9 @@ int sqlite3Fts3SegReaderStep(
fts3SegReaderSort(apSegment, nMerge, j, xCmp);
}
if( nDoclist>0 ){
rc = fts3GrowSegReaderBuffer(pCsr, nDoclist+FTS3_NODE_PADDING);
if( rc ) return rc;
memset(&pCsr->aBuffer[nDoclist], 0, FTS3_NODE_PADDING);
pCsr->aDoclist = pCsr->aBuffer;
pCsr->nDoclist = nDoclist;
rc = SQLITE_ROW;
@@ -4288,7 +4300,7 @@ static int fts3IncrmergeLoad(
int i;
int nHeight = (int)aRoot[0];
NodeWriter *pNode;
if( nHeight<1 || nHeight>FTS_MAX_APPENDABLE_HEIGHT ){
if( nHeight<1 || nHeight>=FTS_MAX_APPENDABLE_HEIGHT ){
sqlite3_reset(pSelect);
return FTS_CORRUPT_VTAB;
}
+2 -2
View File
@@ -93,7 +93,7 @@ static int runSql(sqlite3 *db, const char *zFormat, ...){
static void showSchema(sqlite3 *db, const char *zTab){
sqlite3_stmt *pStmt;
pStmt = prepare(db,
"SELECT sql FROM sqlite_master"
"SELECT sql FROM sqlite_schema"
" WHERE name LIKE '%q%%'"
" ORDER BY 1",
zTab);
@@ -831,7 +831,7 @@ int main(int argc, char **argv){
sqlite3_stmt *pStmt;
int cnt = 0;
pStmt = prepare(db, "SELECT b.sql"
" FROM sqlite_master a, sqlite_master b"
" FROM sqlite_schema a, sqlite_schema b"
" WHERE a.name GLOB '*_segdir'"
" AND b.name=substr(a.name,1,length(a.name)-7)"
" ORDER BY 1");
+2 -2
View File
@@ -2321,11 +2321,11 @@ static void fts5LeafSeek(
}
search_success:
pIter->iLeafOffset = iOff + nNew;
if( pIter->iLeafOffset>n || nNew<1 ){
if( (i64)iOff+nNew>n || nNew<1 ){
p->rc = FTS5_CORRUPT;
return;
}
pIter->iLeafOffset = iOff + nNew;
pIter->iTermLeafOffset = pIter->iLeafOffset;
pIter->iTermLeafPgno = pIter->iLeafPgno;
+215
View File
@@ -10108,6 +10108,221 @@ do_catchsql_test 68.1 {
INSERT INTO t1(t1) SELECT x FROM t2;
} {1 {database disk image is malformed}}
#-------------------------------------------------------------------------
reset_db
do_test 69.0 {
sqlite3 db {}
db deserialize [decode_hexdb {
.open --hexdb
| size 32768 pagesize 4096 filename crash-31c462b8b665d0.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 08 .....@ ........
| 32: 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 96: 00 00 00 00 0d 0f c7 00 07 0d 92 00 0f 8d 0f 36 ...............6
| 112: 0e cb 0e 6b 0e 0e 0d b6 0d 92 00 00 00 00 00 00 ...k............
| 3472: 00 00 22 08 06 17 11 11 01 31 74 61 62 6c 65 74 .........1tablet
| 3488: 32 74 32 08 43 52 45 41 54 45 20 54 41 42 4c 45 2t2.CREATE TABLE
| 3504: 20 74 32 28 78 29 56 07 06 17 1f 1f 01 7d 74 61 t2(x)V.......ta
| 3520: 62 6c 65 74 31 5f 63 6f 6e 66 69 67 74 31 5f 63 blet1_configt1_c
| 3536: 6f 6e 66 69 67 07 43 52 45 41 54 45 20 54 41 42 onfig.CREATE TAB
| 3552: 4c 45 20 27 74 31 5f 63 6f 6e 66 69 67 27 28 6b LE 't1_config'(k
| 3568: 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 PRIMARY KEY, v)
| 3584: 20 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5b 06 WITHOUT ROWID[.
| 3600: 07 17 21 21 01 81 01 74 61 62 6c 65 74 31 5f 64 ..!!...tablet1_d
| 3616: 6f 63 73 69 7a 65 74 31 5f 64 6f 63 73 69 7a 65 ocsizet1_docsize
| 3632: 06 43 52 45 41 54 45 20 54 41 42 4c 45 20 27 74 .CREATE TABLE 't
| 3648: 31 5f 64 6f 63 73 69 7a 65 27 28 69 64 20 49 4e 1_docsize'(id IN
| 3664: 54 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 TEGER PRIMARY KE
| 3680: 59 2c 20 73 7a 20 42 4c 4f 42 29 5e 05 07 17 21 Y, sz BLOB)^...!
| 3696: 21 01 81 07 74 61 62 6c 65 74 31 5f 63 6f 6e 74 !...tablet1_cont
| 3712: 65 6e 74 74 31 5f 63 6f 6e 74 65 6e 74 05 43 52 entt1_content.CR
| 3728: 45 41 54 45 20 54 41 42 4c 45 20 27 74 31 5f 63 EATE TABLE 't1_c
| 3744: 6f 6e 74 65 6e 74 27 28 69 64 20 49 4e 54 45 47 ontent'(id INTEG
| 3760: 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 ER PRIMARY KEY,
| 3776: 63 39 2c 20 63 31 2c 20 63 32 29 69 04 07 17 19 c9, c1, c2)i....
| 3792: 19 01 81 2d 74 61 62 6c 65 74 31 5f 69 64 78 74 ...-tablet1_idxt
| 3808: 31 5f 69 64 78 04 43 52 45 41 54 45 20 54 41 42 1_idx.CREATE TAB
| 3824: 4c 45 20 27 74 31 5f 69 64 78 27 28 73 65 67 69 LE 't1_idx'(segi
| 3840: 64 2c 20 74 65 72 6d 2c 20 70 67 6e 6f 2c 20 50 d, term, pgno, P
| 3856: 52 49 4d 41 52 59 20 4b 45 59 28 73 65 67 69 64 RIMARY KEY(segid
| 3872: 2c 20 74 65 72 6d 29 29 20 57 49 54 48 4f 55 54 , term)) WITHOUT
| 3888: 20 52 4f 57 49 44 55 03 07 17 1b 1b 01 81 01 74 ROWIDU........t
| 3904: 61 62 6c 65 74 31 5f 64 61 74 61 74 31 5f 64 61 ablet1_datat1_da
| 3920: 74 61 03 43 52 45 41 54 45 20 54 41 42 4c 45 20 ta.CREATE TABLE
| 3936: 27 74 31 5f 64 61 74 61 27 28 69 64 20 49 4e 54 't1_data'(id INT
| 3952: 45 47 45 52 20 50 52 49 4d 41 52 59 20 4b 45 59 EGER PRIMARY KEY
| 3968: 2c 20 62 6c 6f 63 6b 20 42 4c 4f 42 29 38 02 06 , block BLOB)8..
| 3984: 17 11 11 08 5f 74 61 62 6c 65 74 31 74 31 43 52 ...._tablet1t1CR
| 4000: 45 41 54 45 20 56 49 52 54 55 41 4c 20 54 41 42 EATE VIRTUAL TAB
| 4016: 4c 45 20 74 31 20 55 53 49 4e 47 20 66 74 73 35 LE t1 USING fts5
| 4032: 28 61 2c 62 2c 63 29 00 00 00 00 00 00 00 00 00 (a,b,c).........
| page 3 offset 8192
| 0: 0d 00 00 00 03 0c 94 00 0f e6 0f ef 0c 94 00 00 ................
| 3216: 00 00 00 00 86 4a 84 80 80 80 80 01 04 00 8d 18 .....J..........
| 3232: 00 00 03 2b 02 30 30 01 02 06 01 02 06 01 02 06 ...+.00.........
| 3248: 1f 02 03 01 02 03 01 02 03 01 08 32 30 31 36 30 ...........20160
| 3264: 36 30 39 01 02 07 01 02 07 01 02 07 01 01 34 01 609...........4.
| 3280: 02 05 01 02 05 01 02 05 01 01 35 01 02 04 01 02 ..........5.....
| 3296: 04 01 02 04 02 07 30 30 30 30 30 30 30 1c 02 04 ......0000000...
| 3312: 01 02 04 01 02 04 01 06 62 69 6e 61 72 79 03 06 ........binary..
| 3328: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3344: 02 02 03 06 00 02 02 03 06 01 02 02 03 06 01 02 ................
| 3360: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
| 3376: 03 06 01 02 02 03 06 01 02 02 01 08 63 6f 6d 70 ............comp
| 3392: 69 6c 65 72 01 02 02 01 02 02 01 02 02 01 06 64 iler...........d
| 3408: 62 73 74 61 74 07 02 03 01 02 03 01 02 03 02 04 bstat...........
| 3424: 65 62 75 67 04 02 02 01 02 02 01 02 02 01 06 65 ebug...........e
| 3440: 6e 61 62 6c 65 07 02 02 01 02 02 01 02 02 01 02 nable...........
| 3456: 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 ................
| 3472: 01 02 02 01 02 02 01 02 02 01 02 02 01 02 02 01 ................
| 3488: 01 02 01 02 02 01 02 02 01 02 02 01 02 02 01 02 ................
| 3504: 02 01 02 02 02 08 78 74 65 6e 73 69 6f 6e 1f 02 ......xtension..
| 3520: 04 01 02 04 01 02 04 01 04 66 74 73 34 1a 02 03 .........fts4...
| 3536: 01 02 03 01 02 03 04 01 35 0d 02 03 01 02 03 01 ........5.......
| 3552: 02 03 01 03 67 63 63 01 aa 03 01 02 03 01 02 03 ....gcc.........
| 3568: 02 06 65 6f 70 6f 6c 79 10 02 03 02 02 03 01 02 ..eopoly........
| 3584: 03 01 05 6a 73 6f 6e 31 13 02 03 01 02 03 01 02 ...json1........
| 3600: 03 01 04 6c 6f 61 64 1f 02 03 01 02 03 01 02 03 ...load.........
| 3616: 01 03 6d 61 78 1c 02 02 01 02 02 01 02 02 02 05 ..max...........
| 3632: 65 6d 6f 72 79 1c 02 03 01 02 03 01 02 03 04 04 emory...........
| 3648: 73 79 73 35 16 02 03 01 02 03 01 02 03 01 06 6e sys5...........n
| 3664: 6f 63 61 73 65 02 06 01 02 02 03 06 01 02 02 03 ocase...........
| 3680: 06 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 ................
| 3696: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3712: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3728: 02 01 04 6f 6d 69 74 1f 02 02 01 02 02 01 02 01 ...omit.........
| 3744: ff ff ff ff ff ff ff ff f0 00 00 00 00 00 01 02 ................
| 3760: 58 81 96 4d 01 06 01 02 02 03 06 01 02 02 03 06 X..M............
| 3776: 01 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 ................
| 3792: 02 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 ................
| 3808: 02 03 06 01 02 02 03 06 01 02 02 03 06 01 02 02 ................
| 3824: 01 0a 74 68 72 65 61 64 73 61 66 65 22 02 02 01 ..threadsafe....
| 3840: 02 02 01 02 02 01 04 76 74 61 62 07 02 04 01 02 .......vtab.....
| 3856: 04 01 02 04 01 01 78 01 06 01 01 02 01 06 01 01 ......x.........
| 3872: 02 01 06 01 1e 02 01 06 01 01 02 01 06 01 01 02 ................
| 3888: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
| 3904: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
| 3920: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
| 3936: 00 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
| 3952: 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 ................
| 3968: 01 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 ................
| 3984: 06 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 ................
| 4000: 01 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 ................
| 4016: 01 02 01 06 01 01 02 01 06 01 01 02 01 06 01 01 ................
| 4032: 02 01 06 01 01 02 01 06 01 01 02 04 15 13 0c 0c ................
| 4048: 12 44 13 11 0f 47 13 0f 0b 0e 11 10 0f 0e 10 0f .D...G..........
| 4064: 44 0f 10 40 15 0f 07 01 03 00 14 24 5a 24 24 0f D..@.......$Z$$.
| 4080: 0a 03 00 24 00 00 00 00 01 01 01 00 01 01 01 01 ...$............
| page 4 offset 12288
| 0: 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 00 00 00 00 00 00 05 04 09 0c 01 02 ................
| page 5 offset 16384
| 0: 0d 00 00 00 24 0c 0a 00 0f d8 0f af 0f 86 0f 74 ....$..........t
| 16: 0f 61 0f 4e 0f 2f 0f 0f 0e ef 0e d7 0e be 0e a5 .a.N./..........
| 32: 0e 8d 0e 74 0e 5b 0e 40 0e 24 0e 08 0d ef 0d d5 ...t.[.@.$......
| 48: 0d bb 0d a0 0d 84 0d 68 0d 4f 0d 00 00 00 00 00 .......h.O......
| 3072: 00 00 00 00 00 00 00 00 00 00 18 24 05 00 25 0f ...........$..%.
| 3088: 19 54 48 52 45 41 44 53 41 46 45 3d 30 58 42 49 .THREADSAFE=0XBI
| 3104: 4e 41 52 59 18 23 05 00 25 0f 19 54 48 52 45 41 NARY.#..%..THREA
| 3120: 44 53 41 46 45 3d 30 58 4e 4f 43 41 53 45 17 22 DSAFE=0XNOCASE..
| 3136: 05 00 25 0f 17 54 48 52 45 41 44 53 41 46 45 3d ..%..THREADSAFE=
| 3152: 30 58 52 54 52 49 4d 1f 21 05 00 33 0f 19 4f 4d 0XRTRIM.!..3..OM
| 3168: 49 54 20 4c 4f 41 44 20 45 58 54 45 4e 53 49 4f IT LOAD EXTENSIO
| 3184: 4e 58 42 49 4e 41 52 59 1f 20 05 00 33 d3 19 4f NXBINARY. ..3..O
| 3200: 4d 49 54 28 2c 4f 41 44 b2 04 55 85 44 54 e5 34 MIT(,OAD..U.DT.4
| 3216: 94 f4 e5 84 e4 f4 34 15 34 51 e1 f0 50 03 30 f1 ......4.4Q..P.0.
| 3232: 74 f4 d4 95 42 04 c4 f4 14 42 04 55 85 44 54 e5 t...B....B.U.DT.
| 3248: 34 94 f4 e5 85 25 45 24 94 d1 f1 e0 50 03 30 f1 4....%E$....P.0.
| 3264: 94 d4 15 82 04 d4 54 d4 f5 25 93 d3 53 03 03 03 ......T..%..S...
| 3280: 03 03 03 05 84 24 94 e4 15 25 91 f1 d0 50 03 30 .....$...%...P.0
| 3296: f1 94 d4 15 82 04 d4 54 d4 f5 25 93 d3 53 03 03 .......T..%..S..
| 3312: 03 03 03 03 05 84 e4 f4 34 15 34 51 e1 c0 50 03 ........4.4Q..P.
| 3328: 30 f1 74 d4 15 82 04 d4 54 d4 f5 25 93 d3 53 03 0.t.....T..%..S.
| 3344: 03 03 03 03 03 05 85 25 45 24 94 d1 81 b0 50 02 .......%E$....P.
| 3360: 50 f1 94 54 e4 14 24 c4 52 05 25 45 24 54 55 84 P..T..$.R.%E$TU.
| 3376: 24 94 e4 15 25 91 81 a0 50 02 50 f1 94 54 e4 14 $...%...P.P..T..
| 3392: 24 c4 52 05 25 45 24 54 55 84 e4 f4 34 15 34 51 $.R.%E$TU...4.4Q
| 3408: 71 90 50 02 50 f1 74 54 e4 14 24 c4 52 05 25 45 q.P.P.tT..$.R.%E
| 3424: 24 54 55 85 25 45 24 94 d1 a1 80 50 02 90 f1 94 $TU.%E$....P....
| 3440: 54 e4 14 24 c4 52 04 d4 54 d5 35 95 33 55 84 24 T..$.R..T.5.3U.$
| 3456: 94 e4 15 25 91 a1 70 50 02 90 f1 94 54 e4 14 24 ...%..pP....T..$
| 3472: c4 52 04 d4 54 d5 35 95 33 55 84 e4 f4 34 15 34 .R..T.5.3U...4.4
| 3488: 51 91 60 50 02 90 f1 74 54 e4 14 24 c4 52 04 d4 Q.`P...tT..$.R..
| 3504: 54 d5 35 95 33 55 85 25 45 24 94 d1 81 50 50 02 T.5.3U.%E$...PP.
| 3520: 50 f1 94 54 e4 14 24 c4 52 04 a5 34 f4 e3 15 84 P..T..$.R..4....
| 3536: 24 94 e4 15 25 91 81 40 50 02 50 f1 94 54 e4 14 $...%..@P.P..T..
| 3552: 24 c4 52 04 a5 34 f4 e3 15 84 e4 f4 34 15 34 51 $.R..4......4.4Q
| 3568: 71 30 50 02 4f f1 74 54 e4 14 24 c4 52 04 a5 34 q0P.O.tT..$.R..4
| 3584: f4 e3 15 85 25 45 24 94 d1 a1 20 50 02 90 f1 94 ....%E$... P....
| 3600: 54 e4 14 24 c4 52 04 74 54 f5 04 f4 c5 95 84 24 T..$.R.tT......$
| 3616: 94 e4 15 25 91 a1 10 50 02 90 f1 94 54 e4 14 24 ...%...P....T..$
| 3632: c4 52 04 74 54 f5 04 f4 c5 95 84 e4 f4 34 15 34 .R.tT........4.4
| 3648: 51 91 00 50 02 90 f1 74 54 e4 14 24 c4 51 f4 74 Q..P...tT..$.Q.t
| 3664: 54 f5 04 f4 c5 95 85 25 45 24 94 d1 70 f0 50 02 T......%E$..p.P.
| 3680: 30 f1 94 54 e4 14 24 c5 20 46 54 53 35 58 42 49 0..T..$. FTS5XBI
| 3696: 4e 41 52 59 17 0e 05 00 23 0f 19 45 4e 41 42 4c NARY....#..ENABL
| 3712: 45 20 46 54 53 35 58 4f 4f 43 41 53 45 16 0d 05 E FTS5XOOCASE...
| 3728: 00 23 0f 17 45 4e 41 42 4c 45 20 46 54 53 35 58 .#..ENABLE FTS5X
| 3744: 52 54 52 49 4d 17 0c 05 00 23 0f 19 45 4e 41 42 RTRIM....#..ENAB
| 3760: 4c 45 20 46 54 53 34 58 42 49 4e 41 52 59 97 0b LE FTS4XBINARY..
| 3776: 05 00 23 0f 19 45 4e 41 42 4c 45 20 46 54 53 34 ..#..ENABLE FTS4
| 3792: 58 4e 4f 43 41 53 45 16 0a 05 00 23 0f 17 45 4e XNOCASE....#..EN
| 3808: 41 42 4c 45 20 46 54 53 34 58 52 54 52 49 4d 1e ABLE FTS4XRTRIM.
| 3824: 09 05 00 3e 5f 19 45 4e 41 42 4c 45 20 44 42 53 ...>_.ENABLE DBS
| 3840: 44 41 54 20 56 54 41 42 58 42 49 4e 41 52 59 1e DAT VTABXBINARY.
| 3856: 08 05 00 31 0f 19 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3872: 54 41 54 20 56 54 41 42 58 4e 4f 43 4d e3 45 1d TAT VTABXNOCM.E.
| 3888: 07 05 00 31 0f 17 45 4e 41 42 4c 45 20 44 42 53 ...1..ENABLE DBS
| 3904: 54 41 54 20 56 54 41 42 58 52 54 52 49 4d 11 06 TAT VTABXRTRIM..
| 3920: 05 00 17 0f 19 44 45 42 55 47 58 42 49 4e 41 52 .....DEBUGXBINAR
| 3936: 59 11 05 05 00 17 0f 19 44 45 42 55 47 58 4e 4f Y.......DEBUGXNO
| 3952: 43 41 53 45 10 02 02 50 08 5f 17 44 45 42 55 47 CASE...P._.DEBUG
| 3968: 58 52 54 52 49 4d 27 03 05 00 44 0f 19 43 4f 4d XRTRIM'...D..COM
| 3984: 50 49 4c 45 52 3d 67 63 63 2d 35 2e 34 2e 30 20 PILER=gcc-5.4.0
| 4000: 32 30 31 36 30 36 30 39 58 42 49 4e 41 52 59 27 20160609XBINARY'
| 4016: 02 05 00 43 0f 19 43 4f 4d 50 49 4c 45 52 3d 67 ...C..COMPILER=g
| 4032: 63 63 2d 35 2e 34 2e 30 20 32 30 31 36 30 36 30 cc-5.4.0 2016060
| 4048: 39 58 4e 4f 43 41 53 45 26 01 05 00 43 c9 17 43 9XNOCASE&...C..C
| 4064: 4f 4d 50 49 4c 47 02 3d 67 63 63 2d 35 2e 34 2e OMPILG.=gcc-5.4.
| 4080: 30 20 32 30 31 36 30 36 30 39 58 52 54 52 49 4d 0 20160609XRTRIM
| page 6 offset 20480
| 0: 0d 00 00 00 24 0e e0 00 0f f8 0f f0 0f e8 0f e0 ....$...........
| 16: 0f d8 0f d0 0f c8 0f c0 0f b8 0f b0 0f a8 0f a0 ................
| 32: 0f 98 0f 90 0f 88 0f 80 0f 78 0f 70 0f 68 0f 60 .........x.p.h.`
| 48: 0f 58 0f 50 0f 48 0f 40 0f 38 00 00 00 00 00 00 .X.P.H.@.8......
| 3808: 06 24 03 00 12 02 01 01 06 23 03 00 12 02 01 01 .$.......#......
| 3824: 06 22 03 00 12 02 01 01 06 21 03 00 12 03 01 01 .........!......
| 3840: 06 20 03 00 12 03 01 01 06 1f 03 00 12 03 01 01 . ..............
| 3856: 06 1e 03 00 12 03 01 01 06 1d 03 00 12 03 01 01 ................
| 3872: 06 1c 03 00 12 03 01 01 06 1b 03 00 12 02 01 01 ................
| 3888: 06 1a 03 00 12 02 01 01 06 19 03 00 12 02 01 01 ................
| 3904: 06 18 03 00 12 02 01 01 06 17 03 00 12 02 01 01 ................
| 3920: 06 16 03 00 12 02 01 01 06 15 03 00 12 02 01 01 ................
| 3936: 06 14 03 00 12 02 01 01 06 13 03 00 12 02 01 01 ................
| 3952: 06 12 03 00 12 02 01 01 06 11 03 00 12 02 01 01 ................
| 3968: 06 10 03 00 12 02 01 01 06 1f 03 00 12 02 01 01 ................
| 3984: 06 0e 03 00 12 02 01 01 06 0d 03 00 12 02 01 01 ................
| 4000: 06 0c 03 00 12 02 01 01 06 0b 03 00 12 02 01 01 ................
| 4016: 06 0a 03 00 12 02 01 01 06 09 03 00 12 03 01 01 ................
| 4032: 06 08 03 00 12 03 01 01 06 07 03 00 12 03 01 01 ................
| 4048: 06 06 03 00 12 01 01 01 06 05 03 00 12 01 01 01 ................
| 4064: 06 04 03 00 12 01 01 01 06 03 03 00 12 06 01 01 ................
| 4080: 06 02 03 00 12 06 01 01 06 01 03 00 12 06 01 01 ................
| page 7 offset 24576
| 0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00 ................
| 4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04 ........version.
| page 8 offset 28672
| 0: 0d 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
| 4048: 00 00 00 00 00 00 11 03 02 2b 69 6e 74 65 67 72 .........+integr
| 4064: 69 74 79 2d 63 68 65 63 6b 09 00 00 00 00 00 00 ity-check.......
| end crash-31c462b8b665d0.db
}]} {}
do_catchsql_test 69.2 {
SELECT * FROM t1 WHERE a MATCH 'fx*'
} {1 {database disk image is malformed}}
sqlite3_fts5_may_be_corrupt 0
finish_test
-1
View File
@@ -24,4 +24,3 @@ int sqlite3IcuInit(sqlite3 *db);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
-2
View File
@@ -654,5 +654,3 @@ void test_data_3(
testFree(zName);
}
}
-2
View File
@@ -322,5 +322,3 @@ void do_writer_crash_test(const char *zPattern, int *pRc){
}
}
-3
View File
@@ -138,6 +138,3 @@ void test_data_4(
testFree(zName);
}
}
-4
View File
@@ -69,7 +69,3 @@ int do_bt(int nArg, char **azArg){
sqlite4_buffer_clear(&buf.output);
return 0;
}
+1 -1
View File
@@ -553,7 +553,7 @@ static int sql_begin(TestDb *pTestDb, int iLevel){
/* If there are no transactions at all open, open a read transaction. */
if( pDb->nOpenTrans==0 ){
int rc = sqlite3_exec(pDb->db,
"BEGIN; SELECT * FROM sqlite_master LIMIT 1;" , 0, 0, 0
"BEGIN; SELECT * FROM sqlite_schema LIMIT 1;" , 0, 0, 0
);
if( rc!=0 ) return rc;
pDb->nOpenTrans = 1;
-1
View File
@@ -367,4 +367,3 @@ int test_mdb_scan(
}
#endif /* HAVE_MDB */
-2
View File
@@ -978,5 +978,3 @@ static int bgc_detach(BtDb *pDb){
/*
** End of background checkpointer.
*************************************************************************/
+8 -1
View File
@@ -228,6 +228,10 @@ static int lsmPosixOsRemap(
}
p->pMap = mmap(0, iSz, PROT_READ|PROT_WRITE, MAP_SHARED, p->fd, 0);
if( p->pMap==MAP_FAILED ){
p->pMap = 0;
return LSM_IOERR_BKPT;
}
p->nMap = iSz;
}
@@ -413,7 +417,10 @@ static int lsmPosixOsShmMap(lsm_file *pFile, int iChunk, int sz, void **ppShm){
p->apShm[iChunk] = mmap(0, LSM_SHM_CHUNK_SIZE,
PROT_READ|PROT_WRITE, MAP_SHARED, p->shmfd, iChunk*LSM_SHM_CHUNK_SIZE
);
if( p->apShm[iChunk]==0 ) return LSM_IOERR_BKPT;
if( p->apShm[iChunk]==MAP_FAILED ){
p->apShm[iChunk] = 0;
return LSM_IOERR_BKPT;
}
}
*ppShm = p->apShm[iChunk];
+1 -1
View File
@@ -439,7 +439,7 @@ static int apndOpen(
p = (ApndFile*)pFile;
memset(p, 0, sizeof(*p));
pSubFile = ORIGFILE(pFile);
p->base.pMethods = &apnd_io_methods;
pFile->pMethods = &apnd_io_methods;
rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
if( rc ) goto apnd_open_done;
rc = pSubFile->pMethods->xFileSize(pSubFile, &sz);
+6 -6
View File
@@ -21,7 +21,7 @@
** name TEXT, -- Name of table or index for this btree.
** tbl_name TEXT, -- Associated table
** rootpage INT, -- The root page of the btree
** sql TEXT, -- SQL for this btree - from sqlite_master
** sql TEXT, -- SQL for this btree - from sqlite_schema
** hasRowid BOOLEAN, -- True if the btree has a rowid
** nEntry INT, -- Estimated number of entries
** nPage INT, -- Estimated number of pages
@@ -30,9 +30,9 @@
** zSchema TEXT HIDDEN -- The schema to which this btree belongs
** );
**
** The first 5 fields are taken directly from the sqlite_master table.
** The first 5 fields are taken directly from the sqlite_schema table.
** Considering only the first 5 fields, the only difference between
** this virtual table and the sqlite_master table is that this virtual
** this virtual table and the sqlite_schema table is that this virtual
** table omits all entries that have a 0 or NULL rowid - in other words
** it omits triggers and views.
**
@@ -88,7 +88,7 @@ typedef struct BinfoCursor BinfoCursor;
/* A cursor for the sqlite_btreeinfo table */
struct BinfoCursor {
sqlite3_vtab_cursor base; /* Base class. Must be first */
sqlite3_stmt *pStmt; /* Query against sqlite_master */
sqlite3_stmt *pStmt; /* Query against sqlite_schema */
int rc; /* Result of previous sqlite_step() call */
int hasRowid; /* hasRowid value. Negative if unknown. */
sqlite3_int64 nEntry; /* nEntry value */
@@ -242,10 +242,10 @@ static int binfoFilter(
pCsr->zSchema = sqlite3_mprintf("main");
}
zSql = sqlite3_mprintf(
"SELECT 0, 'table','sqlite_master','sqlite_master',1,NULL "
"SELECT 0, 'table','sqlite_schema','sqlite_schema',1,NULL "
"UNION ALL "
"SELECT rowid, type, name, tbl_name, rootpage, sql"
" FROM \"%w\".sqlite_master WHERE rootpage>=1",
" FROM \"%w\".sqlite_schema WHERE rootpage>=1",
pCsr->zSchema);
sqlite3_finalize(pCsr->pStmt);
pCsr->pStmt = 0;
+2 -2
View File
@@ -634,7 +634,7 @@ static int cksmOpen(
p = (CksmFile*)pFile;
memset(p, 0, sizeof(*p));
pSubFile = ORIGFILE(pFile);
p->base.pMethods = &cksm_io_methods;
pFile->pMethods = &cksm_io_methods;
rc = pSubVfs->xOpen(pSubVfs, zName, pSubFile, flags, pOutFlags);
if( rc ) goto cksm_open_done;
if( flags & SQLITE_OPEN_WAL ){
@@ -743,7 +743,7 @@ static int cksmRegisterFunc(
static int cksmRegisterVfs(void){
int rc = SQLITE_OK;
sqlite3_vfs *pOrig;
if( sqlite3_vfs_find("cksum")!=0 ) return SQLITE_OK;
if( sqlite3_vfs_find("cksmvfs")!=0 ) return SQLITE_OK;
pOrig = sqlite3_vfs_find(0);
cksm_vfs.iVersion = pOrig->iVersion;
cksm_vfs.pAppData = pOrig;
+2 -2
View File
@@ -226,7 +226,7 @@ static int completionNext(sqlite3_vtab_cursor *cur){
const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
zSql = sqlite3_mprintf(
"%z%s"
"SELECT name FROM \"%w\".sqlite_master",
"SELECT name FROM \"%w\".sqlite_schema",
zSql, zSep, zDb
);
if( zSql==0 ) return SQLITE_NOMEM;
@@ -250,7 +250,7 @@ static int completionNext(sqlite3_vtab_cursor *cur){
const char *zDb = (const char*)sqlite3_column_text(pS2, 1);
zSql = sqlite3_mprintf(
"%z%s"
"SELECT pti.name FROM \"%w\".sqlite_master AS sm"
"SELECT pti.name FROM \"%w\".sqlite_schema AS sm"
" JOIN pragma_table_info(sm.name,%Q) AS pti"
" WHERE sm.type='table'",
zSql, zSep, zDb, zDb
+7 -7
View File
@@ -395,7 +395,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
if( strcmp(zTable, "sqlite_sequence")==0 ){
p->xCallback("DELETE FROM sqlite_sequence;\n", p->pArg);
}else if( sqlite3_strglob("sqlite_stat?", zTable)==0 ){
p->xCallback("ANALYZE sqlite_master;\n", p->pArg);
p->xCallback("ANALYZE sqlite_schema;\n", p->pArg);
}else if( strncmp(zTable, "sqlite_", 7)==0 ){
return 0;
}else if( strncmp(zSql, "CREATE VIRTUAL TABLE", 20)==0 ){
@@ -404,7 +404,7 @@ static int dump_callback(void *pArg, int nArg, char **azArg, char **azCol){
p->writableSchema = 1;
}
output_formatted(p,
"INSERT INTO sqlite_master(type,name,tbl_name,rootpage,sql)"
"INSERT INTO sqlite_schema(type,name,tbl_name,rootpage,sql)"
"VALUES('table','%q','%q',0,'%q');",
zTable, zTable, zSql);
return 0;
@@ -646,27 +646,27 @@ int sqlite3_db_dump(
xCallback("PRAGMA foreign_keys=OFF;\nBEGIN TRANSACTION;\n", pArg);
if( zTable==0 ){
run_schema_dump_query(&x,
"SELECT name, type, sql FROM \"%w\".sqlite_master "
"SELECT name, type, sql FROM \"%w\".sqlite_schema "
"WHERE sql NOT NULL AND type=='table' AND name!='sqlite_sequence'",
zSchema
);
run_schema_dump_query(&x,
"SELECT name, type, sql FROM \"%w\".sqlite_master "
"SELECT name, type, sql FROM \"%w\".sqlite_schema "
"WHERE name=='sqlite_sequence'", zSchema
);
output_sql_from_query(&x,
"SELECT sql FROM sqlite_master "
"SELECT sql FROM sqlite_schema "
"WHERE sql NOT NULL AND type IN ('index','trigger','view')", 0
);
}else{
run_schema_dump_query(&x,
"SELECT name, type, sql FROM \"%w\".sqlite_master "
"SELECT name, type, sql FROM \"%w\".sqlite_schema "
"WHERE tbl_name=%Q COLLATE nocase AND type=='table'"
" AND sql NOT NULL",
zSchema, zTable
);
output_sql_from_query(&x,
"SELECT sql FROM \"%w\".sqlite_master "
"SELECT sql FROM \"%w\".sqlite_schema "
"WHERE sql NOT NULL"
" AND type IN ('index','trigger','view')"
" AND tbl_name=%Q COLLATE nocase",
+634
View File
@@ -0,0 +1,634 @@
/*
** 2020-06-22
**
** 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.
**
******************************************************************************
**
** Routines to implement arbitrary-precision decimal math.
**
** The focus here is on simplicity and correctness, not performance.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(X) (void)(X)
#endif
/* A decimal object */
typedef struct Decimal Decimal;
struct Decimal {
char sign; /* 0 for positive, 1 for negative */
char oom; /* True if an OOM is encountered */
char isNull; /* True if holds a NULL rather than a number */
char isInit; /* True upon initialization */
int nDigit; /* Total number of digits */
int nFrac; /* Number of digits to the right of the decimal point */
signed char *a; /* Array of digits. Most significant first. */
};
/*
** Release memory held by a Decimal, but do not free the object itself.
*/
static void decimal_clear(Decimal *p){
sqlite3_free(p->a);
}
/*
** Destroy a Decimal object
*/
static void decimal_free(Decimal *p){
if( p ){
decimal_clear(p);
sqlite3_free(p);
}
}
/*
** Allocate a new Decimal object. Initialize it to the number given
** by the input string.
*/
static Decimal *decimal_new(
sqlite3_context *pCtx,
sqlite3_value *pIn,
int nAlt,
const unsigned char *zAlt
){
Decimal *p;
int n, i;
const unsigned char *zIn;
int iExp = 0;
p = sqlite3_malloc( sizeof(*p) );
if( p==0 ) goto new_no_mem;
p->sign = 0;
p->oom = 0;
p->isInit = 1;
p->isNull = 0;
p->nDigit = 0;
p->nFrac = 0;
if( zAlt ){
n = nAlt,
zIn = zAlt;
}else{
if( sqlite3_value_type(pIn)==SQLITE_NULL ){
p->a = 0;
p->isNull = 1;
return p;
}
n = sqlite3_value_bytes(pIn);
zIn = sqlite3_value_text(pIn);
}
p->a = sqlite3_malloc64( n+1 );
if( p->a==0 ) goto new_no_mem;
for(i=0; isspace(zIn[i]); i++){}
if( zIn[i]=='-' ){
p->sign = 1;
i++;
}else if( zIn[i]=='+' ){
i++;
}
while( i<n && zIn[i]=='0' ) i++;
while( i<n ){
char c = zIn[i];
if( c>='0' && c<='9' ){
p->a[p->nDigit++] = c - '0';
}else if( c=='.' ){
p->nFrac = p->nDigit + 1;
}else if( c=='e' || c=='E' ){
int j = i+1;
int neg = 0;
if( j>=n ) break;
if( zIn[j]=='-' ){
neg = 1;
j++;
}else if( zIn[j]=='+' ){
j++;
}
while( j<n && iExp<1000000 ){
if( zIn[j]>='0' && zIn[j]<='9' ){
iExp = iExp*10 + zIn[j] - '0';
}
j++;
}
if( neg ) iExp = -iExp;
break;
}
i++;
}
if( p->nFrac ){
p->nFrac = p->nDigit - (p->nFrac - 1);
}
if( iExp>0 ){
if( p->nFrac>0 ){
if( iExp<=p->nFrac ){
p->nFrac -= iExp;
iExp = 0;
}else{
iExp -= p->nFrac;
p->nFrac = 0;
}
}
if( iExp>0 ){
p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
if( p->a==0 ) goto new_no_mem;
memset(p->a+p->nDigit, 0, iExp);
p->nDigit += iExp;
}
}else if( iExp<0 ){
int nExtra;
iExp = -iExp;
nExtra = p->nDigit - p->nFrac - 1;
if( nExtra ){
if( nExtra>=iExp ){
p->nFrac += iExp;
iExp = 0;
}else{
iExp -= nExtra;
p->nFrac = p->nDigit - 1;
}
}
if( iExp>0 ){
p->a = sqlite3_realloc64(p->a, p->nDigit + iExp + 1 );
if( p->a==0 ) goto new_no_mem;
memmove(p->a+iExp, p->a, p->nDigit);
memset(p->a, 0, iExp);
p->nDigit += iExp;
p->nFrac += iExp;
}
}
return p;
new_no_mem:
if( pCtx ) sqlite3_result_error_nomem(pCtx);
sqlite3_free(p);
return 0;
}
/*
** Make the given Decimal the result.
*/
static void decimal_result(sqlite3_context *pCtx, Decimal *p){
char *z;
int i, j;
int n;
if( p==0 || p->oom ){
sqlite3_result_error_nomem(pCtx);
return;
}
if( p->isNull ){
sqlite3_result_null(pCtx);
return;
}
z = sqlite3_malloc( p->nDigit+4 );
if( z==0 ){
sqlite3_result_error_nomem(pCtx);
return;
}
i = 0;
if( p->nDigit==0 || (p->nDigit==1 && p->a[0]==0) ){
p->sign = 0;
}
if( p->sign ){
z[0] = '-';
i = 1;
}
n = p->nDigit - p->nFrac;
if( n<=0 ){
z[i++] = '0';
}
j = 0;
while( n>1 && p->a[j]==0 ){
j++;
n--;
}
while( n>0 ){
z[i++] = p->a[j] + '0';
j++;
n--;
}
if( p->nFrac ){
z[i++] = '.';
do{
z[i++] = p->a[j] + '0';
j++;
}while( j<p->nDigit );
}
z[i] = 0;
sqlite3_result_text(pCtx, z, i, sqlite3_free);
}
/*
** SQL Function: decimal(X)
**
** Convert input X into decimal and then back into text
*/
static void decimalFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *p = decimal_new(context, argv[0], 0, 0);
UNUSED_PARAMETER(argc);
decimal_result(context, p);
decimal_free(p);
}
/*
** Compare to Decimal objects. Return negative, 0, or positive if the
** first object is less than, equal to, or greater than the second.
**
** Preconditions for this routine:
**
** pA!=0
** pA->isNull==0
** pB!=0
** pB->isNull==0
*/
static int decimal_cmp(const Decimal *pA, const Decimal *pB){
int nASig, nBSig, rc, n;
if( pA->sign!=pB->sign ){
return pA->sign ? -1 : +1;
}
if( pA->sign ){
const Decimal *pTemp = pA;
pA = pB;
pB = pTemp;
}
nASig = pA->nDigit - pA->nFrac;
nBSig = pB->nDigit - pB->nFrac;
if( nASig!=nBSig ){
return nASig - nBSig;
}
n = pA->nDigit;
if( n>pB->nDigit ) n = pB->nDigit;
rc = memcmp(pA->a, pB->a, n);
if( rc==0 ){
rc = pA->nDigit - pB->nDigit;
}
return rc;
}
/*
** SQL Function: decimal_cmp(X, Y)
**
** Return negative, zero, or positive if X is less then, equal to, or
** greater than Y.
*/
static void decimalCmpFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = 0, *pB = 0;
int rc;
UNUSED_PARAMETER(argc);
pA = decimal_new(context, argv[0], 0, 0);
if( pA==0 || pA->isNull ) goto cmp_done;
pB = decimal_new(context, argv[1], 0, 0);
if( pB==0 || pB->isNull ) goto cmp_done;
rc = decimal_cmp(pA, pB);
if( rc<0 ) rc = -1;
else if( rc>0 ) rc = +1;
sqlite3_result_int(context, rc);
cmp_done:
decimal_free(pA);
decimal_free(pB);
}
/*
** Expand the Decimal so that it has a least nDigit digits and nFrac
** digits to the right of the decimal point.
*/
static void decimal_expand(Decimal *p, int nDigit, int nFrac){
int nAddSig;
int nAddFrac;
if( p==0 ) return;
nAddFrac = nFrac - p->nFrac;
nAddSig = (nDigit - p->nDigit) - nAddFrac;
if( nAddFrac==0 && nAddSig==0 ) return;
p->a = sqlite3_realloc64(p->a, nDigit+1);
if( p->a==0 ){
p->oom = 1;
return;
}
if( nAddSig ){
memmove(p->a+nAddSig, p->a, p->nDigit);
memset(p->a, 0, nAddSig);
p->nDigit += nAddSig;
}
if( nAddFrac ){
memset(p->a+p->nDigit, 0, nAddFrac);
p->nDigit += nAddFrac;
p->nFrac += nAddFrac;
}
}
/*
** Add the value pB into pA.
**
** Both pA and pB might become denormalized by this routine.
*/
static void decimal_add(Decimal *pA, Decimal *pB){
int nSig, nFrac, nDigit;
int i, rc;
if( pA==0 ){
return;
}
if( pA->oom || pB==0 || pB->oom ){
pA->oom = 1;
return;
}
if( pA->isNull || pB->isNull ){
pA->isNull = 1;
return;
}
nSig = pA->nDigit - pA->nFrac;
if( nSig && pA->a[0]==0 ) nSig--;
if( nSig<pB->nDigit-pB->nFrac ){
nSig = pB->nDigit - pB->nFrac;
}
nFrac = pA->nFrac;
if( nFrac<pB->nFrac ) nFrac = pB->nFrac;
nDigit = nSig + nFrac + 1;
decimal_expand(pA, nDigit, nFrac);
decimal_expand(pB, nDigit, nFrac);
if( pA->oom || pB->oom ){
pA->oom = 1;
}else{
if( pA->sign==pB->sign ){
int carry = 0;
for(i=nDigit-1; i>=0; i--){
int x = pA->a[i] + pB->a[i] + carry;
if( x>=10 ){
carry = 1;
pA->a[i] = x - 10;
}else{
carry = 0;
pA->a[i] = x;
}
}
}else{
signed char *aA, *aB;
int borrow = 0;
rc = memcmp(pA->a, pB->a, nDigit);
if( rc<0 ){
aA = pB->a;
aB = pA->a;
pA->sign = !pA->sign;
}else{
aA = pA->a;
aB = pB->a;
}
for(i=nDigit-1; i>=0; i--){
int x = aA[i] - aB[i] - borrow;
if( x<0 ){
pA->a[i] = x+10;
borrow = 1;
}else{
pA->a[i] = x;
borrow = 0;
}
}
}
}
}
/*
** Compare text in decimal order.
*/
static int decimalCollFunc(
void *notUsed,
int nKey1, const void *pKey1,
int nKey2, const void *pKey2
){
const unsigned char *zA = (const unsigned char*)pKey1;
const unsigned char *zB = (const unsigned char*)pKey2;
Decimal *pA = decimal_new(0, 0, nKey1, zA);
Decimal *pB = decimal_new(0, 0, nKey2, zB);
int rc;
UNUSED_PARAMETER(notUsed);
if( pA==0 || pB==0 ){
rc = 0;
}else{
rc = decimal_cmp(pA, pB);
}
decimal_free(pA);
decimal_free(pB);
return rc;
}
/*
** SQL Function: decimal_add(X, Y)
** decimal_sub(X, Y)
**
** Return the sum or difference of X and Y.
*/
static void decimalAddFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
decimal_add(pA, pB);
decimal_result(context, pA);
decimal_free(pA);
decimal_free(pB);
}
static void decimalSubFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
UNUSED_PARAMETER(argc);
if( pB==0 ) return;
pB->sign = !pB->sign;
decimal_add(pA, pB);
decimal_result(context, pA);
decimal_free(pA);
decimal_free(pB);
}
/* Aggregate funcion: decimal_sum(X)
**
** Works like sum() except that it uses decimal arithmetic for unlimited
** precision.
*/
static void decimalSumStep(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *p;
Decimal *pArg;
UNUSED_PARAMETER(argc);
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p==0 ) return;
if( !p->isInit ){
p->isInit = 1;
p->a = sqlite3_malloc(2);
if( p->a==0 ){
p->oom = 1;
}else{
p->a[0] = 0;
}
p->nDigit = 1;
p->nFrac = 0;
}
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pArg = decimal_new(context, argv[0], 0, 0);
decimal_add(p, pArg);
decimal_free(pArg);
}
static void decimalSumInverse(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *p;
Decimal *pArg;
UNUSED_PARAMETER(argc);
p = sqlite3_aggregate_context(context, sizeof(*p));
if( p==0 ) return;
if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
pArg = decimal_new(context, argv[0], 0, 0);
if( pArg ) pArg->sign = !pArg->sign;
decimal_add(p, pArg);
decimal_free(pArg);
}
static void decimalSumValue(sqlite3_context *context){
Decimal *p = sqlite3_aggregate_context(context, 0);
if( p==0 ) return;
decimal_result(context, p);
}
static void decimalSumFinalize(sqlite3_context *context){
Decimal *p = sqlite3_aggregate_context(context, 0);
if( p==0 ) return;
decimal_result(context, p);
decimal_clear(p);
}
/*
** SQL Function: decimal_mul(X, Y)
**
** Return the product of X and Y.
**
** All significant digits after the decimal point are retained.
** Trailing zeros after the decimal point are omitted as long as
** the number of digits after the decimal point is no less than
** either the number of digits in either input.
*/
static void decimalMulFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
Decimal *pA = decimal_new(context, argv[0], 0, 0);
Decimal *pB = decimal_new(context, argv[1], 0, 0);
signed char *acc = 0;
int i, j, k;
int minFrac;
UNUSED_PARAMETER(argc);
if( pA==0 || pA->oom || pA->isNull
|| pB==0 || pB->oom || pB->isNull
){
goto mul_end;
}
acc = sqlite3_malloc64( pA->nDigit + pB->nDigit + 2 );
if( acc==0 ){
sqlite3_result_error_nomem(context);
goto mul_end;
}
memset(acc, 0, pA->nDigit + pB->nDigit + 2);
minFrac = pA->nFrac;
if( pB->nFrac<minFrac ) minFrac = pB->nFrac;
for(i=pA->nDigit-1; i>=0; i--){
signed char f = pA->a[i];
int carry = 0, x;
for(j=pB->nDigit-1, k=i+j+3; j>=0; j--, k--){
x = acc[k] + f*pB->a[j] + carry;
acc[k] = x%10;
carry = x/10;
}
x = acc[k] + carry;
acc[k] = x%10;
acc[k-1] += x/10;
}
sqlite3_free(pA->a);
pA->a = acc;
acc = 0;
pA->nDigit += pB->nDigit + 2;
pA->nFrac += pB->nFrac;
pA->sign ^= pB->sign;
while( pA->nFrac>minFrac && pA->a[pA->nDigit-1]==0 ){
pA->nFrac--;
pA->nDigit--;
}
decimal_result(context, pA);
mul_end:
sqlite3_free(acc);
decimal_free(pA);
decimal_free(pB);
}
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_decimal_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
static const struct {
const char *zFuncName;
int nArg;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "decimal", 1, decimalFunc },
{ "decimal_cmp", 2, decimalCmpFunc },
{ "decimal_add", 2, decimalAddFunc },
{ "decimal_sub", 2, decimalSubFunc },
{ "decimal_mul", 2, decimalMulFunc },
};
unsigned int i;
(void)pzErrMsg; /* Unused parameter */
SQLITE_EXTENSION_INIT2(pApi);
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_function(db, aFunc[i].zFuncName, aFunc[i].nArg,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC,
0, aFunc[i].xFunc, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_window_function(db, "decimal_sum", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS|SQLITE_DETERMINISTIC, 0,
decimalSumStep, decimalSumFinalize,
decimalSumValue, decimalSumInverse, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_create_collation(db, "decimal", SQLITE_UTF8,
0, decimalCollFunc);
}
return rc;
}
+1 -1
View File
@@ -16,7 +16,7 @@
** Usage example:
**
** .load ./explain
** SELECT p2 FROM explain('SELECT * FROM sqlite_master')
** SELECT p2 FROM explain('SELECT * FROM sqlite_schema')
** WHERE opcode='OpenRead';
**
** This module was originally written to help simplify SQLite testing,
+169 -21
View File
@@ -26,16 +26,76 @@
**
** Examples:
**
** ieee754(2.0) -> 'ieee754(2,0)'
** ieee754(45.25) -> 'ieee754(181,-2)'
** ieee754(2, 0) -> 2.0
** ieee754(181, -2) -> 45.25
** ieee754(2.0) -> 'ieee754(2,0)'
** ieee754(45.25) -> 'ieee754(181,-2)'
** ieee754(2, 0) -> 2.0
** ieee754(181, -2) -> 45.25
**
** Two additional functions break apart the one-argument ieee754()
** result into separate integer values:
**
** ieee754_mantissa(45.25) -> 181
** ieee754_exponent(45.25) -> -2
**
** These functions convert binary64 numbers into blobs and back again.
**
** ieee754_from_blob(x'3ff0000000000000') -> 1.0
** ieee754_to_blob(1.0) -> x'3ff0000000000000'
**
** In all single-argument functions, if the argument is an 8-byte blob
** then that blob is interpreted as a big-endian binary64 value.
**
**
** EXACT DECIMAL REPRESENTATION OF BINARY64 VALUES
** -----------------------------------------------
**
** This extension in combination with the separate 'decimal' extension
** can be used to compute the exact decimal representation of binary64
** values. To begin, first compute a table of exponent values:
**
** CREATE TABLE pow2(x INTEGER PRIMARY KEY, v TEXT);
** WITH RECURSIVE c(x,v) AS (
** VALUES(0,'1')
** UNION ALL
** SELECT x+1, decimal_mul(v,'2') FROM c WHERE x+1<=971
** ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
** WITH RECURSIVE c(x,v) AS (
** VALUES(-1,'0.5')
** UNION ALL
** SELECT x-1, decimal_mul(v,'0.5') FROM c WHERE x-1>=-1075
** ) INSERT INTO pow2(x,v) SELECT x, v FROM c;
**
** Then, to compute the exact decimal representation of a floating
** point value (the value 47.49 is used in the example) do:
**
** WITH c(n) AS (VALUES(47.49))
** ---------------^^^^^---- Replace with whatever you want
** SELECT decimal_mul(ieee754_mantissa(c.n),pow2.v)
** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.n);
**
** Here is a query to show various boundry values for the binary64
** number format:
**
** WITH c(name,bin) AS (VALUES
** ('minimum positive value', x'0000000000000001'),
** ('maximum subnormal value', x'000fffffffffffff'),
** ('mininum positive nornal value', x'0010000000000000'),
** ('maximum value', x'7fefffffffffffff'))
** SELECT c.name, decimal_mul(ieee754_mantissa(c.bin),pow2.v)
** FROM pow2, c WHERE pow2.x=ieee754_exponent(c.bin);
**
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
/* Mark a function parameter as unused, to suppress nuisance compiler
** warnings. */
#ifndef UNUSED_PARAMETER
# define UNUSED_PARAMETER(X) (void)(X)
#endif
/*
** Implementation of the ieee754() function
*/
@@ -51,8 +111,19 @@ static void ieee754func(
int isNeg;
char zResult[100];
assert( sizeof(m)==sizeof(r) );
if( sqlite3_value_type(argv[0])!=SQLITE_FLOAT ) return;
r = sqlite3_value_double(argv[0]);
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
&& sqlite3_value_bytes(argv[0])==sizeof(r)
){
const unsigned char *x = sqlite3_value_blob(argv[0]);
unsigned int i;
sqlite3_uint64 v = 0;
for(i=0; i<sizeof(r); i++){
v = (v<<8) | x[i];
}
memcpy(&r, &v, sizeof(r));
}else{
r = sqlite3_value_double(argv[0]);
}
if( r<0.0 ){
isNeg = 1;
r = -r;
@@ -66,17 +137,31 @@ static void ieee754func(
}else{
e = a>>52;
m = a & ((((sqlite3_int64)1)<<52)-1);
m |= ((sqlite3_int64)1)<<52;
if( e==0 ){
m <<= 1;
}else{
m |= ((sqlite3_int64)1)<<52;
}
while( e<1075 && m>0 && (m&1)==0 ){
m >>= 1;
e++;
}
if( isNeg ) m = -m;
}
sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
m, e-1075);
sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
}else if( argc==2 ){
switch( *(int*)sqlite3_user_data(context) ){
case 0:
sqlite3_snprintf(sizeof(zResult), zResult, "ieee754(%lld,%d)",
m, e-1075);
sqlite3_result_text(context, zResult, -1, SQLITE_TRANSIENT);
break;
case 1:
sqlite3_result_int64(context, m);
break;
case 2:
sqlite3_result_int(context, e-1075);
break;
}
}else{
sqlite3_int64 m, e, a;
double r;
int isNeg = 0;
@@ -86,7 +171,7 @@ static void ieee754func(
isNeg = 1;
m = -m;
if( m<0 ) return;
}else if( m==0 && e>1000 && e<1000 ){
}else if( m==0 && e>-1000 && e<1000 ){
sqlite3_result_double(context, 0.0);
return;
}
@@ -99,8 +184,13 @@ static void ieee754func(
e--;
}
e += 1075;
if( e<0 ) e = m = 0;
if( e>0x7ff ) e = 0x7ff;
if( e<=0 ){
/* Subnormal */
m >>= 1-e;
e = 0;
}else if( e>0x7ff ){
e = 0x7ff;
}
a = m & ((((sqlite3_int64)1)<<52)-1);
a |= e<<52;
if( isNeg ) a |= ((sqlite3_uint64)1)<<63;
@@ -109,6 +199,51 @@ static void ieee754func(
}
}
/*
** Functions to convert between blobs and floats.
*/
static void ieee754func_from_blob(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_BLOB
&& sqlite3_value_bytes(argv[0])==sizeof(double)
){
double r;
const unsigned char *x = sqlite3_value_blob(argv[0]);
unsigned int i;
sqlite3_uint64 v = 0;
for(i=0; i<sizeof(r); i++){
v = (v<<8) | x[i];
}
memcpy(&r, &v, sizeof(r));
sqlite3_result_double(context, r);
}
}
static void ieee754func_to_blob(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
UNUSED_PARAMETER(argc);
if( sqlite3_value_type(argv[0])==SQLITE_FLOAT
|| sqlite3_value_type(argv[0])==SQLITE_INTEGER
){
double r = sqlite3_value_double(argv[0]);
sqlite3_uint64 v;
unsigned char a[sizeof(r)];
unsigned int i;
memcpy(&v, &r, sizeof(r));
for(i=1; i<=sizeof(r); i++){
a[sizeof(r)-i] = v&0xff;
v >>= 8;
}
sqlite3_result_blob(context, a, sizeof(r), SQLITE_TRANSIENT);
}
}
#ifdef _WIN32
__declspec(dllexport)
@@ -118,16 +253,29 @@ int sqlite3_ieee_init(
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
static const struct {
char *zFName;
int nArg;
int iAux;
void (*xFunc)(sqlite3_context*,int,sqlite3_value**);
} aFunc[] = {
{ "ieee754", 1, 0, ieee754func },
{ "ieee754", 2, 0, ieee754func },
{ "ieee754_mantissa", 1, 1, ieee754func },
{ "ieee754_exponent", 1, 2, ieee754func },
{ "ieee754_to_blob", 1, 0, ieee754func_to_blob },
{ "ieee754_from_blob", 1, 0, ieee754func_from_blob },
};
unsigned int i;
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "ieee754", 1,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
ieee754func, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "ieee754", 2,
SQLITE_UTF8|SQLITE_INNOCUOUS, 0,
ieee754func, 0, 0);
for(i=0; i<sizeof(aFunc)/sizeof(aFunc[0]) && rc==SQLITE_OK; i++){
rc = sqlite3_create_function(db, aFunc[i].zFName, aFunc[i].nArg,
SQLITE_UTF8|SQLITE_INNOCUOUS,
(void*)&aFunc[i].iAux,
aFunc[i].xFunc, 0, 0);
}
return rc;
}
+7 -2
View File
@@ -42,6 +42,10 @@ SQLITE_EXTENSION_INIT1
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
#ifndef deliberate_fall_through
# define deliberate_fall_through
#endif
/*
** Versions of isspace(), isalnum() and isdigit() to which it is safe
** to pass signed char values.
@@ -460,7 +464,7 @@ static void jsonRenderNode(
jsonAppendString(pOut, pNode->u.zJContent, pNode->n);
break;
}
/* Fall through into the next case */
/* no break */ deliberate_fall_through
}
case JSON_REAL:
case JSON_INT: {
@@ -601,7 +605,7 @@ static void jsonReturn(
sqlite3_result_int64(pCtx, i);
int_done:
break;
int_as_real: /* fall through to real */;
int_as_real: i=0; /* no break */ deliberate_fall_through
}
case JSON_REAL: {
double r;
@@ -2304,6 +2308,7 @@ static int jsonEachColumn(
}
/* For json_each() path and root are the same so fall through
** into the root case */
/* no break */ deliberate_fall_through
}
default: {
const char *zRoot = p->zRoot;
+1 -1
View File
@@ -43,7 +43,7 @@ int sqlite3_mmap_warm(sqlite3 *db, const char *zDb){
if( 0==sqlite3_get_autocommit(db) ) return SQLITE_MISUSE;
/* Open a read-only transaction on the file in question */
zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_master",
zSql = sqlite3_mprintf("BEGIN; SELECT * FROM %s%q%ssqlite_schema",
(zDb ? "'" : ""), (zDb ? zDb : ""), (zDb ? "'." : "")
);
if( zSql==0 ) return SQLITE_NOMEM;
+9
View File
@@ -286,6 +286,13 @@ static const unsigned char sqlite3CtypeMap[256] = {
#define TK_VARIABLE TK_LITERAL
#define TK_BLOB TK_LITERAL
/* Disable nuisence warnings about case fall-through */
#if !defined(deliberate_fall_through) && defined(__GCC__) && __GCC__>=7
# define deliberate_fall_through __attribute__((fallthrough));
#else
# define deliberate_fall_through
#endif
/*
** Return the length (in bytes) of the token that begins at z[0].
** Store the token type in *tokenType before returning.
@@ -436,6 +443,7 @@ static int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
/* If the next character is a digit, this is a floating point
** number that begins with ".". Fall thru into the next case */
/* no break */ deliberate_fall_through
}
case CC_DIGIT: {
*tokenType = TK_INTEGER;
@@ -528,6 +536,7 @@ static int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
/* If it is not a BLOB literal, then it must be an ID, since no
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
case CC_ID: {
i = 1;
+2 -2
View File
@@ -166,7 +166,7 @@ static void scrubBackupOpenSrc(ScrubState *p){
sqlite3_errmsg(p->dbSrc));
return;
}
p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_master; BEGIN;",
p->rcErr = sqlite3_exec(p->dbSrc, "SELECT 1 FROM sqlite_schema; BEGIN;",
0, 0, 0);
if( p->rcErr ){
scrubBackupErr(p,
@@ -535,7 +535,7 @@ int sqlite3_scrub_backup(
/* Copy all of the btrees */
scrubBackupBtree(&s, 1, 0);
pStmt = scrubBackupPrepare(&s, s.dbSrc,
"SELECT rootpage FROM sqlite_master WHERE coalesce(rootpage,0)>0");
"SELECT rootpage FROM sqlite_schema WHERE coalesce(rootpage,0)>0");
if( pStmt==0 ) goto scrub_abort;
while( sqlite3_step(pStmt)==SQLITE_ROW ){
i = (u32)sqlite3_column_int(pStmt, 0);
+18 -18
View File
@@ -975,7 +975,7 @@ static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){
rc = prepareFreeAndCollectError(p->dbRbu, &pIter->pTblIter, &p->zErrmsg,
sqlite3_mprintf(
"SELECT rbu_target_name(name, type='view') AS target, name "
"FROM sqlite_master "
"FROM sqlite_schema "
"WHERE type IN ('table', 'view') AND target IS NOT NULL "
" %s "
"ORDER BY name"
@@ -984,7 +984,7 @@ static int rbuObjIterFirst(sqlite3rbu *p, RbuObjIter *pIter){
if( rc==SQLITE_OK ){
rc = prepareAndCollectError(p->dbMain, &pIter->pIdxIter, &p->zErrmsg,
"SELECT name, rootpage, sql IS NULL OR substr(8, 6)=='UNIQUE' "
" FROM main.sqlite_master "
" FROM main.sqlite_schema "
" WHERE type='index' AND tbl_name = ?"
);
}
@@ -1156,12 +1156,12 @@ static void rbuFinalize(sqlite3rbu *p, sqlite3_stmt *pStmt){
**
** ALGORITHM:
**
** if( no entry exists in sqlite_master ){
** if( no entry exists in sqlite_schema ){
** return RBU_PK_NOTABLE
** }else if( sql for the entry starts with "CREATE VIRTUAL" ){
** return RBU_PK_VTAB
** }else if( "PRAGMA index_list()" for the table contains a "pk" index ){
** if( the index that is the pk exists in sqlite_master ){
** if( the index that is the pk exists in sqlite_schema ){
** *piPK = rootpage of that index.
** return RBU_PK_EXTERNAL
** }else{
@@ -1181,9 +1181,9 @@ static void rbuTableType(
int *piPk
){
/*
** 0) SELECT count(*) FROM sqlite_master where name=%Q AND IsVirtual(%Q)
** 0) SELECT count(*) FROM sqlite_schema where name=%Q AND IsVirtual(%Q)
** 1) PRAGMA index_list = ?
** 2) SELECT count(*) FROM sqlite_master where name=%Q
** 2) SELECT count(*) FROM sqlite_schema where name=%Q
** 3) PRAGMA table_info = ?
*/
sqlite3_stmt *aStmt[4] = {0, 0, 0, 0};
@@ -1195,7 +1195,7 @@ static void rbuTableType(
p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[0], &p->zErrmsg,
sqlite3_mprintf(
"SELECT (sql LIKE 'create virtual%%'), rootpage"
" FROM sqlite_master"
" FROM sqlite_schema"
" WHERE name=%Q", zTab
));
if( p->rc!=SQLITE_OK || sqlite3_step(aStmt[0])!=SQLITE_ROW ){
@@ -1218,7 +1218,7 @@ static void rbuTableType(
if( zOrig && zIdx && zOrig[0]=='p' ){
p->rc = prepareFreeAndCollectError(p->dbMain, &aStmt[2], &p->zErrmsg,
sqlite3_mprintf(
"SELECT rootpage FROM sqlite_master WHERE name = %Q", zIdx
"SELECT rootpage FROM sqlite_schema WHERE name = %Q", zIdx
));
if( p->rc==SQLITE_OK ){
if( sqlite3_step(aStmt[2])==SQLITE_ROW ){
@@ -2038,7 +2038,7 @@ static void rbuCreateImposterTable2(sqlite3rbu *p, RbuObjIter *pIter){
** This is needed for the argument to "PRAGMA index_xinfo". Set
** zIdx to point to a nul-terminated string containing this name. */
p->rc = prepareAndCollectError(p->dbMain, &pQuery, &p->zErrmsg,
"SELECT name FROM sqlite_master WHERE rootpage = ?"
"SELECT name FROM sqlite_schema WHERE rootpage = ?"
);
if( p->rc==SQLITE_OK ){
sqlite3_bind_int(pQuery, 1, tnum);
@@ -2211,7 +2211,7 @@ static char *rbuObjIterGetIndexWhere(sqlite3rbu *p, RbuObjIter *pIter){
if( rc==SQLITE_OK ){
rc = prepareAndCollectError(p->dbMain, &pStmt, &p->zErrmsg,
"SELECT trim(sql) FROM sqlite_master WHERE type='index' AND name=?"
"SELECT trim(sql) FROM sqlite_schema WHERE type='index' AND name=?"
);
}
if( rc==SQLITE_OK ){
@@ -2793,7 +2793,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
int bOk = 0;
sqlite3_stmt *pCnt = 0;
p->rc = prepareAndCollectError(p->dbRbu, &pCnt, &p->zErrmsg,
"SELECT count(*) FROM stat.sqlite_master"
"SELECT count(*) FROM stat.sqlite_schema"
);
if( p->rc==SQLITE_OK
&& sqlite3_step(pCnt)==SQLITE_ROW
@@ -2897,7 +2897,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
if( p->rc==SQLITE_OK ){
p->rc = sqlite3_file_control(p->dbMain, "main", SQLITE_FCNTL_RBU, (void*)p);
}
rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_master");
rbuMPrintfExec(p, p->dbMain, "SELECT * FROM sqlite_schema");
/* Mark the database file just opened as an RBU target database. If
** this call returns SQLITE_NOTFOUND, then the RBU vfs is not in use.
@@ -2990,7 +2990,7 @@ static void rbuSetupCheckpoint(sqlite3rbu *p, RbuState *pState){
if( pState==0 ){
p->eStage = 0;
if( p->rc==SQLITE_OK ){
p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_master", 0, 0, 0);
p->rc = sqlite3_exec(p->dbMain, "SELECT * FROM sqlite_schema", 0, 0, 0);
}
}
@@ -3581,7 +3581,7 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){
p->rc = sqlite3_exec(p->dbMain, "PRAGMA writable_schema=1", 0,0, &p->zErrmsg);
if( p->rc==SQLITE_OK ){
p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg,
"SELECT sql FROM sqlite_master WHERE sql!='' AND rootpage!=0"
"SELECT sql FROM sqlite_schema WHERE sql!='' AND rootpage!=0"
" AND name!='sqlite_sequence' "
" ORDER BY type DESC"
);
@@ -3596,13 +3596,13 @@ static void rbuCreateTargetSchema(sqlite3rbu *p){
if( p->rc==SQLITE_OK ){
p->rc = prepareAndCollectError(p->dbRbu, &pSql, &p->zErrmsg,
"SELECT * FROM sqlite_master WHERE rootpage=0 OR rootpage IS NULL"
"SELECT * FROM sqlite_schema WHERE rootpage=0 OR rootpage IS NULL"
);
}
if( p->rc==SQLITE_OK ){
p->rc = prepareAndCollectError(p->dbMain, &pInsert, &p->zErrmsg,
"INSERT INTO sqlite_master VALUES(?,?,?,?,?)"
"INSERT INTO sqlite_schema VALUES(?,?,?,?,?)"
);
}
@@ -3865,7 +3865,7 @@ static void rbuIndexCntFunc(
assert( nVal==1 );
rc = prepareFreeAndCollectError(db, &pStmt, &zErrmsg,
sqlite3_mprintf("SELECT count(*) FROM sqlite_master "
sqlite3_mprintf("SELECT count(*) FROM sqlite_schema "
"WHERE type='index' AND tbl_name = %Q", sqlite3_value_text(apVal[0]))
);
if( rc!=SQLITE_OK ){
@@ -3916,7 +3916,7 @@ static void rbuInitPhaseOneSteps(sqlite3rbu *p){
** occurs, nPhaseOneStep will be left set to -1. */
if( p->rc==SQLITE_OK ){
p->rc = prepareAndCollectError(p->dbRbu, &pStmt, &p->zErrmsg,
"SELECT 1 FROM sqlite_master WHERE tbl_name = 'rbu_count'"
"SELECT 1 FROM sqlite_schema WHERE tbl_name = 'rbu_count'"
);
}
if( p->rc==SQLITE_OK ){
+1 -1
View File
@@ -473,7 +473,7 @@ static int cidxLookupIndex(
/* Find the table for this index. */
pFindTab = cidxPrepare(&rc, pCsr,
"SELECT tbl_name, sql FROM sqlite_master WHERE name=%Q AND type='index'",
"SELECT tbl_name, sql FROM sqlite_schema WHERE name=%Q AND type='index'",
zIdx
);
if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
+2
View File
@@ -683,6 +683,8 @@ static GeoPoly *geopolyBBox(
aCoord[2].f = mnY;
aCoord[3].f = mxY;
}
}else{
memset(aCoord, 0, sizeof(RtreeCoord)*4);
}
return pOut;
}
+18
View File
@@ -82,6 +82,7 @@ typedef unsigned int u32;
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
/* The following macro is used to suppress compiler warnings.
*/
@@ -419,6 +420,23 @@ struct RtreeMatchArg {
# define testcase(X)
#endif
/*
** Make sure that the compiler intrinsics we desire are enabled when
** compiling with an appropriate version of MSVC unless prevented by
** the SQLITE_DISABLE_INTRINSIC define.
*/
#if !defined(SQLITE_DISABLE_INTRINSIC)
# if defined(_MSC_VER) && _MSC_VER>=1400
# if !defined(_WIN32_WCE)
# include <intrin.h>
# pragma intrinsic(_byteswap_ulong)
# pragma intrinsic(_byteswap_uint64)
# else
# include <cmnintrin.h>
# endif
# endif
#endif
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
+2 -2
View File
@@ -172,8 +172,8 @@ proc compare_db {db1 db2} {
set data1 [$db1 eval $sql]
set data2 [$db2 eval $sql]
if {$data1 != $data2} {
puts "$data1"
puts "$data2"
puts "$db1: $data1"
puts "$db2: $data2"
error "table $tbl data mismatch"
}
}
+24
View File
@@ -155,5 +155,29 @@ do_test 3.2 {
compare_db db db2
} {}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 4.0 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b UNIQUE);
INSERT INTO t1 VALUES(1, 'one');
INSERT INTO t1 VALUES(2, 'two');
INSERT INTO t1 VALUES(3, 'three');
INSERT INTO t1 VALUES(4, 'four');
}
do_invert_test 4.1 {
DELETE FROM t1;
INSERT INTO t1 VALUES(1, 'two');
INSERT INTO t1 VALUES(2, 'five');
INSERT INTO t1 VALUES(3, 'one');
INSERT INTO t1 VALUES(4, 'three');
} {
{UPDATE t1 0 X. {i 1 t two} {{} {} t one}}
{UPDATE t1 0 X. {i 2 t five} {{} {} t two}}
{UPDATE t1 0 X. {i 3 t one} {{} {} t three}}
{UPDATE t1 0 X. {i 4 t three} {{} {} t four}}
}
finish_test
+12 -3
View File
@@ -2956,8 +2956,13 @@ static int sessionChangesetReadTblhdr(sqlite3_changeset_iter *p){
}
p->apValue = (sqlite3_value**)p->tblhdr.aBuf;
p->abPK = (u8*)&p->apValue[p->nCol*2];
p->zTab = (char*)&p->abPK[p->nCol];
if( p->apValue==0 ){
p->abPK = 0;
p->zTab = 0;
}else{
p->abPK = (u8*)&p->apValue[p->nCol*2];
p->zTab = p->abPK ? (char*)&p->abPK[p->nCol] : 0;
}
return (p->rc = rc);
}
@@ -3479,6 +3484,7 @@ struct SessionApplyCtx {
u8 *abPK; /* Boolean array - true if column is in PK */
int bStat1; /* True if table is sqlite_stat1 */
int bDeferConstraints; /* True to defer constraints */
int bInvertConstraints; /* Invert when iterating constraints buffer */
SessionBuffer constraints; /* Deferred constraints are stored here */
SessionBuffer rebase; /* Rebase information (if any) here */
u8 bRebaseStarted; /* If table header is already in rebase */
@@ -4251,7 +4257,9 @@ static int sessionRetryConstraints(
SessionBuffer cons = pApply->constraints;
memset(&pApply->constraints, 0, sizeof(SessionBuffer));
rc = sessionChangesetStart(&pIter2, 0, 0, cons.nBuf, cons.aBuf, 0);
rc = sessionChangesetStart(
&pIter2, 0, 0, cons.nBuf, cons.aBuf, pApply->bInvertConstraints
);
if( rc==SQLITE_OK ){
size_t nByte = 2*pApply->nCol*sizeof(sqlite3_value*);
int rc2;
@@ -4318,6 +4326,7 @@ static int sessionChangesetApply(
pIter->in.bNoDiscard = 1;
memset(&sApply, 0, sizeof(sApply));
sApply.bRebase = (ppRebase && pnRebase);
sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT);
sqlite3_mutex_enter(sqlite3_db_mutex(db));
if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){
rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0);
+16 -4
View File
@@ -363,6 +363,7 @@ TESTSRC += \
$(TOP)/ext/misc/carray.c \
$(TOP)/ext/misc/closure.c \
$(TOP)/ext/misc/csv.c \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/eval.c \
$(TOP)/ext/misc/explain.c \
$(TOP)/ext/misc/fileio.c \
@@ -727,6 +728,12 @@ parse.c: $(TOP)/src/parse.y lemon
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
sqlite3rc.h: $(TOP)/src/sqlite3.rc $(TOP)/VERSION
echo '#ifndef SQLITE_RESOURCE_VERSION' >$@
echo -n '#define SQLITE_RESOURCE_VERSION ' >>$@
cat $(TOP)/VERSION | tclsh $(TOP)/tool/replace.tcl exact . , >>$@
echo '#endif' >>sqlite3rc.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash $(OPTS) $(TOP)/tool/mkkeywordhash.c
./mkkeywordhash >keywordhash.h
@@ -735,9 +742,11 @@ keywordhash.h: $(TOP)/tool/mkkeywordhash.c
SHELL_SRC = \
$(TOP)/src/shell.c.in \
$(TOP)/ext/misc/appendvfs.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/completion.c \
$(TOP)/ext/misc/decimal.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/sqlar.c \
$(TOP)/ext/misc/uint.c \
$(TOP)/ext/expert/sqlite3expert.c \
@@ -975,6 +984,9 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(EXE)
./testfixture$(EXE) $(TOP)/test/main.test $(TESTOPTS)
shelltest: $(TESTPROGS)
./testfixture$(EXT) $(TOP)/test/permutations.test shell
# The next two rules are used to support the "threadtest" target. Building
# threadtest runs a few thread-safety tests that are implemented in C. This
# target is invoked by the releasetest.tcl script.
@@ -1076,10 +1088,10 @@ checksymbols: sqlite3.o
# a tarball named for the version number. Ex: sqlite-autoconf-3110000.tar.gz.
# The snapshot-tarball target builds a tarball named by the SHA1 hash
#
amalgamation-tarball: sqlite3.c
amalgamation-tarball: sqlite3.c sqlite3rc.h
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --normal
snapshot-tarball: sqlite3.c
snapshot-tarball: sqlite3.c sqlite3rc.h
TOP=$(TOP) sh $(TOP)/tool/mkautoconfamal.sh --snapshot
+1880 -17
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -1 +1 @@
7ebdfa80be8e8e73324b8d66b3460222eb74c7e9dfd655b48d6ca7e1933cc8fd
fca8dc8b578f215a969cd899336378966156154710873e68b3d9ac5881b0ff3f
+40 -33
View File
@@ -52,22 +52,22 @@ static int isAlterableTable(Parse *pParse, Table *pTab){
static void renameTestSchema(Parse *pParse, const char *zDb, int bTemp){
sqlite3NestedParse(pParse,
"SELECT 1 "
"FROM \"%w\".%s "
"FROM \"%w\"." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
" AND sqlite_rename_test(%Q, sql, type, name, %d)=NULL ",
zDb, MASTER_NAME,
zDb,
zDb, bTemp
);
if( bTemp==0 ){
sqlite3NestedParse(pParse,
"SELECT 1 "
"FROM temp.%s "
"FROM temp." DFLT_SCHEMA_TABLE " "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
" AND sql NOT LIKE 'create virtual%%'"
" AND sqlite_rename_test(%Q, sql, type, name, 1)=NULL ",
MASTER_NAME, zDb
zDb
);
}
}
@@ -185,17 +185,17 @@ void sqlite3AlterRenameTable(
/* Rewrite all CREATE TABLE, INDEX, TRIGGER or VIEW statements in
** the schema to use the new table name. */
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, %d) "
"WHERE (type!='index' OR tbl_name=%Q COLLATE nocase)"
"AND name NOT LIKE 'sqliteX_%%' ESCAPE 'X'"
, zDb, MASTER_NAME, zDb, zTabName, zName, (iDb==1), zTabName
, zDb, zDb, zTabName, zName, (iDb==1), zTabName
);
/* Update the tbl_name and name columns of the sqlite_master table
/* Update the tbl_name and name columns of the sqlite_schema table
** as required. */
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET "
"UPDATE %Q." DFLT_SCHEMA_TABLE " SET "
"tbl_name = %Q, "
"name = CASE "
"WHEN type='table' THEN %Q "
@@ -205,7 +205,7 @@ void sqlite3AlterRenameTable(
"ELSE name END "
"WHERE tbl_name=%Q COLLATE nocase AND "
"(type='table' OR type='index' OR type='trigger');",
zDb, MASTER_NAME,
zDb,
zName, zName, zName,
nTabName, zTabName
);
@@ -226,7 +226,7 @@ void sqlite3AlterRenameTable(
** as required. */
if( iDb!=1 ){
sqlite3NestedParse(pParse,
"UPDATE sqlite_temp_master SET "
"UPDATE sqlite_temp_schema SET "
"sql = sqlite_rename_table(%Q, type, name, sql, %Q, %Q, 1), "
"tbl_name = "
"CASE WHEN tbl_name=%Q COLLATE nocase AND "
@@ -382,10 +382,10 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
}
db->mDbFlags |= DBFLAG_PreferBuiltin;
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
"sql = substr(sql,1,%d) || ', ' || %Q || substr(sql,%d) "
"WHERE type = 'table' AND name = %Q",
zDb, MASTER_NAME, pNew->addColOffset, zCol, pNew->addColOffset+1,
zDb, pNew->addColOffset, zCol, pNew->addColOffset+1,
zTab
);
sqlite3DbFree(db, zCol);
@@ -587,7 +587,7 @@ void sqlite3AlterRenameColumn(
/* Do the rename operation using a recursive UPDATE statement that
** uses the sqlite_rename_column() SQL function to compute the new
** CREATE statement text for the sqlite_master table.
** CREATE statement text for the sqlite_schema table.
*/
sqlite3MayAbort(pParse);
zNew = sqlite3NameFromToken(db, pNew);
@@ -595,21 +595,20 @@ void sqlite3AlterRenameColumn(
assert( pNew->n>0 );
bQuote = sqlite3Isquote(pNew->z[0]);
sqlite3NestedParse(pParse,
"UPDATE \"%w\".%s SET "
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, %d) "
"WHERE name NOT LIKE 'sqliteX_%%' ESCAPE 'X' "
" AND (type != 'index' OR tbl_name = %Q)"
" AND sql NOT LIKE 'create virtual%%'",
zDb, MASTER_NAME,
zDb,
zDb, pTab->zName, iCol, zNew, bQuote, iSchema==1,
pTab->zName
);
sqlite3NestedParse(pParse,
"UPDATE temp.%s SET "
"UPDATE temp." DFLT_SCHEMA_TABLE " SET "
"sql = sqlite_rename_column(sql, type, name, %Q, %Q, %d, %Q, %d, 1) "
"WHERE type IN ('trigger', 'view')",
MASTER_NAME,
zDb, pTab->zName, iCol, zNew, bQuote
);
@@ -1161,7 +1160,7 @@ static int renameEditSql(
** successful. Otherwise, return an SQLite error code and leave an error
** message in the Parse object.
*/
static int renameResolveTrigger(Parse *pParse, const char *zDb){
static int renameResolveTrigger(Parse *pParse){
sqlite3 *db = pParse->db;
Trigger *pNew = pParse->pNewTrigger;
TriggerStep *pStep;
@@ -1192,17 +1191,22 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
if( pParse->nErr ) rc = pParse->rc;
}
if( rc==SQLITE_OK && pStep->zTarget ){
Table *pTarget = sqlite3LocateTable(pParse, 0, pStep->zTarget, zDb);
if( pTarget==0 ){
rc = SQLITE_ERROR;
}else if( SQLITE_OK==(rc = sqlite3ViewGetColumnNames(pParse, pTarget)) ){
SrcList sSrc;
memset(&sSrc, 0, sizeof(sSrc));
sSrc.nSrc = 1;
sSrc.a[0].zName = pStep->zTarget;
sSrc.a[0].pTab = pTarget;
sNC.pSrcList = &sSrc;
if( pStep->pWhere ){
SrcList *pSrc = sqlite3TriggerStepSrc(pParse, pStep);
if( pSrc ){
int i;
for(i=0; i<pSrc->nSrc && rc==SQLITE_OK; i++){
struct SrcList_item *p = &pSrc->a[i];
p->pTab = sqlite3LocateTableItem(pParse, 0, p);
p->iCursor = pParse->nTab++;
if( p->pTab==0 ){
rc = SQLITE_ERROR;
}else{
p->pTab->nTabRef++;
rc = sqlite3ViewGetColumnNames(pParse, p->pTab);
}
}
sNC.pSrcList = pSrc;
if( rc==SQLITE_OK && pStep->pWhere ){
rc = sqlite3ResolveExprNames(&sNC, pStep->pWhere);
}
if( rc==SQLITE_OK ){
@@ -1212,7 +1216,7 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
if( pStep->pUpsert ){
Upsert *pUpsert = pStep->pUpsert;
assert( rc==SQLITE_OK );
pUpsert->pUpsertSrc = &sSrc;
pUpsert->pUpsertSrc = pSrc;
sNC.uNC.pUpsert = pUpsert;
sNC.ncFlags = NC_UUpsert;
rc = sqlite3ResolveExprListNames(&sNC, pUpsert->pUpsertTarget);
@@ -1229,6 +1233,9 @@ static int renameResolveTrigger(Parse *pParse, const char *zDb){
sNC.ncFlags = 0;
}
sNC.pSrcList = 0;
sqlite3SrcListDelete(db, pSrc);
}else{
rc = SQLITE_NOMEM;
}
}
}
@@ -1415,7 +1422,7 @@ static void renameColumnFunc(
}else{
/* A trigger */
TriggerStep *pStep;
rc = renameResolveTrigger(&sParse, (bTemp ? 0 : zDb));
rc = renameResolveTrigger(&sParse);
if( rc!=SQLITE_OK ) goto renameColumnFunc_done;
for(pStep=sParse.pNewTrigger->step_list; pStep; pStep=pStep->pNext){
@@ -1618,7 +1625,7 @@ static void renameTableFunc(
}
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
rc = renameResolveTrigger(&sParse);
if( rc==SQLITE_OK ){
renameWalkTrigger(&sWalker, pTrigger);
for(pStep=pTrigger->step_list; pStep; pStep=pStep->pNext){
@@ -1705,7 +1712,7 @@ static void renameTableTest(
else if( sParse.pNewTrigger ){
if( isLegacy==0 ){
rc = renameResolveTrigger(&sParse, bTemp ? 0 : zDb);
rc = renameResolveTrigger(&sParse);
}
if( rc==SQLITE_OK ){
int i1 = sqlite3SchemaToIndex(db, sParse.pNewTrigger->pTabSchema);
+31 -7
View File
@@ -186,7 +186,7 @@ static void openStatTable(
sqlite3 *db = pParse->db;
Db *pDb;
Vdbe *v = sqlite3GetVdbe(pParse);
int aRoot[ArraySize(aTable)];
u32 aRoot[ArraySize(aTable)];
u8 aCreateTbl[ArraySize(aTable)];
#ifdef SQLITE_ENABLE_STAT4
const int nToOpen = OptimizationEnabled(db,SQLITE_Stat4) ? 2 : 1;
@@ -215,7 +215,7 @@ static void openStatTable(
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.%s(%s)", pDb->zDbSName, zTab, aTable[i].zCols
);
aRoot[i] = pParse->regRoot;
aRoot[i] = (u32)pParse->regRoot;
aCreateTbl[i] = OPFLAG_P2ISREG;
}
}else{
@@ -235,7 +235,7 @@ static void openStatTable(
#endif
}else{
/* The sqlite_stat[134] table already exists. Delete all rows. */
sqlite3VdbeAddOp2(v, OP_Clear, aRoot[i], iDb);
sqlite3VdbeAddOp2(v, OP_Clear, (int)aRoot[i], iDb);
}
}
}
@@ -243,7 +243,7 @@ static void openStatTable(
/* Open the sqlite_stat[134] tables for writing. */
for(i=0; i<nToOpen; i++){
assert( i<ArraySize(aTable) );
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, aRoot[i], iDb, 3);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, iStatCur+i, (int)aRoot[i], iDb, 3);
sqlite3VdbeChangeP5(v, aCreateTbl[i]);
VdbeComment((v, aTable[i].zName));
}
@@ -951,6 +951,30 @@ static void callStatGet(Parse *pParse, int regStat, int iParam, int regOut){
&statGetFuncdef, 0);
}
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
/* Add a comment to the most recent VDBE opcode that is the name
** of the k-th column of the pIdx index.
*/
static void analyzeVdbeCommentIndexWithColumnName(
Vdbe *v, /* Prepared statement under construction */
Index *pIdx, /* Index whose column is being loaded */
int k /* Which column index */
){
int i; /* Index of column in the table */
assert( k>=0 && k<pIdx->nColumn );
i = pIdx->aiColumn[k];
if( NEVER(i==XN_ROWID) ){
VdbeComment((v,"%s.rowid",pIdx->zName));
}else if( i==XN_EXPR ){
VdbeComment((v,"%s.expr(%d)",pIdx->zName, k));
}else{
VdbeComment((v,"%s.%s", pIdx->zName, pIdx->pTable->aCol[i].zName));
}
}
#else
# define analyzeVdbeCommentIndexWithColumnName(a,b,c)
#endif /* SQLITE_DEBUG */
/*
** Generate code to do an analysis of all indices associated with
** a single table.
@@ -1167,7 +1191,7 @@ static void analyzeOneTable(
char *pColl = (char*)sqlite3LocateCollSeq(pParse, pIdx->azColl[i]);
sqlite3VdbeAddOp2(v, OP_Integer, i, regChng);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regTemp);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
analyzeVdbeCommentIndexWithColumnName(v,pIdx,i);
aGotoChng[i] =
sqlite3VdbeAddOp4(v, OP_Ne, regTemp, 0, regPrev+i, pColl, P4_COLLSEQ);
sqlite3VdbeChangeP5(v, SQLITE_NULLEQ);
@@ -1188,7 +1212,7 @@ static void analyzeOneTable(
for(i=0; i<nColTest; i++){
sqlite3VdbeJumpHere(v, aGotoChng[i]);
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, regPrev+i);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
analyzeVdbeCommentIndexWithColumnName(v,pIdx,i);
}
sqlite3VdbeResolveLabel(v, endDistinctTest);
sqlite3DbFree(db, aGotoChng);
@@ -1214,7 +1238,7 @@ static void analyzeOneTable(
k = sqlite3TableColumnToIndex(pIdx, pPk->aiColumn[j]);
assert( k>=0 && k<pIdx->nColumn );
sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, k, regKey+j);
VdbeComment((v, "%s.column(%d)", pIdx->zName, i));
analyzeVdbeCommentIndexWithColumnName(v,pIdx,k);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regKey, pPk->nKeyCol, regRowid);
sqlite3ReleaseTempRange(pParse, regKey, pPk->nKeyCol);
+3
View File
@@ -599,6 +599,9 @@ int sqlite3FixTriggerStep(
if( sqlite3FixExprList(pFix, pStep->pExprList) ){
return 1;
}
if( pStep->pFrom && sqlite3FixSrcList(pFix, pStep->pFrom) ){
return 1;
}
#ifndef SQLITE_OMIT_UPSERT
if( pStep->pUpsert ){
Upsert *pUp = pStep->pUpsert;
+120 -85
View File
@@ -69,7 +69,7 @@ int sqlite3BtreeTrace=1; /* True to enable tracing */
** but the test harness needs to access it so we make it global for
** test builds.
**
** Access to this variable is protected by SQLITE_MUTEX_STATIC_MASTER.
** Access to this variable is protected by SQLITE_MUTEX_STATIC_MAIN.
*/
#ifdef SQLITE_TEST
BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
@@ -357,7 +357,7 @@ static int setSharedCacheTableLock(Btree *p, Pgno iTable, u8 eLock){
/* A connection with the read-uncommitted flag set will never try to
** obtain a read-lock using this function. The only read-lock obtained
** by a connection in read-uncommitted mode is on the sqlite_master
** by a connection in read-uncommitted mode is on the sqlite_schema
** table, and that lock is obtained in BtreeBeginTrans(). */
assert( 0==(p->db->flags&SQLITE_ReadUncommit) || eLock==WRITE_LOCK );
@@ -993,7 +993,7 @@ static void ptrmapPut(BtShared *pBt, Pgno key, u8 eType, Pgno parent, int *pRC){
if( *pRC ) return;
assert( sqlite3_mutex_held(pBt->mutex) );
/* The master-journal page number must never be used as a pointer map page */
/* The super-journal page number must never be used as a pointer map page */
assert( 0==PTRMAP_ISPAGE(pBt, PENDING_BYTE_PAGE(pBt)) );
assert( pBt->autoVacuum );
@@ -2139,12 +2139,11 @@ static MemPage *btreePageLookup(BtShared *pBt, Pgno pgno){
** error, return ((unsigned int)-1).
*/
static Pgno btreePagecount(BtShared *pBt){
assert( (pBt->nPage & 0x80000000)==0 || CORRUPT_DB );
return pBt->nPage;
}
u32 sqlite3BtreeLastPage(Btree *p){
Pgno sqlite3BtreeLastPage(Btree *p){
assert( sqlite3BtreeHoldsMutex(p) );
return btreePagecount(p->pBt) & 0x7fffffff;
return btreePagecount(p->pBt);
}
/*
@@ -2422,7 +2421,7 @@ int sqlite3BtreeOpen(
#if SQLITE_THREADSAFE
mutexOpen = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_OPEN);
sqlite3_mutex_enter(mutexOpen);
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
sqlite3_mutex_enter(mutexShared);
#endif
for(pBt=GLOBAL(BtShared*,sqlite3SharedCacheList); pBt; pBt=pBt->pNext){
@@ -2541,7 +2540,7 @@ int sqlite3BtreeOpen(
pBt->nRef = 1;
if( p->sharable ){
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);)
MUTEX_LOGIC( mutexShared = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);)
if( SQLITE_THREADSAFE && sqlite3GlobalConfig.bCoreMutex ){
pBt->mutex = sqlite3MutexAlloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
@@ -2630,13 +2629,13 @@ btree_open_out:
*/
static int removeFromSharingList(BtShared *pBt){
#ifndef SQLITE_OMIT_SHARED_CACHE
MUTEX_LOGIC( sqlite3_mutex *pMaster; )
MUTEX_LOGIC( sqlite3_mutex *pMainMtx; )
BtShared *pList;
int removed = 0;
assert( sqlite3_mutex_notheld(pBt->mutex) );
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
sqlite3_mutex_enter(pMaster);
MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(pMainMtx);
pBt->nRef--;
if( pBt->nRef<=0 ){
if( GLOBAL(BtShared*,sqlite3SharedCacheList)==pBt ){
@@ -2655,7 +2654,7 @@ static int removeFromSharingList(BtShared *pBt){
}
removed = 1;
}
sqlite3_mutex_leave(pMaster);
sqlite3_mutex_leave(pMainMtx);
return removed;
#else
return 1;
@@ -2932,8 +2931,8 @@ int sqlite3BtreeGetRequestedReserve(Btree *p){
** No changes are made if mxPage is 0 or negative.
** Regardless of the value of mxPage, return the maximum page count.
*/
int sqlite3BtreeMaxPageCount(Btree *p, int mxPage){
int n;
Pgno sqlite3BtreeMaxPageCount(Btree *p, Pgno mxPage){
Pgno n;
sqlite3BtreeEnter(p);
n = sqlite3PagerMaxPageCount(p->pBt->pPager, mxPage);
sqlite3BtreeLeave(p);
@@ -3431,7 +3430,7 @@ int sqlite3BtreeBeginTrans(Btree *p, int wrflag, int *pSchemaVersion){
/* Any read-only or read-write transaction implies a read-lock on
** page 1. So if some other shared-cache client already has a write-lock
** on page 1, the transaction cannot be opened. */
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
if( SQLITE_OK!=rc ) goto trans_begun;
pBt->btsFlags &= ~BTS_INITIALLY_EMPTY;
@@ -3886,7 +3885,7 @@ int sqlite3BtreeIncrVacuum(Btree *p){
Pgno nFree = get4byte(&pBt->pPage1->aData[36]);
Pgno nFin = finalDbSize(pBt, nOrig, nFree);
if( nOrig<nFin ){
if( nOrig<nFin || nFree>=nOrig ){
rc = SQLITE_CORRUPT_BKPT;
}else if( nFree>0 ){
rc = saveAllCursors(pBt, 0, 0);
@@ -3983,18 +3982,18 @@ static int autoVacuumCommit(BtShared *pBt){
**
** This call is a no-op if no write-transaction is currently active on pBt.
**
** Otherwise, sync the database file for the btree pBt. zMaster points to
** the name of a master journal file that should be written into the
** individual journal file, or is NULL, indicating no master journal file
** Otherwise, sync the database file for the btree pBt. zSuperJrnl points to
** the name of a super-journal file that should be written into the
** individual journal file, or is NULL, indicating no super-journal file
** (single database transaction).
**
** When this is called, the master journal should already have been
** When this is called, the super-journal should already have been
** created, populated with this journal pointer and synced to disk.
**
** Once this is routine has returned, the only thing required to commit
** the write-transaction for this database file is to delete the journal.
*/
int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zSuperJrnl){
int rc = SQLITE_OK;
if( p->inTrans==TRANS_WRITE ){
BtShared *pBt = p->pBt;
@@ -4011,7 +4010,7 @@ int sqlite3BtreeCommitPhaseOne(Btree *p, const char *zMaster){
sqlite3PagerTruncateImage(pBt->pPager, pBt->nPage);
}
#endif
rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zMaster, 0);
rc = sqlite3PagerCommitPhaseOne(pBt->pPager, zSuperJrnl, 0);
sqlite3BtreeLeave(p);
}
return rc;
@@ -4074,7 +4073,7 @@ static void btreeEndTransaction(Btree *p){
** the upper layer will attempt a rollback. However, if the second argument
** is non-zero then this b-tree transaction is part of a multi-file
** transaction. In this case, the transaction has already been committed
** (by deleting a master journal file) and the caller will ignore this
** (by deleting a super-journal file) and the caller will ignore this
** functions return code. So, even if an error occurs in the pager layer,
** reset the b-tree objects internal state to indicate that the write
** transaction has been closed. This is quite safe, as the pager will have
@@ -4372,7 +4371,7 @@ int sqlite3BtreeSavepoint(Btree *p, int op, int iSavepoint){
*/
static int btreeCursor(
Btree *p, /* The btree */
int iTable, /* Root page of table to open */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
BtCursor *pCur /* Space for new cursor */
@@ -4415,7 +4414,7 @@ static int btreeCursor(
/* Now that no other errors can occur, finish filling in the BtCursor
** variables and link the cursor into the BtShared list. */
pCur->pgnoRoot = (Pgno)iTable;
pCur->pgnoRoot = iTable;
pCur->iPage = -1;
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
@@ -4425,7 +4424,7 @@ static int btreeCursor(
/* If there are two or more cursors on the same btree, then all such
** cursors *must* have the BTCF_Multiple flag set. */
for(pX=pBt->pCursor; pX; pX=pX->pNext){
if( pX->pgnoRoot==(Pgno)iTable ){
if( pX->pgnoRoot==iTable ){
pX->curFlags |= BTCF_Multiple;
pCur->curFlags |= BTCF_Multiple;
}
@@ -4437,7 +4436,7 @@ static int btreeCursor(
}
static int btreeCursorWithLock(
Btree *p, /* The btree */
int iTable, /* Root page of table to open */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to comparison function */
BtCursor *pCur /* Space for new cursor */
@@ -4450,7 +4449,7 @@ static int btreeCursorWithLock(
}
int sqlite3BtreeCursor(
Btree *p, /* The btree */
int iTable, /* Root page of table to open */
Pgno iTable, /* Root page of table to open */
int wrFlag, /* 1 to write. 0 read-only */
struct KeyInfo *pKeyInfo, /* First arg to xCompare() */
BtCursor *pCur /* Write new cursor here */
@@ -4836,7 +4835,7 @@ static int accessPayload(
Pgno nextPage;
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
**
** The aOverflow[] array is sized at one entry for each overflow page
@@ -4875,6 +4874,7 @@ static int accessPayload(
assert( rc==SQLITE_OK && amt>0 );
while( nextPage ){
/* If required, populate the overflow page-list cache. */
if( nextPage > pBt->nPage ) return SQLITE_CORRUPT_BKPT;
assert( pCur->aOverflow[iIdx]==0
|| pCur->aOverflow[iIdx]==nextPage
|| CORRUPT_DB );
@@ -6290,6 +6290,10 @@ static int freePage2(BtShared *pBt, MemPage *pMemPage, Pgno iPage){
u32 nLeaf; /* Initial number of leaf cells on trunk page */
iTrunk = get4byte(&pPage1->aData[32]);
if( iTrunk>btreePagecount(pBt) ){
rc = SQLITE_CORRUPT_BKPT;
goto freepage_out;
}
rc = btreeGetPage(pBt, iTrunk, &pTrunk, 0);
if( rc!=SQLITE_OK ){
goto freepage_out;
@@ -8772,7 +8776,11 @@ int sqlite3BtreeInsert(
assert( pPage->intKey || pX->nKey>=0 );
assert( pPage->leaf || !pPage->intKey );
if( pPage->nFree<0 ){
rc = btreeComputeFreeSpace(pPage);
if( pCur->eState>CURSOR_INVALID ){
rc = SQLITE_CORRUPT_BKPT;
}else{
rc = btreeComputeFreeSpace(pPage);
}
if( rc ) return rc;
}
@@ -9090,7 +9098,7 @@ int sqlite3BtreeDelete(BtCursor *pCur, u8 flags){
** BTREE_INTKEY|BTREE_LEAFDATA Used for SQL tables with rowid keys
** BTREE_ZERODATA Used for SQL indices
*/
static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
static int btreeCreateTable(Btree *p, Pgno *piTable, int createTabFlags){
BtShared *pBt = p->pBt;
MemPage *pRoot;
Pgno pgnoRoot;
@@ -9123,6 +9131,9 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
** created so far, so the new root-page is (meta[3]+1).
*/
sqlite3BtreeGetMeta(p, BTREE_LARGEST_ROOT_PAGE, &pgnoRoot);
if( pgnoRoot>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
pgnoRoot++;
/* The new root-page may not be allocated on a pointer-map page, or the
@@ -9132,8 +9143,7 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
pgnoRoot==PENDING_BYTE_PAGE(pBt) ){
pgnoRoot++;
}
assert( pgnoRoot>=3 || CORRUPT_DB );
testcase( pgnoRoot<3 );
assert( pgnoRoot>=3 );
/* Allocate a page. The page that currently resides at pgnoRoot will
** be moved to the allocated page (unless the allocated page happens
@@ -9230,10 +9240,10 @@ static int btreeCreateTable(Btree *p, int *piTable, int createTabFlags){
zeroPage(pRoot, ptfFlags);
sqlite3PagerUnref(pRoot->pDbPage);
assert( (pBt->openFlags & BTREE_SINGLE)==0 || pgnoRoot==2 );
*piTable = (int)pgnoRoot;
*piTable = pgnoRoot;
return SQLITE_OK;
}
int sqlite3BtreeCreateTable(Btree *p, int *piTable, int flags){
int sqlite3BtreeCreateTable(Btree *p, Pgno *piTable, int flags){
int rc;
sqlite3BtreeEnter(p);
rc = btreeCreateTable(p, piTable, flags);
@@ -9479,7 +9489,7 @@ void sqlite3BtreeGetMeta(Btree *p, int idx, u32 *pMeta){
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE );
assert( SQLITE_OK==querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK) );
assert( SQLITE_OK==querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK) );
assert( pBt->pPage1 );
assert( idx>=0 && idx<=15 );
@@ -9632,7 +9642,7 @@ static void checkAppendMsg(
sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
va_end(ap);
if( pCheck->errMsg.accError==SQLITE_NOMEM ){
pCheck->mallocFailed = 1;
pCheck->bOomFault = 1;
}
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
@@ -9697,7 +9707,7 @@ static void checkPtrmap(
rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent);
if( rc!=SQLITE_OK ){
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->mallocFailed = 1;
if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) pCheck->bOomFault = 1;
checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild);
return;
}
@@ -9717,7 +9727,7 @@ static void checkPtrmap(
static void checkList(
IntegrityCk *pCheck, /* Integrity checking context */
int isFreeList, /* True for a freelist. False for overflow page list */
int iPage, /* Page number for first page in the list */
Pgno iPage, /* Page number for first page in the list */
u32 N /* Expected number of pages in the list */
){
int i;
@@ -9849,7 +9859,7 @@ static int btreeHeapPull(u32 *aHeap, u32 *pOut){
*/
static int checkTreePage(
IntegrityCk *pCheck, /* Context for the sanity check */
int iPage, /* Page number of the page to check */
Pgno iPage, /* Page number of the page to check */
i64 *piMinKey, /* Write minimum integer primary key here */
i64 maxKey /* Error if integer primary key greater than this */
){
@@ -9885,9 +9895,9 @@ static int checkTreePage(
usableSize = pBt->usableSize;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage) ) return 0;
pCheck->zPfx = "Page %d: ";
pCheck->zPfx = "Page %u: ";
pCheck->v1 = iPage;
if( (rc = btreeGetPage(pBt, (Pgno)iPage, &pPage, 0))!=0 ){
if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){
checkAppendMsg(pCheck,
"unable to get the page. error code=%d", rc);
goto end_of_check;
@@ -9912,7 +9922,7 @@ static int checkTreePage(
hdr = pPage->hdrOffset;
/* Set up for cell analysis */
pCheck->zPfx = "On tree page %d cell %d: ";
pCheck->zPfx = "On tree page %u cell %d: ";
contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
@@ -9932,7 +9942,7 @@ static int checkTreePage(
pgno = get4byte(&data[hdr+8]);
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
pCheck->zPfx = "On page %d at right child: ";
pCheck->zPfx = "On page %u at right child: ";
checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage);
}
#endif
@@ -10073,7 +10083,7 @@ static int checkTreePage(
while( btreeHeapPull(heap,&x) ){
if( (prev&0xffff)>=(x>>16) ){
checkAppendMsg(pCheck,
"Multiple uses for byte %u of page %d", x>>16, iPage);
"Multiple uses for byte %u of page %u", x>>16, iPage);
break;
}else{
nFrag += (x>>16) - (prev&0xffff) - 1;
@@ -10088,7 +10098,7 @@ static int checkTreePage(
*/
if( heap[0]==0 && nFrag!=data[hdr+7] ){
checkAppendMsg(pCheck,
"Fragmentation of %d bytes reported as %d on page %d",
"Fragmentation of %d bytes reported as %d on page %u",
nFrag, data[hdr+7], iPage);
}
}
@@ -10116,11 +10126,20 @@ end_of_check:
** allocation errors, an error message held in memory obtained from
** malloc is returned if *pnErr is non-zero. If *pnErr==0 then NULL is
** returned. If a memory allocation error occurs, NULL is returned.
**
** If the first entry in aRoot[] is 0, that indicates that the list of
** root pages is incomplete. This is a "partial integrity-check". This
** happens when performing an integrity check on a single table. The
** zero is skipped, of course. But in addition, the freelist checks
** and the checks to make sure every page is referenced are also skipped,
** since obviously it is not possible to know which pages are covered by
** the unverified btrees. Except, if aRoot[1] is 1, then the freelist
** checks are still performed.
*/
char *sqlite3BtreeIntegrityCheck(
sqlite3 *db, /* Database connection that is running the check */
Btree *p, /* The btree to be checked */
int *aRoot, /* An array of root pages numbers for individual trees */
Pgno *aRoot, /* An array of root pages numbers for individual trees */
int nRoot, /* Number of entries in aRoot[] */
int mxErr, /* Stop reporting errors after this many */
int *pnErr /* Write number of errors seen to this variable */
@@ -10130,7 +10149,17 @@ char *sqlite3BtreeIntegrityCheck(
BtShared *pBt = p->pBt;
u64 savedDbFlags = pBt->db->flags;
char zErr[100];
int bPartial = 0; /* True if not checking all btrees */
int bCkFreelist = 1; /* True to scan the freelist */
VVA_ONLY( int nRef );
assert( nRoot>0 );
/* aRoot[0]==0 means this is a partial check */
if( aRoot[0]==0 ){
assert( nRoot>1 );
bPartial = 1;
if( aRoot[1]!=1 ) bCkFreelist = 0;
}
sqlite3BtreeEnter(p);
assert( p->inTrans>TRANS_NONE && pBt->inTransaction>TRANS_NONE );
@@ -10142,7 +10171,7 @@ char *sqlite3BtreeIntegrityCheck(
sCheck.nPage = btreePagecount(sCheck.pBt);
sCheck.mxErr = mxErr;
sCheck.nErr = 0;
sCheck.mallocFailed = 0;
sCheck.bOomFault = 0;
sCheck.zPfx = 0;
sCheck.v1 = 0;
sCheck.v2 = 0;
@@ -10156,12 +10185,12 @@ char *sqlite3BtreeIntegrityCheck(
sCheck.aPgRef = sqlite3MallocZero((sCheck.nPage / 8)+ 1);
if( !sCheck.aPgRef ){
sCheck.mallocFailed = 1;
sCheck.bOomFault = 1;
goto integrity_ck_cleanup;
}
sCheck.heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
if( sCheck.heap==0 ){
sCheck.mallocFailed = 1;
sCheck.bOomFault = 1;
goto integrity_ck_cleanup;
}
@@ -10170,29 +10199,33 @@ char *sqlite3BtreeIntegrityCheck(
/* Check the integrity of the freelist
*/
sCheck.zPfx = "Main freelist: ";
checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
get4byte(&pBt->pPage1->aData[36]));
sCheck.zPfx = 0;
if( bCkFreelist ){
sCheck.zPfx = "Main freelist: ";
checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]),
get4byte(&pBt->pPage1->aData[36]));
sCheck.zPfx = 0;
}
/* Check all the tables.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum ){
int mx = 0;
int mxInHdr;
for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
mxInHdr = get4byte(&pBt->pPage1->aData[52]);
if( mx!=mxInHdr ){
if( !bPartial ){
if( pBt->autoVacuum ){
Pgno mx = 0;
Pgno mxInHdr;
for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i];
mxInHdr = get4byte(&pBt->pPage1->aData[52]);
if( mx!=mxInHdr ){
checkAppendMsg(&sCheck,
"max rootpage (%d) disagrees with header (%d)",
mx, mxInHdr
);
}
}else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
checkAppendMsg(&sCheck,
"max rootpage (%d) disagrees with header (%d)",
mx, mxInHdr
"incremental_vacuum enabled with a max rootpage of zero"
);
}
}else if( get4byte(&pBt->pPage1->aData[64])!=0 ){
checkAppendMsg(&sCheck,
"incremental_vacuum enabled with a max rootpage of zero"
);
}
#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
@@ -10201,7 +10234,7 @@ char *sqlite3BtreeIntegrityCheck(
i64 notUsed;
if( aRoot[i]==0 ) continue;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( pBt->autoVacuum && aRoot[i]>1 ){
if( pBt->autoVacuum && aRoot[i]>1 && !bPartial ){
checkPtrmap(&sCheck, aRoot[i], PTRMAP_ROOTPAGE, 0);
}
#endif
@@ -10211,24 +10244,26 @@ char *sqlite3BtreeIntegrityCheck(
/* Make sure every page in the file is referenced
*/
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
if( !bPartial ){
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
#ifdef SQLITE_OMIT_AUTOVACUUM
if( getPageReferenced(&sCheck, i)==0 ){
checkAppendMsg(&sCheck, "Page %d is never used", i);
}
if( getPageReferenced(&sCheck, i)==0 ){
checkAppendMsg(&sCheck, "Page %d is never used", i);
}
#else
/* If the database supports auto-vacuum, make sure no tables contain
** references to pointer-map pages.
*/
if( getPageReferenced(&sCheck, i)==0 &&
(PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
checkAppendMsg(&sCheck, "Page %d is never used", i);
}
if( getPageReferenced(&sCheck, i)!=0 &&
(PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
}
/* If the database supports auto-vacuum, make sure no tables contain
** references to pointer-map pages.
*/
if( getPageReferenced(&sCheck, i)==0 &&
(PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){
checkAppendMsg(&sCheck, "Page %d is never used", i);
}
if( getPageReferenced(&sCheck, i)!=0 &&
(PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){
checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i);
}
#endif
}
}
/* Clean up and report errors.
@@ -10236,7 +10271,7 @@ char *sqlite3BtreeIntegrityCheck(
integrity_ck_cleanup:
sqlite3PageFree(sCheck.heap);
sqlite3_free(sCheck.aPgRef);
if( sCheck.mallocFailed ){
if( sCheck.bOomFault ){
sqlite3_str_reset(&sCheck.errMsg);
sCheck.nErr++;
}
@@ -10356,13 +10391,13 @@ void *sqlite3BtreeSchema(Btree *p, int nBytes, void(*xFree)(void *)){
/*
** Return SQLITE_LOCKED_SHAREDCACHE if another user of the same shared
** btree as the argument handle holds an exclusive lock on the
** sqlite_master table. Otherwise SQLITE_OK.
** sqlite_schema table. Otherwise SQLITE_OK.
*/
int sqlite3BtreeSchemaLocked(Btree *p){
int rc;
assert( sqlite3_mutex_held(p->db->mutex) );
sqlite3BtreeEnter(p);
rc = querySharedCacheTableLock(p, MASTER_ROOT, READ_LOCK);
rc = querySharedCacheTableLock(p, SCHEMA_ROOT, READ_LOCK);
assert( rc==SQLITE_OK || rc==SQLITE_LOCKED_SHAREDCACHE );
sqlite3BtreeLeave(p);
return rc;
+6 -6
View File
@@ -71,20 +71,20 @@ int sqlite3BtreeSetSpillSize(Btree*,int);
int sqlite3BtreeSetPagerFlags(Btree*,unsigned);
int sqlite3BtreeSetPageSize(Btree *p, int nPagesize, int nReserve, int eFix);
int sqlite3BtreeGetPageSize(Btree*);
int sqlite3BtreeMaxPageCount(Btree*,int);
u32 sqlite3BtreeLastPage(Btree*);
Pgno sqlite3BtreeMaxPageCount(Btree*,Pgno);
Pgno sqlite3BtreeLastPage(Btree*);
int sqlite3BtreeSecureDelete(Btree*,int);
int sqlite3BtreeGetRequestedReserve(Btree*);
int sqlite3BtreeGetReserveNoMutex(Btree *p);
int sqlite3BtreeSetAutoVacuum(Btree *, int);
int sqlite3BtreeGetAutoVacuum(Btree *);
int sqlite3BtreeBeginTrans(Btree*,int,int*);
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
int sqlite3BtreeCommitPhaseOne(Btree*, const char*);
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
int sqlite3BtreeCommit(Btree*);
int sqlite3BtreeRollback(Btree*,int,int);
int sqlite3BtreeBeginStmt(Btree*,int);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeCreateTable(Btree*, Pgno*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
int sqlite3BtreeIsInReadTrans(Btree*);
int sqlite3BtreeIsInBackup(Btree*);
@@ -225,7 +225,7 @@ int sqlite3BtreeNewDb(Btree *p);
int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
int iTable, /* Index of root page */
Pgno iTable, /* Index of root page */
int wrFlag, /* 1 for writing. 0 for read-only */
struct KeyInfo*, /* First argument to compare function */
BtCursor *pCursor /* Space to write cursor structure */
@@ -316,7 +316,7 @@ const void *sqlite3BtreePayloadFetch(BtCursor*, u32 *pAmt);
u32 sqlite3BtreePayloadSize(BtCursor*);
sqlite3_int64 sqlite3BtreeMaxRecordSize(BtCursor*);
char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,int*aRoot,int nRoot,int,int*);
char *sqlite3BtreeIntegrityCheck(sqlite3*,Btree*,Pgno*aRoot,int nRoot,int,int*);
struct Pager *sqlite3BtreePager(Btree*);
i64 sqlite3BtreeRowCountEst(BtCursor*);
+4 -3
View File
@@ -381,7 +381,7 @@ struct Btree {
**
** Fields in this structure are accessed under the BtShared.mutex
** mutex, except for nRef and pNext which are accessed under the
** global SQLITE_MUTEX_STATIC_MASTER mutex. The pPager field
** global SQLITE_MUTEX_STATIC_MAIN mutex. The pPager field
** may not be modified once it is initially set as long as nRef>0.
** The pSchema field may be set once under BtShared.mutex and
** thereafter is unchanged as long as nRef>0.
@@ -679,9 +679,10 @@ struct IntegrityCk {
Pgno nPage; /* Number of pages in the database */
int mxErr; /* Stop accumulating errors when this reaches zero */
int nErr; /* Number of messages written to zErrMsg so far */
int mallocFailed; /* A memory allocation error has occurred */
int bOomFault; /* A memory allocation error has occurred */
const char *zPfx; /* Error message prefix */
int v1, v2; /* Values for up to two %d fields in zPfx */
Pgno v1; /* Value for first %u substitution in zPfx */
int v2; /* Value for second %d substitution in zPfx */
StrAccum errMsg; /* Accumulate the error message text here */
u32 *heap; /* Min-heap used for analyzing cell coverage */
sqlite3 *db; /* Database connection running the check */
+130 -82
View File
@@ -31,7 +31,7 @@
*/
struct TableLock {
int iDb; /* The database containing the table to be locked */
int iTab; /* The root page of the table to be locked */
Pgno iTab; /* The root page of the table to be locked */
u8 isWriteLock; /* True for write lock. False for a read lock */
const char *zLockName; /* Name of the table */
};
@@ -49,7 +49,7 @@ struct TableLock {
void sqlite3TableLock(
Parse *pParse, /* Parsing context */
int iDb, /* Index of the database containing the table to lock */
int iTab, /* Root page number of the table to be locked */
Pgno iTab, /* Root page number of the table to be locked */
u8 isWriteLock, /* True for a write lock */
const char *zName /* Name of the table to be locked */
){
@@ -253,7 +253,7 @@ void sqlite3FinishCoding(Parse *pParse){
** outermost parser.
**
** Not everything is nestable. This facility is designed to permit
** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
** INSERT, UPDATE, and DELETE operations against the schema table. Use
** care if you decide to try to use this routine for some other purposes.
*/
void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
@@ -335,9 +335,21 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
}
}
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p==0 && i==1 && sqlite3StrICmp(zName, MASTER_NAME)==0 ){
/* All temp.sqlite_master to be an alias for sqlite_temp_master */
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash, TEMP_MASTER_NAME);
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( i==1 ){
if( sqlite3StrICmp(zName+7, &ALT_TEMP_SCHEMA_TABLE[7])==0
|| sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0
|| sqlite3StrICmp(zName+7, &DFLT_SCHEMA_TABLE[7])==0
){
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
DFLT_TEMP_SCHEMA_TABLE);
}
}else{
if( sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash,
DFLT_SCHEMA_TABLE);
}
}
}
}else{
/* Match against TEMP first */
@@ -352,6 +364,14 @@ Table *sqlite3FindTable(sqlite3 *db, const char *zName, const char *zDatabase){
p = sqlite3HashFind(&db->aDb[i].pSchema->tblHash, zName);
if( p ) break;
}
if( p==0 && sqlite3StrNICmp(zName, "sqlite_", 7)==0 ){
if( sqlite3StrICmp(zName+7, &ALT_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[0].pSchema->tblHash, DFLT_SCHEMA_TABLE);
}else if( sqlite3StrICmp(zName+7, &ALT_TEMP_SCHEMA_TABLE[7])==0 ){
p = sqlite3HashFind(&db->aDb[1].pSchema->tblHash,
DFLT_TEMP_SCHEMA_TABLE);
}
}
}
return p;
}
@@ -743,13 +763,13 @@ char *sqlite3NameFromToken(sqlite3 *db, Token *pName){
}
/*
** Open the sqlite_master table stored in database number iDb for
** Open the sqlite_schema table stored in database number iDb for
** writing. The table is opened using cursor 0.
*/
void sqlite3OpenMasterTable(Parse *p, int iDb){
void sqlite3OpenSchemaTable(Parse *p, int iDb){
Vdbe *v = sqlite3GetVdbe(p);
sqlite3TableLock(p, iDb, MASTER_ROOT, 1, MASTER_NAME);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, MASTER_ROOT, iDb, 5);
sqlite3TableLock(p, iDb, SCHEMA_ROOT, 1, DFLT_SCHEMA_TABLE);
sqlite3VdbeAddOp4Int(v, OP_OpenWrite, 0, SCHEMA_ROOT, iDb, 5);
if( p->nTab==0 ){
p->nTab = 1;
}
@@ -857,7 +877,7 @@ int sqlite3WritableSchema(sqlite3 *db){
** "sqlite_" (in upper, lower or mixed case). This portion of the namespace
** is reserved for internal use.
**
** When parsing the sqlite_master table, this routine also checks to
** When parsing the sqlite_schema table, this routine also checks to
** make sure the "type", "name", and "tbl_name" columns are consistent
** with the SQL.
*/
@@ -868,7 +888,10 @@ int sqlite3CheckObjectName(
const char *zTblName /* Parent table name for triggers and indexes */
){
sqlite3 *db = pParse->db;
if( sqlite3WritableSchema(db) || db->init.imposterTable ){
if( sqlite3WritableSchema(db)
|| db->init.imposterTable
|| !sqlite3Config.bExtraSchemaChecks
){
/* Skip these error checks for writable_schema=ON */
return SQLITE_OK;
}
@@ -877,10 +900,8 @@ int sqlite3CheckObjectName(
|| sqlite3_stricmp(zName, db->init.azInit[1])
|| sqlite3_stricmp(zTblName, db->init.azInit[2])
){
if( sqlite3Config.bExtraSchemaChecks ){
sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
return SQLITE_ERROR;
}
sqlite3ErrorMsg(pParse, ""); /* corruptSchema() will supply the error */
return SQLITE_ERROR;
}
}else{
if( (pParse->nested==0 && 0==sqlite3StrNICmp(zName, "sqlite_", 7))
@@ -1029,7 +1050,7 @@ void sqlite3StartTable(
Token *pName; /* Unqualified name of the table to create */
if( db->init.busy && db->init.newTnum==1 ){
/* Special case: Parsing the sqlite_master or sqlite_temp_master schema */
/* Special case: Parsing the sqlite_schema or sqlite_temp_schema schema */
iDb = db->init.iDb;
zName = sqlite3DbStrDup(db, SCHEMA_TABLE(iDb));
pName = pName1;
@@ -1135,7 +1156,7 @@ void sqlite3StartTable(
#endif
/* Begin generating the code that will insert the table record into
** the SQLITE_MASTER table. Note in particular that we must go ahead
** the schema table. Note in particular that we must go ahead
** and allocate the record number for the table entry now. Before any
** PRIMARY KEY or UNIQUE keywords are parsed. Those keywords will cause
** indices to be created and the table record must come before the
@@ -1171,7 +1192,7 @@ void sqlite3StartTable(
sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, BTREE_TEXT_ENCODING, ENC(db));
sqlite3VdbeJumpHere(v, addr1);
/* This just creates a place-holder record in the sqlite_master table.
/* This just creates a place-holder record in the sqlite_schema table.
** The record created does not contain anything yet. It will be replaced
** by the real entry in code generated at sqlite3EndTable().
**
@@ -1189,7 +1210,7 @@ void sqlite3StartTable(
pParse->addrCrTab =
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, reg2, BTREE_INTKEY);
}
sqlite3OpenMasterTable(pParse, iDb);
sqlite3OpenSchemaTable(pParse, iDb);
sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
sqlite3VdbeAddOp4(v, OP_Blob, 6, reg3, 0, nullRow, P4_STATIC);
sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
@@ -1999,9 +2020,9 @@ static void recomputeColumnsNotIndexed(Index *pIdx){
** (1) Set all columns of the PRIMARY KEY schema object to be NOT NULL.
** (2) Convert P3 parameter of the OP_CreateBtree from BTREE_INTKEY
** into BTREE_BLOBKEY.
** (3) Bypass the creation of the sqlite_master table entry
** (3) Bypass the creation of the sqlite_schema table entry
** for the PRIMARY KEY as the primary key index is now
** identified by the sqlite_master table entry of the table itself.
** identified by the sqlite_schema table entry of the table itself.
** (4) Set the Index.tnum of the PRIMARY KEY Index object in the
** schema to the rootpage from the main table.
** (5) Add all table columns to the PRIMARY KEY Index object
@@ -2088,13 +2109,13 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
if( !db->init.imposterTable ) pPk->uniqNotNull = 1;
nPk = pPk->nColumn = pPk->nKeyCol;
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_master
/* Bypass the creation of the PRIMARY KEY btree and the sqlite_schema
** table entry. This is only required if currently generating VDBE
** code for a CREATE TABLE (not when parsing one as part of reading
** a database schema). */
if( v && pPk->tnum>0 ){
assert( db->init.busy==0 );
sqlite3VdbeChangeOpcode(v, pPk->tnum, OP_Goto);
sqlite3VdbeChangeOpcode(v, (int)pPk->tnum, OP_Goto);
}
/* The root page of the PRIMARY KEY is the table root page */
@@ -2236,12 +2257,12 @@ static void markExprListImmutable(ExprList *pList){
** is added to the internal hash tables, assuming no errors have
** occurred.
**
** An entry for the table is made in the master table on disk, unless
** An entry for the table is made in the schema table on disk, unless
** this is a temporary table or db->init.busy==1. When db->init.busy==1
** it means we are reading the sqlite_master table because we just
** connected to the database or because the sqlite_master table has
** it means we are reading the sqlite_schema table because we just
** connected to the database or because the sqlite_schema table has
** recently changed, so the entry for this table already exists in
** the sqlite_master table. We do not want to create it again.
** the sqlite_schema table. We do not want to create it again.
**
** If the pSelect argument is not NULL, it means that this routine
** was called to create a table generated from a
@@ -2272,12 +2293,12 @@ void sqlite3EndTable(
}
/* If the db->init.busy is 1 it means we are reading the SQL off the
** "sqlite_master" or "sqlite_temp_master" table on the disk.
** "sqlite_schema" or "sqlite_temp_schema" table on the disk.
** So do not write to the disk again. Extract the root page number
** for the table from the db->init.newTnum field. (The page number
** should have been put there by the sqliteOpenCb routine.)
**
** If the root page number is 1, that means this is the sqlite_master
** If the root page number is 1, that means this is the sqlite_schema
** table itself. So mark it read-only.
*/
if( db->init.busy ){
@@ -2364,7 +2385,7 @@ void sqlite3EndTable(
}
/* If not initializing, then create a record for the new table
** in the SQLITE_MASTER table of the database.
** in the schema table of the database.
**
** If this is a TEMPORARY table, write the entry into the auxiliary
** file instead of into the main database file.
@@ -2466,14 +2487,14 @@ void sqlite3EndTable(
}
/* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
** schema table. We just need to update that slot with all
** the information we've collected.
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s "
"SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
"WHERE rowid=#%d",
db->aDb[iDb].zDbSName, MASTER_NAME,
"UPDATE %Q." DFLT_SCHEMA_TABLE
" SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q"
" WHERE rowid=#%d",
db->aDb[iDb].zDbSName,
zType,
p->zName,
p->zName,
@@ -2601,7 +2622,7 @@ void sqlite3CreateView(
sEnd.z = &z[n-1];
sEnd.n = 1;
/* Use sqlite3EndTable() to add the view to the SQLITE_MASTER table */
/* Use sqlite3EndTable() to add the view to the schema table */
sqlite3EndTable(pParse, 0, &sEnd, 0, 0);
create_view_fail:
@@ -2682,10 +2703,8 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
assert( pTable->pSelect );
pSel = sqlite3SelectDup(db, pTable->pSelect, 0);
if( pSel ){
#ifndef SQLITE_OMIT_ALTERTABLE
u8 eParseMode = pParse->eParseMode;
pParse->eParseMode = PARSE_MODE_NORMAL;
#endif
n = pParse->nTab;
sqlite3SrcListAssignCursors(pParse, pSel->pSrc);
pTable->nCol = -1;
@@ -2733,9 +2752,7 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
sqlite3DeleteTable(db, pSelTab);
sqlite3SelectDelete(db, pSel);
EnableLookaside;
#ifndef SQLITE_OMIT_ALTERTABLE
pParse->eParseMode = eParseMode;
#endif
} else {
nErr++;
}
@@ -2790,7 +2807,7 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
** in order to be certain that we got the right one.
*/
#ifndef SQLITE_OMIT_AUTOVACUUM
void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
void sqlite3RootPageMoved(sqlite3 *db, int iDb, Pgno iFrom, Pgno iTo){
HashElem *pElem;
Hash *pHash;
Db *pDb;
@@ -2816,7 +2833,7 @@ void sqlite3RootPageMoved(sqlite3 *db, int iDb, int iFrom, int iTo){
/*
** Write code to erase the table with root-page iTable from database iDb.
** Also write code to modify the sqlite_master table and internal schema
** Also write code to modify the sqlite_schema table and internal schema
** if a root-page of another table is moved by the btree-layer whilst
** erasing iTable (this can happen with an auto-vacuum database).
*/
@@ -2829,7 +2846,7 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
#ifndef SQLITE_OMIT_AUTOVACUUM
/* OP_Destroy stores an in integer r1. If this integer
** is non-zero, then it is the root page number of a table moved to
** location iTable. The following code modifies the sqlite_master table to
** location iTable. The following code modifies the sqlite_schema table to
** reflect this.
**
** The "#NNN" in the SQL is a special constant that means whatever value
@@ -2837,15 +2854,16 @@ static void destroyRootPage(Parse *pParse, int iTable, int iDb){
** token for additional information.
*/
sqlite3NestedParse(pParse,
"UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zDbSName, MASTER_NAME, iTable, r1, r1);
"UPDATE %Q." DFLT_SCHEMA_TABLE
" SET rootpage=%d WHERE #%d AND rootpage=#%d",
pParse->db->aDb[iDb].zDbSName, iTable, r1, r1);
#endif
sqlite3ReleaseTempReg(pParse, r1);
}
/*
** Write VDBE code to erase table pTab and all associated indices on disk.
** Code to update the sqlite_master tables and internal schema definitions
** Code to update the sqlite_schema tables and internal schema definitions
** in case a root-page belonging to another table is moved by the btree layer
** is also added (this can happen with an auto-vacuum database).
*/
@@ -2866,18 +2884,18 @@ static void destroyTable(Parse *pParse, Table *pTab){
** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
** a free-list page.
*/
int iTab = pTab->tnum;
int iDestroyed = 0;
Pgno iTab = pTab->tnum;
Pgno iDestroyed = 0;
while( 1 ){
Index *pIdx;
int iLargest = 0;
Pgno iLargest = 0;
if( iDestroyed==0 || iTab<iDestroyed ){
iLargest = iTab;
}
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int iIdx = pIdx->tnum;
Pgno iIdx = pIdx->tnum;
assert( pIdx->pSchema==pTab->pSchema );
if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
iLargest = iIdx;
@@ -2938,8 +2956,8 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
#endif
/* Drop all triggers associated with the table being dropped. Code
** is generated to remove entries from sqlite_master and/or
** sqlite_temp_master if required.
** is generated to remove entries from sqlite_schema and/or
** sqlite_temp_schema if required.
*/
pTrigger = sqlite3TriggerList(pParse, pTab);
while( pTrigger ){
@@ -2963,16 +2981,17 @@ void sqlite3CodeDropTable(Parse *pParse, Table *pTab, int iDb, int isView){
}
#endif
/* Drop all SQLITE_MASTER table and index entries that refer to the
** table. The program name loops through the master table and deletes
/* Drop all entries in the schema table that refer to the
** table. The program name loops through the schema table and deletes
** every row that refers to a table of the same name as the one being
** dropped. Triggers are handled separately because a trigger can be
** created in the temp database that refers to a table in another
** database.
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
pDb->zDbSName, MASTER_NAME, pTab->zName);
"DELETE FROM %Q." DFLT_SCHEMA_TABLE
" WHERE tbl_name=%Q and type!='trigger'",
pDb->zDbSName, pTab->zName);
if( !isView && !IsVirtual(pTab) ){
destroyTable(pParse, pTab);
}
@@ -3108,7 +3127,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
}
#endif
/* Generate code to remove the table from the master table
/* Generate code to remove the table from the schema table
** on disk.
*/
v = sqlite3GetVdbe(pParse);
@@ -3299,7 +3318,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
int iSorter; /* Cursor opened by OpenSorter (if in use) */
int addr1; /* Address of top of loop */
int addr2; /* Address to jump to for next iteration */
int tnum; /* Root page of index */
Pgno tnum; /* Root page of index */
int iPartIdxLabel; /* Jump to this label to skip a row */
Vdbe *v; /* Generate code into this virtual machine */
KeyInfo *pKey; /* KeyInfo for index */
@@ -3320,7 +3339,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
v = sqlite3GetVdbe(pParse);
if( v==0 ) return;
if( memRootPage>=0 ){
tnum = memRootPage;
tnum = (Pgno)memRootPage;
}else{
tnum = pIndex->tnum;
}
@@ -3345,7 +3364,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb,
sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, (int)tnum, iDb,
(char *)pKey, P4_KEYINFO);
sqlite3VdbeChangeP5(v, OPFLAG_BULKCSR|((memRootPage>=0)?OPFLAG_P2ISREG:0));
@@ -3562,10 +3581,7 @@ void sqlite3CreateIndex(
#if SQLITE_USER_AUTHENTICATION
&& sqlite3UserAuthTable(pTab->zName)==0
#endif
#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX
&& sqlite3StrICmp(&pTab->zName[7],"master")!=0
#endif
){
){
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
goto exit_create_index;
}
@@ -3587,7 +3603,7 @@ void sqlite3CreateIndex(
** index or table with the same name.
**
** Exception: If we are reading the names of permanent indices from the
** sqlite_master table (because some other process changed the schema) and
** sqlite_schema table (because some other process changed the schema) and
** one of the index names collides with the name of a temporary table or
** index, then we will continue to process this index.
**
@@ -3931,8 +3947,8 @@ void sqlite3CreateIndex(
/* If this is the initial CREATE INDEX statement (or CREATE TABLE if the
** index is an implied index for a UNIQUE or PRIMARY KEY constraint) then
** emit code to allocate the index rootpage on disk and make an entry for
** the index in the sqlite_master table and populate the index with
** content. But, do not do this if we are simply reading the sqlite_master
** the index in the sqlite_schema table and populate the index with
** content. But, do not do this if we are simply reading the sqlite_schema
** table to parse the schema, or if this index is the PRIMARY KEY index
** of a WITHOUT ROWID table.
**
@@ -3957,7 +3973,7 @@ void sqlite3CreateIndex(
** PRIMARY KEY and the table is actually a WITHOUT ROWID table. In
** that case the convertToWithoutRowidTable() routine will replace
** the Noop with a Goto to jump over the VDBE code generated below. */
pIndex->tnum = sqlite3VdbeAddOp0(v, OP_Noop);
pIndex->tnum = (Pgno)sqlite3VdbeAddOp0(v, OP_Noop);
sqlite3VdbeAddOp3(v, OP_CreateBtree, iDb, iMem, BTREE_BLOBKEY);
/* Gather the complete text of the CREATE INDEX statement into
@@ -3976,11 +3992,11 @@ void sqlite3CreateIndex(
zStmt = 0;
}
/* Add an entry in sqlite_master for this index
/* Add an entry in sqlite_schema for this index
*/
sqlite3NestedParse(pParse,
"INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zDbSName, MASTER_NAME,
"INSERT INTO %Q." DFLT_SCHEMA_TABLE " VALUES('index',%Q,%Q,#%d,%Q);",
db->aDb[iDb].zDbSName,
pIndex->zName,
pTab->zName,
iMem,
@@ -3999,7 +4015,7 @@ void sqlite3CreateIndex(
sqlite3VdbeAddOp2(v, OP_Expire, 0, 1);
}
sqlite3VdbeJumpHere(v, pIndex->tnum);
sqlite3VdbeJumpHere(v, (int)pIndex->tnum);
}
}
if( db->init.busy || pTblName==0 ){
@@ -4056,9 +4072,10 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
/* 10, 9, 8, 7, 6 */
LogEst aVal[] = { 33, 32, 30, 28, 26 };
/* 10, 9, 8, 7, 6 */
static const LogEst aVal[] = { 33, 32, 30, 28, 26 };
LogEst *a = pIdx->aiRowLogEst;
LogEst x;
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
int i;
@@ -4067,10 +4084,21 @@ void sqlite3DefaultRowEst(Index *pIdx){
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table, or half the number of rows in the table
** for a partial index. But do not let the estimate drop below 10. */
a[0] = pIdx->pTable->nRowLogEst;
if( pIdx->pPartIdxWhere!=0 ) a[0] -= 10; assert( 10==sqlite3LogEst(2) );
if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
** for a partial index.
**
** 2020-05-27: If some of the stat data is coming from the sqlite_stat1
** table but other parts we are having to guess at, then do not let the
** estimated number of rows in the table be less than 1000 (LogEst 99).
** Failure to do this can cause the indexes for which we do not have
** stat1 data to be ignored by the query planner.
*/
x = pIdx->pTable->nRowLogEst;
assert( 99==sqlite3LogEst(1000) );
if( x<99 ){
pIdx->pTable->nRowLogEst = x = 99;
}
if( pIdx->pPartIdxWhere!=0 ) x -= 10; assert( 10==sqlite3LogEst(2) );
a[0] = x;
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
** 6 and each subsequent value (if any) is 5. */
@@ -4133,13 +4161,13 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
}
#endif
/* Generate code to remove the index and from the master table */
/* Generate code to remove the index and from the schema table */
v = sqlite3GetVdbe(pParse);
if( v ){
sqlite3BeginWriteOperation(pParse, 1, iDb);
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE name=%Q AND type='index'",
db->aDb[iDb].zDbSName, MASTER_NAME, pIndex->zName
"DELETE FROM %Q." DFLT_SCHEMA_TABLE " WHERE name=%Q AND type='index'",
db->aDb[iDb].zDbSName, pIndex->zName
);
sqlite3ClearStatTables(pParse, iDb, "idx", pIndex->zName);
sqlite3ChangeCookie(pParse, iDb);
@@ -4538,6 +4566,26 @@ void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pIndexedBy){
}
}
/*
** Append the contents of SrcList p2 to SrcList p1 and return the resulting
** SrcList. Or, if an error occurs, return NULL. In all cases, p1 and p2
** are deleted by this function.
*/
SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2){
assert( p1 && p1->nSrc==1 );
if( p2 ){
SrcList *pNew = sqlite3SrcListEnlarge(pParse, p1, p2->nSrc, 1);
if( pNew==0 ){
sqlite3SrcListDelete(pParse->db, p2);
}else{
p1 = pNew;
memcpy(&p1->a[1], p2->a, p2->nSrc*sizeof(struct SrcList_item));
sqlite3DbFree(pParse->db, p2);
}
}
return p1;
}
/*
** Add the list of function arguments to the SrcList entry for a
** table-valued-function.
+5 -5
View File
@@ -515,7 +515,7 @@ static int osLocaltime(time_t *t, struct tm *pTm){
#if !HAVE_LOCALTIME_R && !HAVE_LOCALTIME_S
struct tm *pX;
#if SQLITE_THREADSAFE>0
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
sqlite3_mutex_enter(mutex);
pX = localtime(t);
@@ -1112,8 +1112,8 @@ static void strftimeFunc(
case 'm': sqlite3_snprintf(3, &z[j],"%02d",x.M); j+=2; break;
case 'M': sqlite3_snprintf(3, &z[j],"%02d",x.m); j+=2; break;
case 's': {
sqlite3_snprintf(30,&z[j],"%lld",
(i64)(x.iJD/1000 - 21086676*(i64)10000));
i64 iS = (i64)(x.iJD/1000 - 21086676*(i64)10000);
sqlite3Int64ToText(iS, &z[j]);
j += sqlite3Strlen30(&z[j]);
break;
}
@@ -1211,10 +1211,10 @@ static void currentTimeFunc(
#if HAVE_GMTIME_R
pTm = gmtime_r(&t, &sNow);
#else
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
pTm = gmtime(&t);
if( pTm ) memcpy(&sNow, pTm, sizeof(sNow));
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
#endif
if( pTm ){
strftime(zBuf, 20, zFormat, &sNow);
+2 -2
View File
@@ -724,10 +724,10 @@ static int statFilter(
pSql = sqlite3_str_new(pTab->db);
sqlite3_str_appendf(pSql,
"SELECT * FROM ("
"SELECT 'sqlite_master' AS name,1 AS rootpage,'table' AS type"
"SELECT 'sqlite_schema' AS name,1 AS rootpage,'table' AS type"
" UNION ALL "
"SELECT name,rootpage,type"
" FROM \"%w\".sqlite_master WHERE rootpage!=0)",
" FROM \"%w\".sqlite_schema WHERE rootpage!=0)",
pTab->db->aDb[pCsr->iDb].zDbSName);
if( zName ){
sqlite3_str_appendf(pSql, "WHERE name=%Q", zName);
+2 -2
View File
@@ -31,7 +31,7 @@
Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
struct SrcList_item *pItem = pSrc->a;
Table *pTab;
assert( pItem && pSrc->nSrc==1 );
assert( pItem && pSrc->nSrc>=1 );
pTab = sqlite3LocateTableItem(pParse, 0, pItem);
sqlite3DeleteTable(pParse->db, pItem->pTab);
pItem->pTab = pTab;
@@ -51,7 +51,7 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
** 1) It is a virtual table and no implementation of the xUpdate method
** has been provided
**
** 2) It is a system table (i.e. sqlite_master), this call is not
** 2) It is a system table (i.e. sqlite_schema), this call is not
** part of a nested parse and writable_schema pragma has not
** been specified
**
+35 -34
View File
@@ -52,12 +52,10 @@ char sqlite3ExprAffinity(const Expr *pExpr){
op = pExpr->op;
if( op==TK_SELECT ){
assert( pExpr->flags&EP_xIsSelect );
if( ALWAYS(pExpr->x.pSelect)
&& pExpr->x.pSelect->pEList
&& ALWAYS(pExpr->x.pSelect->pEList->a[0].pExpr)
){
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
assert( pExpr->x.pSelect!=0 );
assert( pExpr->x.pSelect->pEList!=0 );
assert( pExpr->x.pSelect->pEList->a[0].pExpr!=0 );
return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr);
}
if( op==TK_REGISTER ) op = pExpr->op2;
#ifndef SQLITE_OMIT_CAST
@@ -200,7 +198,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, const Expr *pExpr){
&& ALWAYS(!ExprHasProperty(p, EP_xIsSelect))
){
int i;
for(i=0; i<p->x.pList->nExpr; i++){
for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
pNext = p->x.pList->a[i].pExpr;
break;
@@ -1993,10 +1991,10 @@ Expr *sqlite3ExprSimplifiedAndOr(Expr *pExpr){
**
** The sqlite3ExprIsConstantOrFunction() is used for evaluating DEFAULT
** expressions in a CREATE TABLE statement. The Walker.eCode value is 5
** when parsing an existing schema out of the sqlite_master table and 4
** when parsing an existing schema out of the sqlite_schema table and 4
** when processing a new CREATE TABLE statement. A bound parameter raises
** an error for new statements, but is silently converted
** to NULL for existing schemas. This allows sqlite_master tables that
** to NULL for existing schemas. This allows sqlite_schema tables that
** contain a bound parameter because they were generated by older versions
** of SQLite to be parsed by newer versions of SQLite without raising a
** malformed schema error.
@@ -2031,7 +2029,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
if( sqlite3ExprIdToTrueFalse(pExpr) ){
return WRC_Prune;
}
/* Fall thru */
/* no break */ deliberate_fall_through
case TK_COLUMN:
case TK_AGG_FUNCTION:
case TK_AGG_COLUMN:
@@ -2045,7 +2043,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
return WRC_Continue;
}
/* Fall through */
/* no break */ deliberate_fall_through
case TK_IF_NULL_ROW:
case TK_REGISTER:
case TK_DOT:
@@ -2058,7 +2056,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
if( pWalker->eCode==5 ){
/* Silently convert bound parameters that appear inside of CREATE
** statements into a NULL when parsing the CREATE statement text out
** of the sqlite_master table */
** of the sqlite_schema table */
pExpr->op = TK_NULL;
}else if( pWalker->eCode==4 ){
/* A bound parameter in a CREATE statement that originates from
@@ -2066,7 +2064,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
pWalker->eCode = 0;
return WRC_Abort;
}
/* Fall through */
/* no break */ deliberate_fall_through
default:
testcase( pExpr->op==TK_SELECT ); /* sqlite3SelectWalkFail() disallows */
testcase( pExpr->op==TK_EXISTS ); /* sqlite3SelectWalkFail() disallows */
@@ -2191,12 +2189,12 @@ int sqlite3ExprIsConstantOrGroupBy(Parse *pParse, Expr *p, ExprList *pGroupBy){
** the expression is constant or a function call with constant arguments.
** Return and 0 if there are any variables.
**
** isInit is true when parsing from sqlite_master. isInit is false when
** isInit is true when parsing from sqlite_schema. isInit is false when
** processing a new CREATE TABLE statement. When isInit is true, parameters
** (such as ? or $abc) in the expression are converted into NULL. When
** isInit is false, parameters raise an error. Parameters should not be
** allowed in a CREATE TABLE statement, but some legacy versions of SQLite
** allowed it, so we need to support it when reading sqlite_master for
** allowed it, so we need to support it when reading sqlite_schema for
** backwards compatibility.
**
** If isInit is true, set EP_FromDDL on every TK_FUNCTION node.
@@ -2559,7 +2557,7 @@ int sqlite3FindInIndex(
if( pParse->nErr==0 && (p = isCandidateForInOpt(pX))!=0 ){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
i16 iDb; /* Database idx for pTab */
int iDb; /* Database idx for pTab */
ExprList *pEList = p->pEList;
int nExpr = pEList->nExpr;
@@ -2570,6 +2568,7 @@ int sqlite3FindInIndex(
/* Code an OP_Transaction and OP_TableLock for <table>. */
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
assert( iDb>=0 && iDb<SQLITE_MAX_ATTACHED );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -3803,10 +3802,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
int p5 = 0;
assert( target>0 && target<=pParse->nMem );
if( v==0 ){
assert( pParse->db->mallocFailed );
return 0;
}
assert( v!=0 );
expr_code_doover:
if( pExpr==0 ){
@@ -3840,6 +3836,7 @@ expr_code_doover:
return target;
}
/* Otherwise, fall thru into the TK_COLUMN case */
/* no break */ deliberate_fall_through
}
case TK_COLUMN: {
int iTab = pExpr->iTable;
@@ -4272,7 +4269,9 @@ expr_code_doover:
int nCol;
testcase( op==TK_EXISTS );
testcase( op==TK_SELECT );
if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
if( pParse->db->mallocFailed ){
return 0;
}else if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
sqlite3SubselectError(pParse, nCol, 1);
}else{
return sqlite3CodeSubselect(pParse, pExpr);
@@ -4636,9 +4635,10 @@ void sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) );
assert( target>0 && target<=pParse->nMem );
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
assert( pParse->pVdbe!=0 || pParse->db->mallocFailed );
if( inReg!=target && pParse->pVdbe ){
if( pParse->pVdbe==0 ) return;
inReg = sqlite3ExprCodeTarget(pParse, pExpr, target);
if( inReg!=target ){
u8 op;
if( ExprHasProperty(pExpr,EP_Subquery) ){
op = OP_Copy;
@@ -4902,7 +4902,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( op==TK_ISNOT );
op = (op==TK_IS) ? TK_EQ : TK_NE;
jumpIfNull = SQLITE_NULLEQ;
/* Fall thru */
/* no break */ deliberate_fall_through
case TK_LT:
case TK_LE:
case TK_GT:
@@ -5078,7 +5078,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( pExpr->op==TK_ISNOT );
op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
jumpIfNull = SQLITE_NULLEQ;
/* Fall thru */
/* no break */ deliberate_fall_through
case TK_LT:
case TK_LE:
case TK_GT:
@@ -5390,13 +5390,13 @@ static int exprImpliesNotNull(
case TK_RSHIFT:
case TK_CONCAT:
seenNot = 1;
/* Fall thru */
/* no break */ deliberate_fall_through
case TK_STAR:
case TK_REM:
case TK_BITAND:
case TK_SLASH: {
if( exprImpliesNotNull(pParse, p->pRight, pNN, iTab, seenNot) ) return 1;
/* Fall thru into the next case */
/* no break */ deliberate_fall_through
}
case TK_SPAN:
case TK_COLLATE:
@@ -5545,6 +5545,7 @@ static int impliesNotNullRow(Walker *pWalker, Expr *pExpr){
){
return WRC_Prune;
}
/* no break */ deliberate_fall_through
}
default:
return WRC_Continue;
@@ -5757,20 +5758,20 @@ static int agginfoPersistExprCb(Walker *pWalker, Expr *pExpr){
assert( pExpr->op==TK_AGG_COLUMN || pExpr->op==TK_AGG_FUNCTION );
if( pExpr->op==TK_AGG_COLUMN ){
assert( iAgg>=0 && iAgg<pAggInfo->nColumn );
if( pAggInfo->aCol[iAgg].pExpr==pExpr ){
if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aCol[iAgg].pExpr = pExpr;
pAggInfo->aCol[iAgg].pCExpr = pExpr;
pParse->pConstExpr =
sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
}
}
}else{
assert( iAgg>=0 && iAgg<pAggInfo->nFunc );
if( pAggInfo->aFunc[iAgg].pExpr==pExpr ){
if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){
pExpr = sqlite3ExprDup(db, pExpr, 0);
if( pExpr ){
pAggInfo->aFunc[iAgg].pExpr = pExpr;
pAggInfo->aFunc[iAgg].pFExpr = pExpr;
pParse->pConstExpr =
sqlite3ExprListAppend(pParse, pParse->pConstExpr, pExpr);
}
@@ -5872,7 +5873,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
pCol->iColumn = pExpr->iColumn;
pCol->iMem = ++pParse->nMem;
pCol->iSorterColumn = -1;
pCol->pExpr = pExpr;
pCol->pCExpr = pExpr;
if( pAggInfo->pGroupBy ){
int j, n;
ExprList *pGB = pAggInfo->pGroupBy;
@@ -5915,7 +5916,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
*/
struct AggInfo_func *pItem = pAggInfo->aFunc;
for(i=0; i<pAggInfo->nFunc; i++, pItem++){
if( sqlite3ExprCompare(0, pItem->pExpr, pExpr, -1)==0 ){
if( sqlite3ExprCompare(0, pItem->pFExpr, pExpr, -1)==0 ){
break;
}
}
@@ -5927,7 +5928,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){
if( i>=0 ){
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
pItem = &pAggInfo->aFunc[i];
pItem->pExpr = pExpr;
pItem->pFExpr = pExpr;
pItem->iMem = ++pParse->nMem;
assert( !ExprHasProperty(pExpr, EP_IntValue) );
pItem->pFunc = sqlite3FindFunction(pParse->db,
+1
View File
@@ -1359,6 +1359,7 @@ static Trigger *fkActionTrigger(
pStep->op = TK_DELETE;
break;
}
/* no break */ deliberate_fall_through
default:
pStep->op = TK_UPDATE;
}
+5
View File
@@ -300,6 +300,11 @@ sqlite3_uint64 sqlite3NProfileCnt = 0;
int sqlite3PendingByte = 0x40000000;
#endif
/*
** Flags for select tracing and the ".selecttrace" macro of the CLI
*/
u32 sqlite3_unsupported_selecttrace = 0;
#include "opcodes.h"
/*
** Properties of opcodes. The OPFLG_INITIALIZER macro is
+6 -6
View File
@@ -180,7 +180,7 @@ static int readsTable(Parse *p, int iDb, Table *pTab){
assert( pOp!=0 );
if( pOp->opcode==OP_OpenRead && pOp->p3==iDb ){
Index *pIndex;
int tnum = pOp->p2;
Pgno tnum = pOp->p2;
if( tnum==pTab->tnum ){
return 1;
}
@@ -1612,7 +1612,7 @@ void sqlite3GenerateConstraintChecks(
}
case OE_Abort:
sqlite3MayAbort(pParse);
/* Fall through */
/* no break */ deliberate_fall_through
case OE_Rollback:
case OE_Fail: {
char *zMsg = sqlite3MPrintf(db, "%s.%s", pTab->zName,
@@ -1840,7 +1840,7 @@ void sqlite3GenerateConstraintChecks(
switch( onError ){
default: {
onError = OE_Abort;
/* Fall thru into the next case */
/* no break */ deliberate_fall_through
}
case OE_Rollback:
case OE_Abort:
@@ -1901,7 +1901,7 @@ void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_UPSERT
case OE_Update: {
sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, 0, iDataCur);
/* Fall through */
/* no break */ deliberate_fall_through
}
#endif
case OE_Ignore: {
@@ -2122,7 +2122,7 @@ void sqlite3GenerateConstraintChecks(
#ifndef SQLITE_OMIT_UPSERT
case OE_Update: {
sqlite3UpsertDoUpdate(pParse, pUpsert, pTab, pIdx, iIdxCur+ix);
/* Fall through */
/* no break */ deliberate_fall_through
}
#endif
case OE_Ignore: {
@@ -2610,7 +2610,7 @@ static int xferOptimization(
return 0; /* FROM clause does not contain a real table */
}
if( pSrc->tnum==pDest->tnum && pSrc->pSchema==pDest->pSchema ){
testcase( pSrc!=pDest ); /* Possible due to bad sqlite_master.rootpage */
testcase( pSrc!=pDest ); /* Possible due to bad sqlite_schema.rootpage */
return 0; /* tab1 and tab2 may not be the same table */
}
if( HasRowid(pDest)!=HasRowid(pSrc) ){
+5 -5
View File
@@ -689,7 +689,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
** The following object holds the list of automatically loaded
** extensions.
**
** This list is shared across threads. The SQLITE_MUTEX_STATIC_MASTER
** This list is shared across threads. The SQLITE_MUTEX_STATIC_MAIN
** mutex must be held while accessing this list.
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
@@ -731,7 +731,7 @@ int sqlite3_auto_extension(
{
u32 i;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
wsdAutoextInit;
sqlite3_mutex_enter(mutex);
@@ -769,7 +769,7 @@ int sqlite3_cancel_auto_extension(
void (*xInit)(void)
){
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
int i;
int n = 0;
@@ -796,7 +796,7 @@ void sqlite3_reset_auto_extension(void){
#endif
{
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
wsdAutoextInit;
sqlite3_mutex_enter(mutex);
@@ -826,7 +826,7 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){
for(i=0; go; i++){
char *zErrmsg;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
#ifdef SQLITE_OMIT_LOAD_EXTENSION
const sqlite3_api_routines *pThunk = 0;
+19 -13
View File
@@ -100,7 +100,7 @@ static int (*const sqlite3BuiltinExtensions[])(sqlite3*) = {
#ifndef SQLITE_AMALGAMATION
/* IMPLEMENTATION-OF: R-46656-45156 The sqlite3_version[] string constant
** contains the text of SQLITE_VERSION macro.
** contains the text of SQLITE_VERSION macro.
*/
const char sqlite3_version[] = SQLITE_VERSION;
#endif
@@ -201,7 +201,7 @@ char *sqlite3_data_directory = 0;
** without blocking.
*/
int sqlite3_initialize(void){
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
int rc; /* Result code */
#ifdef SQLITE_EXTRA_INIT
int bRunExtraInit = 0; /* Extra initialization needed */
@@ -241,13 +241,13 @@ int sqlite3_initialize(void){
if( rc ) return rc;
/* Initialize the malloc() system and the recursive pInitMutex mutex.
** This operation is protected by the STATIC_MASTER mutex. Note that
** This operation is protected by the STATIC_MAIN mutex. Note that
** MutexAlloc() is called for a static mutex prior to initializing the
** malloc subsystem - this implies that the allocation of a static
** mutex must not require support from the malloc subsystem.
*/
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
sqlite3_mutex_enter(pMaster);
MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(pMainMtx);
sqlite3GlobalConfig.isMutexInit = 1;
if( !sqlite3GlobalConfig.isMallocInit ){
rc = sqlite3MallocInit();
@@ -265,7 +265,7 @@ int sqlite3_initialize(void){
if( rc==SQLITE_OK ){
sqlite3GlobalConfig.nRefInitMutex++;
}
sqlite3_mutex_leave(pMaster);
sqlite3_mutex_leave(pMainMtx);
/* If rc is not SQLITE_OK at this point, then either the malloc
** subsystem could not be initialized or the system failed to allocate
@@ -326,14 +326,14 @@ int sqlite3_initialize(void){
/* Go back under the static mutex and clean up the recursive
** mutex to prevent a resource leak.
*/
sqlite3_mutex_enter(pMaster);
sqlite3_mutex_enter(pMainMtx);
sqlite3GlobalConfig.nRefInitMutex--;
if( sqlite3GlobalConfig.nRefInitMutex<=0 ){
assert( sqlite3GlobalConfig.nRefInitMutex==0 );
sqlite3_mutex_free(sqlite3GlobalConfig.pInitMutex);
sqlite3GlobalConfig.pInitMutex = 0;
}
sqlite3_mutex_leave(pMaster);
sqlite3_mutex_leave(pMainMtx);
/* The following is just a sanity check to make sure SQLite has
** been compiled correctly. It is important to run this code, but
@@ -1202,7 +1202,7 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
}
sqlite3_mutex_enter(db->mutex);
if( db->mTrace & SQLITE_TRACE_CLOSE ){
db->xTrace(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
db->trace.xV2(SQLITE_TRACE_CLOSE, db->pTraceArg, db, 0);
}
/* Force xDisconnect calls on all virtual tables */
@@ -2091,7 +2091,7 @@ void *sqlite3_trace(sqlite3 *db, void(*xTrace)(void*,const char*), void *pArg){
sqlite3_mutex_enter(db->mutex);
pOld = db->pTraceArg;
db->mTrace = xTrace ? SQLITE_TRACE_LEGACY : 0;
db->xTrace = (int(*)(u32,void*,void*,void*))xTrace;
db->trace.xLegacy = xTrace;
db->pTraceArg = pArg;
sqlite3_mutex_leave(db->mutex);
return pOld;
@@ -2115,7 +2115,7 @@ int sqlite3_trace_v2(
if( mTrace==0 ) xTrace = 0;
if( xTrace==0 ) mTrace = 0;
db->mTrace = mTrace;
db->xTrace = xTrace;
db->trace.xV2 = xTrace;
db->pTraceArg = pArg;
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
@@ -3112,7 +3112,7 @@ static int openDatabase(
SQLITE_OPEN_MAIN_JOURNAL |
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_SUBJOURNAL |
SQLITE_OPEN_MASTER_JOURNAL |
SQLITE_OPEN_SUPER_JOURNAL |
SQLITE_OPEN_NOMUTEX |
SQLITE_OPEN_FULLMUTEX |
SQLITE_OPEN_WAL
@@ -4089,8 +4089,14 @@ int sqlite3_test_control(int op, ...){
/* sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, int);
**
** Set or clear a flag that causes SQLite to verify that type, name,
** and tbl_name fields of the sqlite_master table. This is normally
** and tbl_name fields of the sqlite_schema table. This is normally
** on, but it is sometimes useful to turn it off for testing.
**
** 2020-07-22: Disabling EXTRA_SCHEMA_CHECKS also disables the
** verification of rootpage numbers when parsing the schema. This
** is useful to make it easier to reach strange internal error states
** during testing. The EXTRA_SCHEMA_CHECKS setting is always enabled
** in production.
*/
case SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS: {
sqlite3GlobalConfig.bExtraSchemaChecks = va_arg(ap, int);
+2 -4
View File
@@ -719,11 +719,9 @@ char *sqlite3DbStrDup(sqlite3 *db, const char *z){
char *sqlite3DbStrNDup(sqlite3 *db, const char *z, u64 n){
char *zNew;
assert( db!=0 );
if( z==0 ){
return 0;
}
assert( z!=0 || n==0 );
assert( (n&0x7fffffff)==n );
zNew = sqlite3DbMallocRawNN(db, n+1);
zNew = z ? sqlite3DbMallocRawNN(db, n+1) : 0;
if( zNew ){
memcpy(zNew, z, (size_t)n);
zNew[n] = 0;
+3 -3
View File
@@ -379,7 +379,7 @@ void sqlite3MemSetDefault(void){
** Set the "type" of an allocation.
*/
void sqlite3MemdebugSetType(void *p, u8 eType){
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD );
@@ -398,7 +398,7 @@ void sqlite3MemdebugSetType(void *p, u8 eType){
*/
int sqlite3MemdebugHasType(void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
@@ -420,7 +420,7 @@ int sqlite3MemdebugHasType(void *p, u8 eType){
*/
int sqlite3MemdebugNoType(void *p, u8 eType){
int rc = 1;
if( p && sqlite3GlobalConfig.m.xMalloc==sqlite3MemMalloc ){
if( p && sqlite3GlobalConfig.m.xFree==sqlite3MemFree ){
struct MemBlockHdr *pHdr;
pHdr = sqlite3MemsysGetHeader(p);
assert( pHdr->iForeGuard==FOREGUARD ); /* Allocation is valid */
+74 -74
View File
@@ -118,16 +118,16 @@ static SQLITE_WSD struct Mem3Global {
/*
** The minimum amount of free space that we have seen.
*/
u32 mnMaster;
u32 mnKeyBlk;
/*
** iMaster is the index of the master chunk. Most new allocations
** occur off of this chunk. szMaster is the size (in Mem3Blocks)
** of the current master. iMaster is 0 if there is not master chunk.
** The master chunk is not in either the aiHash[] or aiSmall[].
** iKeyBlk is the index of the key chunk. Most new allocations
** occur off of this chunk. szKeyBlk is the size (in Mem3Blocks)
** of the current key chunk. iKeyBlk is 0 if there is no key chunk.
** The key chunk is not in either the aiHash[] or aiSmall[].
*/
u32 iMaster;
u32 szMaster;
u32 iKeyBlk;
u32 szKeyBlk;
/*
** Array of lists of free blocks according to the block size
@@ -263,34 +263,34 @@ static void *memsys3Checkout(u32 i, u32 nBlock){
}
/*
** Carve a piece off of the end of the mem3.iMaster free chunk.
** Return a pointer to the new allocation. Or, if the master chunk
** Carve a piece off of the end of the mem3.iKeyBlk free chunk.
** Return a pointer to the new allocation. Or, if the key chunk
** is not large enough, return 0.
*/
static void *memsys3FromMaster(u32 nBlock){
static void *memsys3FromKeyBlk(u32 nBlock){
assert( sqlite3_mutex_held(mem3.mutex) );
assert( mem3.szMaster>=nBlock );
if( nBlock>=mem3.szMaster-1 ){
/* Use the entire master */
void *p = memsys3Checkout(mem3.iMaster, mem3.szMaster);
mem3.iMaster = 0;
mem3.szMaster = 0;
mem3.mnMaster = 0;
assert( mem3.szKeyBlk>=nBlock );
if( nBlock>=mem3.szKeyBlk-1 ){
/* Use the entire key chunk */
void *p = memsys3Checkout(mem3.iKeyBlk, mem3.szKeyBlk);
mem3.iKeyBlk = 0;
mem3.szKeyBlk = 0;
mem3.mnKeyBlk = 0;
return p;
}else{
/* Split the master block. Return the tail. */
/* Split the key block. Return the tail. */
u32 newi, x;
newi = mem3.iMaster + mem3.szMaster - nBlock;
assert( newi > mem3.iMaster+1 );
mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = nBlock;
mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x |= 2;
newi = mem3.iKeyBlk + mem3.szKeyBlk - nBlock;
assert( newi > mem3.iKeyBlk+1 );
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = nBlock;
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x |= 2;
mem3.aPool[newi-1].u.hdr.size4x = nBlock*4 + 1;
mem3.szMaster -= nBlock;
mem3.aPool[newi-1].u.hdr.prevSize = mem3.szMaster;
x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
if( mem3.szMaster < mem3.mnMaster ){
mem3.mnMaster = mem3.szMaster;
mem3.szKeyBlk -= nBlock;
mem3.aPool[newi-1].u.hdr.prevSize = mem3.szKeyBlk;
x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
if( mem3.szKeyBlk < mem3.mnKeyBlk ){
mem3.mnKeyBlk = mem3.szKeyBlk;
}
return (void*)&mem3.aPool[newi];
}
@@ -304,13 +304,13 @@ static void *memsys3FromMaster(u32 nBlock){
** This routine examines all entries on the given list and tries
** to coalesce each entries with adjacent free chunks.
**
** If it sees a chunk that is larger than mem3.iMaster, it replaces
** the current mem3.iMaster with the new larger chunk. In order for
** this mem3.iMaster replacement to work, the master chunk must be
** If it sees a chunk that is larger than mem3.iKeyBlk, it replaces
** the current mem3.iKeyBlk with the new larger chunk. In order for
** this mem3.iKeyBlk replacement to work, the key chunk must be
** linked into the hash tables. That is not the normal state of
** affairs, of course. The calling routine must link the master
** affairs, of course. The calling routine must link the key
** chunk before invoking this routine, then must unlink the (possibly
** changed) master chunk once this routine has finished.
** changed) key chunk once this routine has finished.
*/
static void memsys3Merge(u32 *pRoot){
u32 iNext, prev, size, i, x;
@@ -337,9 +337,9 @@ static void memsys3Merge(u32 *pRoot){
}else{
size /= 4;
}
if( size>mem3.szMaster ){
mem3.iMaster = i;
mem3.szMaster = size;
if( size>mem3.szKeyBlk ){
mem3.iKeyBlk = i;
mem3.szKeyBlk = size;
}
}
}
@@ -388,26 +388,26 @@ static void *memsys3MallocUnsafe(int nByte){
/* STEP 2:
** Try to satisfy the allocation by carving a piece off of the end
** of the master chunk. This step usually works if step 1 fails.
** of the key chunk. This step usually works if step 1 fails.
*/
if( mem3.szMaster>=nBlock ){
return memsys3FromMaster(nBlock);
if( mem3.szKeyBlk>=nBlock ){
return memsys3FromKeyBlk(nBlock);
}
/* STEP 3:
** Loop through the entire memory pool. Coalesce adjacent free
** chunks. Recompute the master chunk as the largest free chunk.
** chunks. Recompute the key chunk as the largest free chunk.
** Then try again to satisfy the allocation by carving a piece off
** of the end of the master chunk. This step happens very
** of the end of the key chunk. This step happens very
** rarely (we hope!)
*/
for(toFree=nBlock*16; toFree<(mem3.nPool*16); toFree *= 2){
memsys3OutOfMemory(toFree);
if( mem3.iMaster ){
memsys3Link(mem3.iMaster);
mem3.iMaster = 0;
mem3.szMaster = 0;
if( mem3.iKeyBlk ){
memsys3Link(mem3.iKeyBlk);
mem3.iKeyBlk = 0;
mem3.szKeyBlk = 0;
}
for(i=0; i<N_HASH; i++){
memsys3Merge(&mem3.aiHash[i]);
@@ -415,10 +415,10 @@ static void *memsys3MallocUnsafe(int nByte){
for(i=0; i<MX_SMALL-1; i++){
memsys3Merge(&mem3.aiSmall[i]);
}
if( mem3.szMaster ){
memsys3Unlink(mem3.iMaster);
if( mem3.szMaster>=nBlock ){
return memsys3FromMaster(nBlock);
if( mem3.szKeyBlk ){
memsys3Unlink(mem3.iKeyBlk);
if( mem3.szKeyBlk>=nBlock ){
return memsys3FromKeyBlk(nBlock);
}
}
}
@@ -448,23 +448,23 @@ static void memsys3FreeUnsafe(void *pOld){
mem3.aPool[i+size-1].u.hdr.size4x &= ~2;
memsys3Link(i);
/* Try to expand the master using the newly freed chunk */
if( mem3.iMaster ){
while( (mem3.aPool[mem3.iMaster-1].u.hdr.size4x&2)==0 ){
size = mem3.aPool[mem3.iMaster-1].u.hdr.prevSize;
mem3.iMaster -= size;
mem3.szMaster += size;
memsys3Unlink(mem3.iMaster);
x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
/* Try to expand the key using the newly freed chunk */
if( mem3.iKeyBlk ){
while( (mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x&2)==0 ){
size = mem3.aPool[mem3.iKeyBlk-1].u.hdr.prevSize;
mem3.iKeyBlk -= size;
mem3.szKeyBlk += size;
memsys3Unlink(mem3.iKeyBlk);
x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
}
x = mem3.aPool[mem3.iMaster-1].u.hdr.size4x & 2;
while( (mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x&1)==0 ){
memsys3Unlink(mem3.iMaster+mem3.szMaster);
mem3.szMaster += mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.size4x/4;
mem3.aPool[mem3.iMaster-1].u.hdr.size4x = mem3.szMaster*4 | x;
mem3.aPool[mem3.iMaster+mem3.szMaster-1].u.hdr.prevSize = mem3.szMaster;
x = mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x & 2;
while( (mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x&1)==0 ){
memsys3Unlink(mem3.iKeyBlk+mem3.szKeyBlk);
mem3.szKeyBlk += mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.size4x/4;
mem3.aPool[mem3.iKeyBlk-1].u.hdr.size4x = mem3.szKeyBlk*4 | x;
mem3.aPool[mem3.iKeyBlk+mem3.szKeyBlk-1].u.hdr.prevSize = mem3.szKeyBlk;
}
}
}
@@ -560,11 +560,11 @@ static int memsys3Init(void *NotUsed){
mem3.aPool = (Mem3Block *)sqlite3GlobalConfig.pHeap;
mem3.nPool = (sqlite3GlobalConfig.nHeap / sizeof(Mem3Block)) - 2;
/* Initialize the master block. */
mem3.szMaster = mem3.nPool;
mem3.mnMaster = mem3.szMaster;
mem3.iMaster = 1;
mem3.aPool[0].u.hdr.size4x = (mem3.szMaster<<2) + 2;
/* Initialize the key block. */
mem3.szKeyBlk = mem3.nPool;
mem3.mnKeyBlk = mem3.szKeyBlk;
mem3.iKeyBlk = 1;
mem3.aPool[0].u.hdr.size4x = (mem3.szKeyBlk<<2) + 2;
mem3.aPool[mem3.nPool].u.hdr.prevSize = mem3.nPool;
mem3.aPool[mem3.nPool].u.hdr.size4x = 1;
@@ -624,7 +624,7 @@ void sqlite3Memsys3Dump(const char *zFilename){
fprintf(out, "%p %6d bytes checked out\n", &mem3.aPool[i], (size/4)*8-8);
}else{
fprintf(out, "%p %6d bytes free%s\n", &mem3.aPool[i], (size/4)*8-8,
i==mem3.iMaster ? " **master**" : "");
i==mem3.iKeyBlk ? " **key**" : "");
}
}
for(i=0; i<MX_SMALL-1; i++){
@@ -645,9 +645,9 @@ void sqlite3Memsys3Dump(const char *zFilename){
}
fprintf(out, "\n");
}
fprintf(out, "master=%d\n", mem3.iMaster);
fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szMaster*8);
fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnMaster*8);
fprintf(out, "key=%d\n", mem3.iKeyBlk);
fprintf(out, "nowUsed=%d\n", mem3.nPool*8 - mem3.szKeyBlk*8);
fprintf(out, "mxUsed=%d\n", mem3.nPool*8 - mem3.mnKeyBlk*8);
sqlite3_mutex_leave(mem3.mutex);
if( out==stdout ){
fflush(stdout);
+2 -2
View File
@@ -339,12 +339,12 @@ static int memdbOpen(
p->mFlags = SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE;
assert( pOutFlags!=0 ); /* True because flags==SQLITE_OPEN_MAIN_DB */
*pOutFlags = flags | SQLITE_OPEN_MEMORY;
p->base.pMethods = &memdb_io_methods;
pFile->pMethods = &memdb_io_methods;
p->szMax = sqlite3GlobalConfig.mxMemdbSize;
return SQLITE_OK;
}
#if 0 /* Only used to delete rollback journals, master journals, and WAL
#if 0 /* Only used to delete rollback journals, super-journals, and WAL
** files, none of which exist in memdb. So this routine is never used */
/*
** Delete the file located at zPath. If the dirSync argument is true,
+2 -2
View File
@@ -366,7 +366,7 @@ int sqlite3JournalOpen(
assert( MEMJOURNAL_DFLT_FILECHUNKSIZE==fileChunkSize(p->nChunkSize) );
}
p->pMethod = (const sqlite3_io_methods*)&MemJournalMethods;
pJfd->pMethods = (const sqlite3_io_methods*)&MemJournalMethods;
p->nSpill = nSpill;
p->flags = flags;
p->zJournal = zName;
@@ -392,7 +392,7 @@ void sqlite3MemJournalOpen(sqlite3_file *pJfd){
int sqlite3JournalCreate(sqlite3_file *pJfd){
int rc = SQLITE_OK;
MemJournal *p = (MemJournal*)pJfd;
if( p->pMethod==&MemJournalMethods && (
if( pJfd->pMethods==&MemJournalMethods && (
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
p->nSpill>0
#else
+1 -1
View File
@@ -112,7 +112,7 @@ static int pthreadMutexEnd(void){ return SQLITE_OK; }
** <ul>
** <li> SQLITE_MUTEX_FAST
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MAIN
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_OPEN
** <li> SQLITE_MUTEX_STATIC_PRNG
+1 -1
View File
@@ -171,7 +171,7 @@ static int winMutexEnd(void){
** <ul>
** <li> SQLITE_MUTEX_FAST
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MAIN
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_OPEN
** <li> SQLITE_MUTEX_STATIC_PRNG
+8 -8
View File
@@ -29,12 +29,12 @@
*/
#define assertMutexHeld() \
assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) )
assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) )
/*
** Head of a linked list of all sqlite3 objects created by this process
** for which either sqlite3.pBlockingConnection or sqlite3.pUnlockConnection
** is not NULL. This variable may only accessed while the STATIC_MASTER
** is not NULL. This variable may only accessed while the STATIC_MAIN
** mutex is held.
*/
static sqlite3 *SQLITE_WSD sqlite3BlockedList = 0;
@@ -108,20 +108,20 @@ static void addToBlockedList(sqlite3 *db){
}
/*
** Obtain the STATIC_MASTER mutex.
** Obtain the STATIC_MAIN mutex.
*/
static void enterMutex(void){
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
sqlite3_mutex_enter(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
checkListProperties(0);
}
/*
** Release the STATIC_MASTER mutex.
** Release the STATIC_MAIN mutex.
*/
static void leaveMutex(void){
assertMutexHeld();
checkListProperties(0);
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER));
sqlite3_mutex_leave(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN));
}
/*
@@ -232,7 +232,7 @@ void sqlite3ConnectionUnlocked(sqlite3 *db){
void *aStatic[16]; /* Starter space for aArg[]. No malloc required */
aArg = aStatic;
enterMutex(); /* Enter STATIC_MASTER mutex */
enterMutex(); /* Enter STATIC_MAIN mutex */
/* This loop runs once for each entry in the blocked-connections list. */
for(pp=&sqlite3BlockedList; *pp; /* no-op */ ){
@@ -315,7 +315,7 @@ void sqlite3ConnectionUnlocked(sqlite3 *db){
xUnlockNotify(aArg, nArg);
}
sqlite3_free(aDyn);
leaveMutex(); /* Leave STATIC_MASTER mutex */
leaveMutex(); /* Leave STATIC_MAIN mutex */
}
/*
+4 -4
View File
@@ -353,7 +353,7 @@ sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
if( rc ) return 0;
#endif
#if SQLITE_THREADSAFE
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN);
#endif
sqlite3_mutex_enter(mutex);
for(pVfs = vfsList; pVfs; pVfs=pVfs->pNext){
@@ -368,7 +368,7 @@ sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
** Unlink a VFS from the linked list
*/
static void vfsUnlink(sqlite3_vfs *pVfs){
assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER)) );
assert( sqlite3_mutex_held(sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN)) );
if( pVfs==0 ){
/* No-op */
}else if( vfsList==pVfs ){
@@ -399,7 +399,7 @@ int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
if( pVfs==0 ) return SQLITE_MISUSE_BKPT;
#endif
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
if( makeDflt || vfsList==0 ){
@@ -423,7 +423,7 @@ int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
int rc = sqlite3_initialize();
if( rc ) return rc;
#endif
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
sqlite3_mutex_enter(mutex);
vfsUnlink(pVfs);
sqlite3_mutex_leave(mutex);
+15 -12
View File
@@ -3340,7 +3340,7 @@ static int unixRead(
assert( offset>=0 );
assert( amt>0 );
/* If this is a database file (not a journal, master-journal or temp
/* If this is a database file (not a journal, super-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
assert( pFile->pPreallocatedUnused==0
@@ -3453,7 +3453,7 @@ static int unixWrite(
assert( id );
assert( amt>0 );
/* If this is a database file (not a journal, master-journal or temp
/* If this is a database file (not a journal, super-journal or temp
** file), the bytes in the locking range should never be read or written. */
#if 0
assert( pFile->pPreallocatedUnused==0
@@ -4836,7 +4836,10 @@ static int unixShmLock(
**
** In other words, if this is a blocking lock, none of the locks that
** occur later in the above list than the lock being obtained may be
** held. */
** held.
**
** It is not permitted to block on the RECOVER lock.
*/
#ifdef SQLITE_ENABLE_SETLK_TIMEOUT
assert( (flags & SQLITE_SHM_UNLOCK) || pDbFd->iBusyTimeout==0 || (
(ofst!=2) /* not RECOVER */
@@ -5689,7 +5692,7 @@ static int fillInUnixFile(
if( rc!=SQLITE_OK ){
if( h>=0 ) robust_close(pNew, h, __LINE__);
}else{
pNew->pMethod = pLockingStyle;
pId->pMethods = pLockingStyle;
OpenCounter(+1);
verifyDbFile(pNew);
}
@@ -5770,7 +5773,7 @@ static int proxyTransformUnixFile(unixFile*, const char*);
/*
** Search for an unused file descriptor that was opened on the database
** file (not a journal or master-journal file) identified by pathname
** file (not a journal or super-journal file) identified by pathname
** zPath with SQLITE_OPEN_XXX flags matching those passed as the second
** argument to this function.
**
@@ -5904,7 +5907,7 @@ static int findCreateFileMode(
while( zPath[nDb]!='-' ){
/* In normal operation, the journal file name will always contain
** a '-' character. However in 8+3 filename mode, or if a corrupt
** rollback journal specifies a master journal with a goofy name, then
** rollback journal specifies a super-journal with a goofy name, then
** the '-' might be missing. */
if( nDb==0 || zPath[nDb]=='.' ) return SQLITE_OK;
nDb--;
@@ -5977,12 +5980,12 @@ static int unixOpen(
struct statfs fsInfo;
#endif
/* If creating a master or main-file journal, this function will open
/* If creating a super- or main-file journal, this function will open
** a file-descriptor on the directory too. The first time unixSync()
** is called the directory file descriptor will be fsync()ed and close()d.
*/
int isNewJrnl = (isCreate && (
eType==SQLITE_OPEN_MASTER_JOURNAL
eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
@@ -6005,17 +6008,17 @@ static int unixOpen(
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
/* The main DB, main journal, WAL file and master journal are never
/* The main DB, main journal, WAL file and super-journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
@@ -6208,7 +6211,7 @@ static int unixOpen(
#endif
assert( zPath==0 || zPath[0]=='/'
|| eType==SQLITE_OPEN_MASTER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_SUPER_JOURNAL || eType==SQLITE_OPEN_MAIN_JOURNAL
);
rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags);
+10 -10
View File
@@ -1290,17 +1290,17 @@ int sqlite3_win32_compact_heap(LPUINT pnLargest){
*/
int sqlite3_win32_reset_heap(){
int rc;
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMainMtx; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
MUTEX_LOGIC( pMaster = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER); )
MUTEX_LOGIC( pMainMtx = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MAIN); )
MUTEX_LOGIC( pMem = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MEM); )
sqlite3_mutex_enter(pMaster);
sqlite3_mutex_enter(pMainMtx);
sqlite3_mutex_enter(pMem);
winMemAssertMagic();
if( winMemGetHeap()!=NULL && winMemGetOwned() && sqlite3_memory_used()==0 ){
/*
** At this point, there should be no outstanding memory allocations on
** the heap. Also, since both the master and memsys locks are currently
** the heap. Also, since both the main and memsys locks are currently
** being held by us, no other function (i.e. from another thread) should
** be able to even access the heap. Attempt to destroy and recreate our
** isolated Win32 native heap now.
@@ -1323,7 +1323,7 @@ int sqlite3_win32_reset_heap(){
rc = SQLITE_BUSY;
}
sqlite3_mutex_leave(pMem);
sqlite3_mutex_leave(pMaster);
sqlite3_mutex_leave(pMainMtx);
return rc;
}
#endif /* SQLITE_WIN32_MALLOC */
@@ -5023,7 +5023,7 @@ static int winOpen(
#ifndef NDEBUG
int isOpenJournal = (isCreate && (
eType==SQLITE_OPEN_MASTER_JOURNAL
eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_MAIN_JOURNAL
|| eType==SQLITE_OPEN_WAL
));
@@ -5044,17 +5044,17 @@ static int winOpen(
assert(isExclusive==0 || isCreate);
assert(isDelete==0 || isCreate);
/* The main DB, main journal, WAL file and master journal are never
/* The main DB, main journal, WAL file and super-journal are never
** automatically deleted. Nor are they ever temporary files. */
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_DB );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MAIN_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_MASTER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_SUPER_JOURNAL );
assert( (!isDelete && zName) || eType!=SQLITE_OPEN_WAL );
/* Assert that the upper layer has set one of the "file-type" flags. */
assert( eType==SQLITE_OPEN_MAIN_DB || eType==SQLITE_OPEN_TEMP_DB
|| eType==SQLITE_OPEN_MAIN_JOURNAL || eType==SQLITE_OPEN_TEMP_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_MASTER_JOURNAL
|| eType==SQLITE_OPEN_SUBJOURNAL || eType==SQLITE_OPEN_SUPER_JOURNAL
|| eType==SQLITE_OPEN_TRANSIENT_DB || eType==SQLITE_OPEN_WAL
);
@@ -5266,7 +5266,7 @@ static int winOpen(
}
sqlite3_free(zTmpname);
pFile->pMethod = pAppData ? pAppData->pMethod : &winIoMethod;
id->pMethods = pAppData ? pAppData->pMethod : &winIoMethod;
pFile->pVfs = pVfs;
pFile->h = h;
if( isReadonly ){
+174 -178
View File
@@ -70,8 +70,8 @@
** (5) All writes to the database file are synced prior to the rollback journal
** being deleted, truncated, or zeroed.
**
** (6) If a master journal file is used, then all writes to the database file
** are synced prior to the master journal being deleted.
** (6) If a super-journal file is used, then all writes to the database file
** are synced prior to the super-journal being deleted.
**
** Definition: Two databases (or the same database at two points it time)
** are said to be "logically equivalent" if they give the same answer to
@@ -488,29 +488,29 @@ struct PagerSavepoint {
** need only update the change-counter once, for the first transaction
** committed.
**
** setMaster
** setSuper
**
** When PagerCommitPhaseOne() is called to commit a transaction, it may
** (or may not) specify a master-journal name to be written into the
** (or may not) specify a super-journal name to be written into the
** journal file before it is synced to disk.
**
** Whether or not a journal file contains a master-journal pointer affects
** Whether or not a journal file contains a super-journal pointer affects
** the way in which the journal file is finalized after the transaction is
** committed or rolled back when running in "journal_mode=PERSIST" mode.
** If a journal file does not contain a master-journal pointer, it is
** If a journal file does not contain a super-journal pointer, it is
** finalized by overwriting the first journal header with zeroes. If
** it does contain a master-journal pointer the journal file is finalized
** it does contain a super-journal pointer the journal file is finalized
** by truncating it to zero bytes, just as if the connection were
** running in "journal_mode=truncate" mode.
**
** Journal files that contain master journal pointers cannot be finalized
** Journal files that contain super-journal pointers cannot be finalized
** simply by overwriting the first journal-header with zeroes, as the
** master journal pointer could interfere with hot-journal rollback of any
** super-journal pointer could interfere with hot-journal rollback of any
** subsequently interrupted transaction that reuses the journal file.
**
** The flag is cleared as soon as the journal file is finalized (either
** by PagerCommitPhaseTwo or PagerRollback). If an IO error prevents the
** journal file from being successfully finalized, the setMaster flag
** journal file from being successfully finalized, the setSuper flag
** is cleared anyway (and the pager will move to ERROR state).
**
** doNotSpill
@@ -642,7 +642,7 @@ struct Pager {
u8 eState; /* Pager state (OPEN, READER, WRITER_LOCKED..) */
u8 eLock; /* Current lock held on database file */
u8 changeCountDone; /* Set after incrementing the change-counter */
u8 setMaster; /* True if a m-j name has been written to jrnl */
u8 setSuper; /* Super-jrnl name is written into jrnl */
u8 doNotSpill; /* Do not spill the cache when non-zero */
u8 subjInMemory; /* True to use in-memory sub-journals */
u8 bUseFetch; /* True to use xFetch() */
@@ -786,11 +786,6 @@ static const unsigned char aJournalMagic[] = {
# define USEFETCH(x) 0
#endif
/*
** The maximum legal page number is (2^31 - 1).
*/
#define PAGER_MAX_PGNO 2147483647
/*
** The argument to this macro is a file descriptor (type sqlite3_file*).
** Return 0 if it is not open, or non-zero (but not 1) if it is.
@@ -920,7 +915,7 @@ static int assert_pager_state(Pager *p){
assert( pPager->dbSize==pPager->dbOrigSize );
assert( pPager->dbOrigSize==pPager->dbFileSize );
assert( pPager->dbOrigSize==pPager->dbHintSize );
assert( pPager->setMaster==0 );
assert( pPager->setSuper==0 );
break;
case PAGER_WRITER_CACHEMOD:
@@ -1274,66 +1269,66 @@ static void checkPage(PgHdr *pPg){
/*
** When this is called the journal file for pager pPager must be open.
** This function attempts to read a master journal file name from the
** This function attempts to read a super-journal file name from the
** end of the file and, if successful, copies it into memory supplied
** by the caller. See comments above writeMasterJournal() for the format
** used to store a master journal file name at the end of a journal file.
** by the caller. See comments above writeSuperJournal() for the format
** used to store a super-journal file name at the end of a journal file.
**
** zMaster must point to a buffer of at least nMaster bytes allocated by
** zSuper must point to a buffer of at least nSuper bytes allocated by
** the caller. This should be sqlite3_vfs.mxPathname+1 (to ensure there is
** enough space to write the master journal name). If the master journal
** name in the journal is longer than nMaster bytes (including a
** nul-terminator), then this is handled as if no master journal name
** enough space to write the super-journal name). If the super-journal
** name in the journal is longer than nSuper bytes (including a
** nul-terminator), then this is handled as if no super-journal name
** were present in the journal.
**
** If a master journal file name is present at the end of the journal
** file, then it is copied into the buffer pointed to by zMaster. A
** nul-terminator byte is appended to the buffer following the master
** journal file name.
** If a super-journal file name is present at the end of the journal
** file, then it is copied into the buffer pointed to by zSuper. A
** nul-terminator byte is appended to the buffer following the
** super-journal file name.
**
** If it is determined that no master journal file name is present
** zMaster[0] is set to 0 and SQLITE_OK returned.
** If it is determined that no super-journal file name is present
** zSuper[0] is set to 0 and SQLITE_OK returned.
**
** If an error occurs while reading from the journal file, an SQLite
** error code is returned.
*/
static int readMasterJournal(sqlite3_file *pJrnl, char *zMaster, u32 nMaster){
static int readSuperJournal(sqlite3_file *pJrnl, char *zSuper, u32 nSuper){
int rc; /* Return code */
u32 len; /* Length in bytes of master journal name */
u32 len; /* Length in bytes of super-journal name */
i64 szJ; /* Total size in bytes of journal file pJrnl */
u32 cksum; /* MJ checksum value read from journal */
u32 u; /* Unsigned loop counter */
unsigned char aMagic[8]; /* A buffer to hold the magic header */
zMaster[0] = '\0';
zSuper[0] = '\0';
if( SQLITE_OK!=(rc = sqlite3OsFileSize(pJrnl, &szJ))
|| szJ<16
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-16, &len))
|| len>=nMaster
|| len>=nSuper
|| len>szJ-16
|| len==0
|| SQLITE_OK!=(rc = read32bits(pJrnl, szJ-12, &cksum))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, aMagic, 8, szJ-8))
|| memcmp(aMagic, aJournalMagic, 8)
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zMaster, len, szJ-16-len))
|| SQLITE_OK!=(rc = sqlite3OsRead(pJrnl, zSuper, len, szJ-16-len))
){
return rc;
}
/* See if the checksum matches the master journal name */
/* See if the checksum matches the super-journal name */
for(u=0; u<len; u++){
cksum -= zMaster[u];
cksum -= zSuper[u];
}
if( cksum ){
/* If the checksum doesn't add up, then one or more of the disk sectors
** containing the master journal filename is corrupted. This means
** containing the super-journal filename is corrupted. This means
** definitely roll back, so just return SQLITE_OK and report a (nul)
** master-journal filename.
** super-journal filename.
*/
len = 0;
}
zMaster[len] = '\0';
zMaster[len+1] = '\0';
zSuper[len] = '\0';
zSuper[len+1] = '\0';
return SQLITE_OK;
}
@@ -1661,50 +1656,50 @@ static int readJournalHdr(
/*
** Write the supplied master journal name into the journal file for pager
** pPager at the current location. The master journal name must be the last
** Write the supplied super-journal name into the journal file for pager
** pPager at the current location. The super-journal name must be the last
** thing written to a journal file. If the pager is in full-sync mode, the
** journal file descriptor is advanced to the next sector boundary before
** anything is written. The format is:
**
** + 4 bytes: PAGER_MJ_PGNO.
** + N bytes: Master journal filename in utf-8.
** + 4 bytes: N (length of master journal name in bytes, no nul-terminator).
** + 4 bytes: Master journal name checksum.
** + N bytes: super-journal filename in utf-8.
** + 4 bytes: N (length of super-journal name in bytes, no nul-terminator).
** + 4 bytes: super-journal name checksum.
** + 8 bytes: aJournalMagic[].
**
** The master journal page checksum is the sum of the bytes in the master
** journal name, where each byte is interpreted as a signed 8-bit integer.
** The super-journal page checksum is the sum of the bytes in thesuper-journal
** name, where each byte is interpreted as a signed 8-bit integer.
**
** If zMaster is a NULL pointer (occurs for a single database transaction),
** If zSuper is a NULL pointer (occurs for a single database transaction),
** this call is a no-op.
*/
static int writeMasterJournal(Pager *pPager, const char *zMaster){
static int writeSuperJournal(Pager *pPager, const char *zSuper){
int rc; /* Return code */
int nMaster; /* Length of string zMaster */
int nSuper; /* Length of string zSuper */
i64 iHdrOff; /* Offset of header in journal file */
i64 jrnlSize; /* Size of journal file on disk */
u32 cksum = 0; /* Checksum of string zMaster */
u32 cksum = 0; /* Checksum of string zSuper */
assert( pPager->setMaster==0 );
assert( pPager->setSuper==0 );
assert( !pagerUseWal(pPager) );
if( !zMaster
if( !zSuper
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|| !isOpen(pPager->jfd)
){
return SQLITE_OK;
}
pPager->setMaster = 1;
pPager->setSuper = 1;
assert( pPager->journalHdr <= pPager->journalOff );
/* Calculate the length in bytes and the checksum of zMaster */
for(nMaster=0; zMaster[nMaster]; nMaster++){
cksum += zMaster[nMaster];
/* Calculate the length in bytes and the checksum of zSuper */
for(nSuper=0; zSuper[nSuper]; nSuper++){
cksum += zSuper[nSuper];
}
/* If in full-sync mode, advance to the next disk sector before writing
** the master journal name. This is in case the previous page written to
** the super-journal name. This is in case the previous page written to
** the journal has already been synced.
*/
if( pPager->fullSync ){
@@ -1712,25 +1707,25 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
}
iHdrOff = pPager->journalOff;
/* Write the master journal data to the end of the journal file. If
/* Write the super-journal data to the end of the journal file. If
** an error occurs, return the error code to the caller.
*/
if( (0 != (rc = write32bits(pPager->jfd, iHdrOff, PAGER_MJ_PGNO(pPager))))
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, zMaster, nMaster, iHdrOff+4)))
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster, nMaster)))
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nMaster+4, cksum)))
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, zSuper, nSuper, iHdrOff+4)))
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper, nSuper)))
|| (0 != (rc = write32bits(pPager->jfd, iHdrOff+4+nSuper+4, cksum)))
|| (0 != (rc = sqlite3OsWrite(pPager->jfd, aJournalMagic, 8,
iHdrOff+4+nMaster+8)))
iHdrOff+4+nSuper+8)))
){
return rc;
}
pPager->journalOff += (nMaster+20);
pPager->journalOff += (nSuper+20);
/* If the pager is in peristent-journal mode, then the physical
** journal-file may extend past the end of the master-journal name
** journal-file may extend past the end of the super-journal name
** and 8 bytes of magic data just written to the file. This is
** dangerous because the code to rollback a hot-journal file
** will not be able to find the master-journal name to determine
** will not be able to find the super-journal name to determine
** whether or not the journal is hot.
**
** Easiest thing to do in this scenario is to truncate the journal
@@ -1891,7 +1886,7 @@ static void pager_unlock(Pager *pPager){
pPager->journalOff = 0;
pPager->journalHdr = 0;
pPager->setMaster = 0;
pPager->setSuper = 0;
}
/*
@@ -2007,7 +2002,7 @@ static int pagerFlushOnCommit(Pager *pPager, int bCommit){
** to the first error encountered (the journal finalization one) is
** returned.
*/
static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
static int pager_end_transaction(Pager *pPager, int hasSuper, int bCommit){
int rc = SQLITE_OK; /* Error code from journal finalization operation */
int rc2 = SQLITE_OK; /* Error code from db file unlock operation */
@@ -2059,7 +2054,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
}else if( pPager->journalMode==PAGER_JOURNALMODE_PERSIST
|| (pPager->exclusiveMode && pPager->journalMode!=PAGER_JOURNALMODE_WAL)
){
rc = zeroJournalHdr(pPager, hasMaster||pPager->tempFile);
rc = zeroJournalHdr(pPager, hasSuper||pPager->tempFile);
pPager->journalOff = 0;
}else{
/* This branch may be executed with Pager.journalMode==MEMORY if
@@ -2132,7 +2127,7 @@ static int pager_end_transaction(Pager *pPager, int hasMaster, int bCommit){
rc2 = pagerUnlockDb(pPager, SHARED_LOCK);
}
pPager->eState = PAGER_READER;
pPager->setMaster = 0;
pPager->setSuper = 0;
return (rc==SQLITE_OK?rc2:rc);
}
@@ -2440,36 +2435,36 @@ static int pager_playback_one_page(
}
/*
** Parameter zMaster is the name of a master journal file. A single journal
** file that referred to the master journal file has just been rolled back.
** This routine checks if it is possible to delete the master journal file,
** Parameter zSuper is the name of a super-journal file. A single journal
** file that referred to the super-journal file has just been rolled back.
** This routine checks if it is possible to delete the super-journal file,
** and does so if it is.
**
** Argument zMaster may point to Pager.pTmpSpace. So that buffer is not
** Argument zSuper may point to Pager.pTmpSpace. So that buffer is not
** available for use within this function.
**
** When a master journal file is created, it is populated with the names
** When a super-journal file is created, it is populated with the names
** of all of its child journals, one after another, formatted as utf-8
** encoded text. The end of each child journal file is marked with a
** nul-terminator byte (0x00). i.e. the entire contents of a master journal
** nul-terminator byte (0x00). i.e. the entire contents of a super-journal
** file for a transaction involving two databases might be:
**
** "/home/bill/a.db-journal\x00/home/bill/b.db-journal\x00"
**
** A master journal file may only be deleted once all of its child
** A super-journal file may only be deleted once all of its child
** journals have been rolled back.
**
** This function reads the contents of the master-journal file into
** This function reads the contents of the super-journal file into
** memory and loops through each of the child journal names. For
** each child journal, it checks if:
**
** * if the child journal exists, and if so
** * if the child journal contains a reference to master journal
** file zMaster
** * if the child journal contains a reference to super-journal
** file zSuper
**
** If a child journal can be found that matches both of the criteria
** above, this function returns without doing anything. Otherwise, if
** no such child journal can be found, file zMaster is deleted from
** no such child journal can be found, file zSuper is deleted from
** the file-system using sqlite3OsDelete().
**
** If an IO error within this function, an error code is returned. This
@@ -2478,99 +2473,100 @@ static int pager_playback_one_page(
** occur, SQLITE_OK is returned.
**
** TODO: This function allocates a single block of memory to load
** the entire contents of the master journal file. This could be
** the entire contents of the super-journal file. This could be
** a couple of kilobytes or so - potentially larger than the page
** size.
*/
static int pager_delmaster(Pager *pPager, const char *zMaster){
static int pager_delsuper(Pager *pPager, const char *zSuper){
sqlite3_vfs *pVfs = pPager->pVfs;
int rc; /* Return code */
sqlite3_file *pMaster; /* Malloc'd master-journal file descriptor */
sqlite3_file *pSuper; /* Malloc'd super-journal file descriptor */
sqlite3_file *pJournal; /* Malloc'd child-journal file descriptor */
char *zMasterJournal = 0; /* Contents of master journal file */
i64 nMasterJournal; /* Size of master journal file */
char *zSuperJournal = 0; /* Contents of super-journal file */
i64 nSuperJournal; /* Size of super-journal file */
char *zJournal; /* Pointer to one journal within MJ file */
char *zMasterPtr; /* Space to hold MJ filename from a journal file */
int nMasterPtr; /* Amount of space allocated to zMasterPtr[] */
char *zSuperPtr; /* Space to hold super-journal filename */
int nSuperPtr; /* Amount of space allocated to zSuperPtr[] */
/* Allocate space for both the pJournal and pMaster file descriptors.
** If successful, open the master journal file for reading.
/* Allocate space for both the pJournal and pSuper file descriptors.
** If successful, open the super-journal file for reading.
*/
pMaster = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
pJournal = (sqlite3_file *)(((u8 *)pMaster) + pVfs->szOsFile);
if( !pMaster ){
pSuper = (sqlite3_file *)sqlite3MallocZero(pVfs->szOsFile * 2);
if( !pSuper ){
rc = SQLITE_NOMEM_BKPT;
pJournal = 0;
}else{
const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
rc = sqlite3OsOpen(pVfs, zMaster, pMaster, flags, 0);
const int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
rc = sqlite3OsOpen(pVfs, zSuper, pSuper, flags, 0);
pJournal = (sqlite3_file *)(((u8 *)pSuper) + pVfs->szOsFile);
}
if( rc!=SQLITE_OK ) goto delmaster_out;
if( rc!=SQLITE_OK ) goto delsuper_out;
/* Load the entire master journal file into space obtained from
** sqlite3_malloc() and pointed to by zMasterJournal. Also obtain
** sufficient space (in zMasterPtr) to hold the names of master
** journal files extracted from regular rollback-journals.
/* Load the entire super-journal file into space obtained from
** sqlite3_malloc() and pointed to by zSuperJournal. Also obtain
** sufficient space (in zSuperPtr) to hold the names of super-journal
** files extracted from regular rollback-journals.
*/
rc = sqlite3OsFileSize(pMaster, &nMasterJournal);
if( rc!=SQLITE_OK ) goto delmaster_out;
nMasterPtr = pVfs->mxPathname+1;
zMasterJournal = sqlite3Malloc(nMasterJournal + nMasterPtr + 2);
if( !zMasterJournal ){
rc = sqlite3OsFileSize(pSuper, &nSuperJournal);
if( rc!=SQLITE_OK ) goto delsuper_out;
nSuperPtr = pVfs->mxPathname+1;
zSuperJournal = sqlite3Malloc(nSuperJournal + nSuperPtr + 2);
if( !zSuperJournal ){
rc = SQLITE_NOMEM_BKPT;
goto delmaster_out;
goto delsuper_out;
}
zMasterPtr = &zMasterJournal[nMasterJournal+2];
rc = sqlite3OsRead(pMaster, zMasterJournal, (int)nMasterJournal, 0);
if( rc!=SQLITE_OK ) goto delmaster_out;
zMasterJournal[nMasterJournal] = 0;
zMasterJournal[nMasterJournal+1] = 0;
zSuperPtr = &zSuperJournal[nSuperJournal+2];
rc = sqlite3OsRead(pSuper, zSuperJournal, (int)nSuperJournal, 0);
if( rc!=SQLITE_OK ) goto delsuper_out;
zSuperJournal[nSuperJournal] = 0;
zSuperJournal[nSuperJournal+1] = 0;
zJournal = zMasterJournal;
while( (zJournal-zMasterJournal)<nMasterJournal ){
zJournal = zSuperJournal;
while( (zJournal-zSuperJournal)<nSuperJournal ){
int exists;
rc = sqlite3OsAccess(pVfs, zJournal, SQLITE_ACCESS_EXISTS, &exists);
if( rc!=SQLITE_OK ){
goto delmaster_out;
goto delsuper_out;
}
if( exists ){
/* One of the journals pointed to by the master journal exists.
** Open it and check if it points at the master journal. If
** so, return without deleting the master journal file.
/* One of the journals pointed to by the super-journal exists.
** Open it and check if it points at the super-journal. If
** so, return without deleting the super-journal file.
** NB: zJournal is really a MAIN_JOURNAL. But call it a
** MASTER_JOURNAL here so that the VFS will not send the zJournal
** SUPER_JOURNAL here so that the VFS will not send the zJournal
** name into sqlite3_database_file_object().
*/
int c;
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_MASTER_JOURNAL);
int flags = (SQLITE_OPEN_READONLY|SQLITE_OPEN_SUPER_JOURNAL);
rc = sqlite3OsOpen(pVfs, zJournal, pJournal, flags, 0);
if( rc!=SQLITE_OK ){
goto delmaster_out;
goto delsuper_out;
}
rc = readMasterJournal(pJournal, zMasterPtr, nMasterPtr);
rc = readSuperJournal(pJournal, zSuperPtr, nSuperPtr);
sqlite3OsClose(pJournal);
if( rc!=SQLITE_OK ){
goto delmaster_out;
goto delsuper_out;
}
c = zMasterPtr[0]!=0 && strcmp(zMasterPtr, zMaster)==0;
c = zSuperPtr[0]!=0 && strcmp(zSuperPtr, zSuper)==0;
if( c ){
/* We have a match. Do not delete the master journal file. */
goto delmaster_out;
/* We have a match. Do not delete the super-journal file. */
goto delsuper_out;
}
}
zJournal += (sqlite3Strlen30(zJournal)+1);
}
sqlite3OsClose(pMaster);
rc = sqlite3OsDelete(pVfs, zMaster, 0);
sqlite3OsClose(pSuper);
rc = sqlite3OsDelete(pVfs, zSuper, 0);
delmaster_out:
sqlite3_free(zMasterJournal);
if( pMaster ){
sqlite3OsClose(pMaster);
delsuper_out:
sqlite3_free(zSuperJournal);
if( pSuper ){
sqlite3OsClose(pSuper);
assert( !isOpen(pJournal) );
sqlite3_free(pMaster);
sqlite3_free(pSuper);
}
return rc;
}
@@ -2648,7 +2644,7 @@ int sqlite3SectorSize(sqlite3_file *pFile){
** pager based on the value returned by the xSectorSize method
** of the open database file. The sector size will be used
** to determine the size and alignment of journal header and
** master journal pointers within created journal files.
** super-journal pointers within created journal files.
**
** For temporary files the effective sector size is always 512 bytes.
**
@@ -2747,7 +2743,7 @@ static int pager_playback(Pager *pPager, int isHot){
Pgno mxPg = 0; /* Size of the original file in pages */
int rc; /* Result code of a subroutine */
int res = 1; /* Value returned by sqlite3OsAccess() */
char *zMaster = 0; /* Name of master journal file if any */
char *zSuper = 0; /* Name of super-journal file if any */
int needPagerReset; /* True to reset page prior to first page rollback */
int nPlayback = 0; /* Total number of pages restored from journal */
u32 savedPageSize = pPager->pageSize;
@@ -2761,8 +2757,8 @@ static int pager_playback(Pager *pPager, int isHot){
goto end_playback;
}
/* Read the master journal name from the journal, if it is present.
** If a master journal file name is specified, but the file is not
/* Read the super-journal name from the journal, if it is present.
** If a super-journal file name is specified, but the file is not
** present on disk, then the journal is not hot and does not need to be
** played back.
**
@@ -2772,12 +2768,12 @@ static int pager_playback(Pager *pPager, int isHot){
** mxPathname is 512, which is the same as the minimum allowable value
** for pageSize.
*/
zMaster = pPager->pTmpSpace;
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
if( rc==SQLITE_OK && zMaster[0] ){
rc = sqlite3OsAccess(pVfs, zMaster, SQLITE_ACCESS_EXISTS, &res);
zSuper = pPager->pTmpSpace;
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
if( rc==SQLITE_OK && zSuper[0] ){
rc = sqlite3OsAccess(pVfs, zSuper, SQLITE_ACCESS_EXISTS, &res);
}
zMaster = 0;
zSuper = 0;
if( rc!=SQLITE_OK || !res ){
goto end_playback;
}
@@ -2904,8 +2900,8 @@ end_playback:
pPager->changeCountDone = pPager->tempFile;
if( rc==SQLITE_OK ){
zMaster = pPager->pTmpSpace;
rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
zSuper = pPager->pTmpSpace;
rc = readSuperJournal(pPager->jfd, zSuper, pPager->pVfs->mxPathname+1);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK
@@ -2914,14 +2910,14 @@ end_playback:
rc = sqlite3PagerSync(pPager, 0);
}
if( rc==SQLITE_OK ){
rc = pager_end_transaction(pPager, zMaster[0]!='\0', 0);
rc = pager_end_transaction(pPager, zSuper[0]!='\0', 0);
testcase( rc!=SQLITE_OK );
}
if( rc==SQLITE_OK && zMaster[0] && res ){
/* If there was a master journal and this routine will return success,
** see if it is possible to delete the master journal.
if( rc==SQLITE_OK && zSuper[0] && res ){
/* If there was a super-journal and this routine will return success,
** see if it is possible to delete the super-journal.
*/
rc = pager_delmaster(pPager, zMaster);
rc = pager_delsuper(pPager, zSuper);
testcase( rc!=SQLITE_OK );
}
if( isHot && nPlayback ){
@@ -3300,7 +3296,7 @@ static int pagerOpenWalIfPresent(Pager *pPager){
/*
** Playback savepoint pSavepoint. Or, if pSavepoint==NULL, then playback
** the entire master journal file. The case pSavepoint==NULL occurs when
** the entire super-journal file. The case pSavepoint==NULL occurs when
** a ROLLBACK TO command is invoked on a SAVEPOINT that is a transaction
** savepoint.
**
@@ -3763,7 +3759,7 @@ void *sqlite3PagerTempSpace(Pager *pPager){
**
** Regardless of mxPage, return the current maximum page count.
*/
int sqlite3PagerMaxPageCount(Pager *pPager, int mxPage){
Pgno sqlite3PagerMaxPageCount(Pager *pPager, Pgno mxPage){
if( mxPage>0 ){
pPager->mxPgno = mxPage;
}
@@ -5040,8 +5036,8 @@ sqlite3_file *sqlite3_database_file_object(const char *zName){
** just deleted using OsDelete, *pExists is set to 0 and SQLITE_OK
** is returned.
**
** This routine does not check if there is a master journal filename
** at the end of the file. If there is, and that master journal file
** This routine does not check if there is a super-journal filename
** at the end of the file. If there is, and that super-journal file
** does not exist, then the journal file is not really hot. In this
** case this routine will return a false-positive. The pager_playback()
** routine will discover that the journal file is not really hot and
@@ -5490,7 +5486,7 @@ static int getPageNormal(
if( pPg->pPager && !noContent ){
/* In this case the pcache already contains an initialized copy of
** the page. Return without further ado. */
assert( pgno<=PAGER_MAX_PGNO && pgno!=PAGER_MJ_PGNO(pPager) );
assert( pgno!=PAGER_MJ_PGNO(pPager) );
pPager->aStat[PAGER_STAT_HIT]++;
return SQLITE_OK;
@@ -5498,10 +5494,10 @@ static int getPageNormal(
/* The pager cache has created a new page. Its content needs to
** be initialized. But first some error checks:
**
** (1) The maximum page number is 2^31
** (*) obsolete. Was: maximum page number is 2^31
** (2) Never try to fetch the locking page
*/
if( pgno>PAGER_MAX_PGNO || pgno==PAGER_MJ_PGNO(pPager) ){
if( pgno==PAGER_MJ_PGNO(pPager) ){
rc = SQLITE_CORRUPT_BKPT;
goto pager_acquire_err;
}
@@ -5786,7 +5782,7 @@ static int pager_open_journal(Pager *pPager){
/* TODO: Check if all of these are really required. */
pPager->nRec = 0;
pPager->journalOff = 0;
pPager->setMaster = 0;
pPager->setSuper = 0;
pPager->journalHdr = 0;
rc = writeJournalHdr(pPager);
}
@@ -6298,9 +6294,9 @@ static int pager_incr_changecounter(Pager *pPager, int isDirectMode){
** If successful, or if called on a pager for which it is a no-op, this
** function returns SQLITE_OK. Otherwise, an IO error code is returned.
*/
int sqlite3PagerSync(Pager *pPager, const char *zMaster){
int sqlite3PagerSync(Pager *pPager, const char *zSuper){
int rc = SQLITE_OK;
void *pArg = (void*)zMaster;
void *pArg = (void*)zSuper;
rc = sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, pArg);
if( rc==SQLITE_NOTFOUND ) rc = SQLITE_OK;
if( rc==SQLITE_OK && !pPager->noSync ){
@@ -6338,10 +6334,10 @@ int sqlite3PagerExclusiveLock(Pager *pPager){
}
/*
** Sync the database file for the pager pPager. zMaster points to the name
** of a master journal file that should be written into the individual
** journal file. zMaster may be NULL, which is interpreted as no master
** journal (a single database transaction).
** Sync the database file for the pager pPager. zSuper points to the name
** of a super-journal file that should be written into the individual
** journal file. zSuper may be NULL, which is interpreted as no
** super-journal (a single database transaction).
**
** This routine ensures that:
**
@@ -6353,9 +6349,9 @@ int sqlite3PagerExclusiveLock(Pager *pPager){
**
** The only thing that remains to commit the transaction is to finalize
** (delete, truncate or zero the first part of) the journal file (or
** delete the master journal file if specified).
** delete the super-journal file if specified).
**
** Note that if zMaster==NULL, this does not overwrite a previous value
** Note that if zSuper==NULL, this does not overwrite a previous value
** passed to an sqlite3PagerCommitPhaseOne() call.
**
** If the final parameter - noSync - is true, then the database file itself
@@ -6365,7 +6361,7 @@ int sqlite3PagerExclusiveLock(Pager *pPager){
*/
int sqlite3PagerCommitPhaseOne(
Pager *pPager, /* Pager object */
const char *zMaster, /* If not NULL, the master journal name */
const char *zSuper, /* If not NULL, the super-journal name */
int noSync /* True to omit the xSync on the db file */
){
int rc = SQLITE_OK; /* Return code */
@@ -6383,8 +6379,8 @@ int sqlite3PagerCommitPhaseOne(
/* Provide the ability to easily simulate an I/O error during testing */
if( sqlite3FaultSim(400) ) return SQLITE_IOERR;
PAGERTRACE(("DATABASE SYNC: File=%s zMaster=%s nSize=%d\n",
pPager->zFilename, zMaster, pPager->dbSize));
PAGERTRACE(("DATABASE SYNC: File=%s zSuper=%s nSize=%d\n",
pPager->zFilename, zSuper, pPager->dbSize));
/* If no database changes have been made, return early. */
if( pPager->eState<PAGER_WRITER_CACHEMOD ) return SQLITE_OK;
@@ -6423,7 +6419,7 @@ int sqlite3PagerCommitPhaseOne(
*/
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
sqlite3_file *fd = pPager->fd;
int bBatch = zMaster==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
int bBatch = zSuper==0 /* An SQLITE_IOCAP_BATCH_ATOMIC commit */
&& (sqlite3OsDeviceCharacteristics(fd) & SQLITE_IOCAP_BATCH_ATOMIC)
&& !pPager->noSync
&& sqlite3JournalIsInMemory(pPager->jfd);
@@ -6461,7 +6457,7 @@ int sqlite3PagerCommitPhaseOne(
|| pPager->journalMode==PAGER_JOURNALMODE_OFF
|| pPager->journalMode==PAGER_JOURNALMODE_WAL
);
if( !zMaster && isOpen(pPager->jfd)
if( !zSuper && isOpen(pPager->jfd)
&& pPager->journalOff==jrnlBufferSize(pPager)
&& pPager->dbSize>=pPager->dbOrigSize
&& (!(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
@@ -6482,7 +6478,7 @@ int sqlite3PagerCommitPhaseOne(
}
#else /* SQLITE_ENABLE_ATOMIC_WRITE */
#ifdef SQLITE_ENABLE_BATCH_ATOMIC_WRITE
if( zMaster ){
if( zSuper ){
rc = sqlite3JournalCreate(pPager->jfd);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
assert( bBatch==0 );
@@ -6492,11 +6488,11 @@ int sqlite3PagerCommitPhaseOne(
#endif /* !SQLITE_ENABLE_ATOMIC_WRITE */
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Write the master journal name into the journal file. If a master
** journal file name has already been written to the journal file,
** or if zMaster is NULL (no master journal), then this call is a no-op.
/* Write the super-journal name into the journal file. If a
** super-journal file name has already been written to the journal file,
** or if zSuper is NULL (no super-journal), then this call is a no-op.
*/
rc = writeMasterJournal(pPager, zMaster);
rc = writeSuperJournal(pPager, zSuper);
if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
/* Sync the journal file and write all dirty pages to the database.
@@ -6564,7 +6560,7 @@ int sqlite3PagerCommitPhaseOne(
/* Finally, sync the database file. */
if( !noSync ){
rc = sqlite3PagerSync(pPager, zMaster);
rc = sqlite3PagerSync(pPager, zSuper);
}
IOTRACE(("DBSYNC %p\n", pPager))
}
@@ -6629,7 +6625,7 @@ int sqlite3PagerCommitPhaseTwo(Pager *pPager){
}
PAGERTRACE(("COMMIT %d\n", PAGERID(pPager)));
rc = pager_end_transaction(pPager, pPager->setMaster, 1);
rc = pager_end_transaction(pPager, pPager->setSuper, 1);
return pager_error(pPager, rc);
}
@@ -6674,7 +6670,7 @@ int sqlite3PagerRollback(Pager *pPager){
if( pagerUseWal(pPager) ){
int rc2;
rc = sqlite3PagerSavepoint(pPager, SAVEPOINT_ROLLBACK, -1);
rc2 = pager_end_transaction(pPager, pPager->setMaster, 0);
rc2 = pager_end_transaction(pPager, pPager->setSuper, 0);
if( rc==SQLITE_OK ) rc = rc2;
}else if( !isOpen(pPager->jfd) || pPager->eState==PAGER_WRITER_LOCKED ){
int eState = pPager->eState;
+5 -5
View File
@@ -46,8 +46,8 @@ typedef struct PgHdr DbPage;
** Page number PAGER_MJ_PGNO is never used in an SQLite database (it is
** reserved for working around a windows/posix incompatibility). It is
** used in the journal to signify that the remainder of the journal file
** is devoted to storing a master journal name - there are no more pages to
** roll back. See comments for function writeMasterJournal() in pager.c
** is devoted to storing a super-journal name - there are no more pages to
** roll back. See comments for function writeSuperJournal() in pager.c
** for details.
*/
#define PAGER_MJ_PGNO(x) ((Pgno)((PENDING_BYTE/((x)->pageSize))+1))
@@ -128,7 +128,7 @@ int sqlite3PagerReadFileheader(Pager*, int, unsigned char*);
/* Functions used to configure a Pager object. */
void sqlite3PagerSetBusyHandler(Pager*, int(*)(void *), void *);
int sqlite3PagerSetPagesize(Pager*, u32*, int);
int sqlite3PagerMaxPageCount(Pager*, int);
Pgno sqlite3PagerMaxPageCount(Pager*, Pgno);
void sqlite3PagerSetCachesize(Pager*, int);
int sqlite3PagerSetSpillsize(Pager*, int);
void sqlite3PagerSetMmapLimit(Pager *, sqlite3_int64);
@@ -161,9 +161,9 @@ void *sqlite3PagerGetExtra(DbPage *);
/* Functions used to manage pager transactions and savepoints. */
void sqlite3PagerPagecount(Pager*, int*);
int sqlite3PagerBegin(Pager*, int exFlag, int);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zMaster, int);
int sqlite3PagerCommitPhaseOne(Pager*,const char *zSuper, int);
int sqlite3PagerExclusiveLock(Pager*);
int sqlite3PagerSync(Pager *pPager, const char *zMaster);
int sqlite3PagerSync(Pager *pPager, const char *zSuper);
int sqlite3PagerCommitPhaseTwo(Pager*);
int sqlite3PagerRollback(Pager*);
int sqlite3PagerOpenSavepoint(Pager *pPager, int n);
+51 -20
View File
@@ -111,6 +111,27 @@ static void disableLookaside(Parse *pParse){
DisableLookaside;
}
#if !defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) \
&& defined(SQLITE_UDL_CAPABLE_PARSER)
/*
** Issue an error message if an ORDER BY or LIMIT clause occurs on an
** UPDATE or DELETE statement.
*/
static void updateDeleteLimitError(
Parse *pParse,
ExprList *pOrderBy,
Expr *pLimit
){
if( pOrderBy ){
sqlite3ErrorMsg(pParse, "syntax error near \"ORDER BY\"");
}else{
sqlite3ErrorMsg(pParse, "syntax error near \"LIMIT\"");
}
sqlite3ExprListDelete(pParse->db, pOrderBy);
sqlite3ExprDelete(pParse->db, pLimit);
}
#endif /* SQLITE_ENABLE_UPDATE_DELETE_LIMIT */
} // end %include
// Input is a single SQL command
@@ -448,7 +469,7 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
//////////////////////// The SELECT statement /////////////////////////////////
//
cmd ::= select(X). {
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0};
SelectDest dest = {SRT_Output, 0, 0, 0, 0, 0, 0};
sqlite3Select(pParse, X, &dest);
sqlite3SelectDelete(pParse->db, X);
}
@@ -637,7 +658,7 @@ as(X) ::= . {X.n = 0; X.z = 0;}
// A complete FROM clause.
//
from(A) ::= . {A = sqlite3DbMallocZero(pParse->db, sizeof(*A));}
from(A) ::= . {A = 0;}
from(A) ::= FROM seltablist(X). {
A = X;
sqlite3SrcListShiftJoinType(A);
@@ -840,18 +861,20 @@ limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y).
/////////////////////////// The DELETE statement /////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
%if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W)
orderby_opt(O) limit_opt(L). {
sqlite3SrcListIndexedBy(pParse, X, &I);
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
sqlite3ExprListDelete(pParse->db, O); O = 0;
sqlite3ExprDelete(pParse->db, L); L = 0;
if( O || L ){
updateDeleteLimitError(pParse,O,L);
O = 0;
L = 0;
}
#endif
sqlite3DeleteFrom(pParse,X,W,O,L);
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
%else
cmd ::= with DELETE FROM xfullname(X) indexed_opt(I) where_opt(W). {
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3DeleteFrom(pParse,X,W,0,0);
@@ -866,23 +889,33 @@ where_opt(A) ::= WHERE expr(X). {A = X;}
////////////////////////// The UPDATE command ////////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y)
%if SQLITE_ENABLE_UPDATE_DELETE_LIMIT || SQLITE_UDL_CAPABLE_PARSER
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
where_opt(W) orderby_opt(O) limit_opt(L). {
sqlite3SrcListIndexedBy(pParse, X, &I);
X = sqlite3SrcListAppendList(pParse, X, F);
sqlite3ExprListCheckLength(pParse,Y,"set list");
#ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
if( O || L ){
updateDeleteLimitError(pParse,O,L);
O = 0;
L = 0;
}
#endif
sqlite3Update(pParse,X,Y,W,R,O,L,0);
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y)
where_opt(W). {
%else
cmd ::= with UPDATE orconf(R) xfullname(X) indexed_opt(I) SET setlist(Y) from(F)
where_opt(W). {
sqlite3SrcListIndexedBy(pParse, X, &I);
sqlite3ExprListCheckLength(pParse,Y,"set list");
X = sqlite3SrcListAppendList(pParse, X, F);
sqlite3Update(pParse,X,Y,W,R,0,0,0);
}
%endif
%type setlist {ExprList*}
%destructor setlist {sqlite3ExprListDelete(pParse->db, $$);}
@@ -1315,7 +1348,7 @@ uniqueflag(A) ::= . {A = OE_None;}
//
// IMPORTANT COMPATIBILITY NOTE: Some prior versions of SQLite accepted
// COLLATE clauses and ASC or DESC keywords on ID lists in inappropriate
// places - places that might have been stored in the sqlite_master schema.
// places - places that might have been stored in the sqlite_schema table.
// Those extra features were ignored. But because they might be in some
// (busted) old databases, we need to continue parsing them when loading
// historical schemas.
@@ -1370,16 +1403,14 @@ cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
///////////////////////////// The VACUUM command /////////////////////////////
//
%ifndef SQLITE_OMIT_VACUUM
%ifndef SQLITE_OMIT_ATTACH
%if !SQLITE_OMIT_VACUUM && !SQLITE_OMIT_ATTACH
%type vinto {Expr*}
%destructor vinto {sqlite3ExprDelete(pParse->db, $$);}
cmd ::= VACUUM vinto(Y). {sqlite3Vacuum(pParse,0,Y);}
cmd ::= VACUUM nm(X) vinto(Y). {sqlite3Vacuum(pParse,&X,Y);}
vinto(A) ::= INTO expr(X). {A = X;}
vinto(A) ::= . {A = 0;}
%endif SQLITE_OMIT_ATTACH
%endif SQLITE_OMIT_VACUUM
%endif
///////////////////////////// The PRAGMA command /////////////////////////////
//
@@ -1486,8 +1517,8 @@ tridxby ::= NOT INDEXED. {
%destructor trigger_cmd {sqlite3DeleteTriggerStep(pParse->db, $$);}
// UPDATE
trigger_cmd(A) ::=
UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) where_opt(Z) scanpt(E).
{A = sqlite3TriggerUpdateStep(pParse, &X, Y, Z, R, B.z, E);}
UPDATE(B) orconf(R) trnm(X) tridxby SET setlist(Y) from(F) where_opt(Z) scanpt(E).
{A = sqlite3TriggerUpdateStep(pParse, &X, F, Y, Z, R, B.z, E);}
// INSERT
trigger_cmd(A) ::= scanpt(B) insert_cmd(R) INTO
+46 -16
View File
@@ -611,13 +611,19 @@ void sqlite3Pragma(
*/
case PragTyp_PAGE_COUNT: {
int iReg;
i64 x = 0;
sqlite3CodeVerifySchema(pParse, iDb);
iReg = ++pParse->nMem;
if( sqlite3Tolower(zLeft[0])=='p' ){
sqlite3VdbeAddOp2(v, OP_Pagecount, iDb, iReg);
}else{
sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg,
sqlite3AbsInt32(sqlite3Atoi(zRight)));
if( zRight && sqlite3DecOrHexToI64(zRight,&x)==0 ){
if( x<0 ) x = 0;
else if( x>0xfffffffe ) x = 0xfffffffe;
}else{
x = 0;
}
sqlite3VdbeAddOp3(v, OP_MaxPgcnt, iDb, iReg, (int)x);
}
sqlite3VdbeAddOp2(v, OP_ResultRow, iReg, 1);
break;
@@ -1138,15 +1144,14 @@ void sqlite3Pragma(
*/
case PragTyp_TABLE_INFO: if( zRight ){
Table *pTab;
sqlite3CodeVerifyNamedSchema(pParse, zDb);
pTab = sqlite3LocateTable(pParse, LOCATE_NOERR, zRight, zDb);
if( pTab ){
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
int i, k;
int nHidden = 0;
Column *pCol;
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
pParse->nMem = 7;
sqlite3CodeVerifySchema(pParse, iTabDb);
sqlite3ViewGetColumnNames(pParse, pTab);
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
int isHidden = 0;
@@ -1403,7 +1408,6 @@ void sqlite3Pragma(
regRow = ++pParse->nMem;
k = sqliteHashFirst(&db->aDb[iDb].pSchema->tblHash);
while( k ){
int iTabDb;
if( zRight ){
pTab = sqlite3LocateTable(pParse, 0, zRight, zDb);
k = 0;
@@ -1412,23 +1416,24 @@ void sqlite3Pragma(
k = sqliteHashNext(k);
}
if( pTab==0 || pTab->pFKey==0 ) continue;
iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3CodeVerifySchema(pParse, iTabDb);
sqlite3TableLock(pParse, iTabDb, pTab->tnum, 0, pTab->zName);
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
zDb = db->aDb[iDb].zDbSName;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow;
sqlite3OpenTable(pParse, 0, iTabDb, pTab, OP_OpenRead);
sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead);
sqlite3VdbeLoadString(v, regResult, pTab->zName);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue;
pIdx = 0;
sqlite3TableLock(pParse, iTabDb, pParent->tnum, 0, pParent->zName);
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
if( x==0 ){
if( pIdx==0 ){
sqlite3OpenTable(pParse, i, iTabDb, pParent, OP_OpenRead);
sqlite3OpenTable(pParse, i, iDb, pParent, OP_OpenRead);
}else{
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iTabDb);
sqlite3VdbeAddOp3(v, OP_OpenRead, i, pIdx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
}
}else{
@@ -1521,9 +1526,22 @@ void sqlite3Pragma(
** integrity_check designed to detect most database corruption
** without the overhead of cross-checking indexes. Quick_check
** is linear time wherease integrity_check is O(NlogN).
**
** The maximum nubmer of errors is 100 by default. A different default
** can be specified using a numeric parameter N.
**
** Or, the parameter N can be the name of a table. In that case, only
** the one table named is verified. The freelist is only verified if
** the named table is "sqlite_schema" (or one of its aliases).
**
** All schemas are checked by default. To check just a single
** schema, use the form:
**
** PRAGMA schema.integrity_check;
*/
case PragTyp_INTEGRITY_CHECK: {
int i, j, addr, mxErr;
Table *pObjTab = 0; /* Check only this one table, if not NULL */
int isQuick = (sqlite3Tolower(zLeft[0])=='q');
@@ -1546,9 +1564,13 @@ void sqlite3Pragma(
/* Set the maximum error count */
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
if( zRight ){
sqlite3GetInt32(zRight, &mxErr);
if( mxErr<=0 ){
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
if( sqlite3GetInt32(zRight, &mxErr) ){
if( mxErr<=0 ){
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
}else{
pObjTab = sqlite3LocateTable(pParse, 0, zRight,
iDb>=0 ? db->aDb[iDb].zDbSName : 0);
}
}
sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
@@ -1577,15 +1599,21 @@ void sqlite3Pragma(
Table *pTab = sqliteHashData(x); /* Current table */
Index *pIdx; /* An index on pTab */
int nIdx; /* Number of indexes on pTab */
if( pObjTab && pObjTab!=pTab ) continue;
if( HasRowid(pTab) ) cnt++;
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
if( nIdx>mxIdx ) mxIdx = nIdx;
}
if( cnt==0 ) continue;
if( pObjTab ) cnt++;
aRoot = sqlite3DbMallocRawNN(db, sizeof(int)*(cnt+1));
if( aRoot==0 ) break;
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
cnt = 0;
if( pObjTab ) aRoot[++cnt] = 0;
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx;
if( pObjTab && pObjTab!=pTab ) continue;
if( HasRowid(pTab) ) aRoot[++cnt] = pTab->tnum;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
aRoot[++cnt] = pIdx->tnum;
@@ -1619,6 +1647,7 @@ void sqlite3Pragma(
int r1 = -1;
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
if( pObjTab && pObjTab!=pTab ) continue;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
@@ -1890,6 +1919,7 @@ void sqlite3Pragma(
aOp[1].p1 = iDb;
aOp[1].p2 = iCookie;
aOp[1].p3 = sqlite3Atoi(zRight);
aOp[1].p5 = 1;
}else{
/* Read the specified cookie value */
static const VdbeOpList readCookie[] = {
+1 -1
View File
@@ -281,7 +281,7 @@ static const PragmaName aPragmaName[] = {
#if !defined(SQLITE_OMIT_FOREIGN_KEY) && !defined(SQLITE_OMIT_TRIGGER)
{/* zName: */ "foreign_key_check",
/* ePragTyp: */ PragTyp_FOREIGN_KEY_CHECK,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0,
/* ePragFlg: */ PragFlg_NeedSchema|PragFlg_Result0|PragFlg_Result1|PragFlg_SchemaOpt,
/* ColNames: */ 37, 4,
/* iArg: */ 0 },
#endif
+30 -16
View File
@@ -115,7 +115,13 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
assert( db->init.busy );
db->init.iDb = iDb;
db->init.newTnum = sqlite3Atoi(argv[3]);
if( sqlite3GetUInt32(argv[3], &db->init.newTnum)==0
|| (db->init.newTnum>pData->mxPage && pData->mxPage>0)
){
if( sqlite3Config.bExtraSchemaChecks ){
corruptSchema(pData, argv[1], "invalid rootpage");
}
}
db->init.orphanTrigger = 0;
db->init.azInit = argv;
pStmt = 0;
@@ -148,12 +154,17 @@ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **NotUsed){
*/
Index *pIndex;
pIndex = sqlite3FindIndex(db, argv[1], db->aDb[iDb].zDbSName);
if( pIndex==0
|| sqlite3GetInt32(argv[3],&pIndex->tnum)==0
if( pIndex==0 ){
corruptSchema(pData, argv[1], "orphan index");
}else
if( sqlite3GetUInt32(argv[3],&pIndex->tnum)==0
|| pIndex->tnum<2
|| pIndex->tnum>pData->mxPage
|| sqlite3IndexHasDuplicateRootPage(pIndex)
){
corruptSchema(pData, argv[1], pIndex?"invalid rootpage":"orphan index");
if( sqlite3Config.bExtraSchemaChecks ){
corruptSchema(pData, argv[1], "invalid rootpage");
}
}
}
return 0;
@@ -177,7 +188,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
char const *azArg[6];
int meta[5];
InitData initData;
const char *zMasterName;
const char *zSchemaTabName;
int openedTransaction = 0;
int mask = ((db->mDbFlags & DBFLAG_EncodingFixed) | ~DBFLAG_EncodingFixed);
@@ -189,13 +200,13 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
db->init.busy = 1;
/* Construct the in-memory representation schema tables (sqlite_master or
** sqlite_temp_master) by invoking the parser directly. The appropriate
/* Construct the in-memory representation schema tables (sqlite_schema or
** sqlite_temp_schema) by invoking the parser directly. The appropriate
** table name will be inserted automatically by the parser so we can just
** use the abbreviation "x" here. The parser will also automatically tag
** the schema table as read-only. */
azArg[0] = "table";
azArg[1] = zMasterName = SCHEMA_TABLE(iDb);
azArg[1] = zSchemaTabName = SCHEMA_TABLE(iDb);
azArg[2] = azArg[1];
azArg[3] = "1";
azArg[4] = "CREATE TABLE x(type text,name text,tbl_name text,"
@@ -207,6 +218,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
initData.pzErrMsg = pzErrMsg;
initData.mInitFlags = mFlags;
initData.nInitRow = 0;
initData.mxPage = 0;
sqlite3InitCallback(&initData, 5, (char **)azArg, 0);
db->mDbFlags &= mask;
if( initData.rc ){
@@ -329,11 +341,12 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
/* Read the schema information out of the schema tables
*/
assert( db->init.busy );
initData.mxPage = sqlite3BtreeLastPage(pDb->pBt);
{
char *zSql;
zSql = sqlite3MPrintf(db,
"SELECT*FROM\"%w\".%s ORDER BY rowid",
db->aDb[iDb].zDbSName, zMasterName);
db->aDb[iDb].zDbSName, zSchemaTabName);
#ifndef SQLITE_OMIT_AUTHORIZATION
{
sqlite3_xauth xAuth;
@@ -363,7 +376,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
** current sqlite3_prepare() operation will fail, but the following one
** will attempt to compile the supplied statement against whatever subset
** of the schema was loaded before the error occurred. The primary
** purpose of this is to allow access to the sqlite_master table
** purpose of this is to allow access to the sqlite_schema table
** even when its contents have been corrupted.
*/
DbSetProperty(db, iDb, DB_SchemaLoaded);
@@ -504,17 +517,18 @@ static void schemaIsValid(Parse *pParse){
** attached database is returned.
*/
int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
int i = -1000000;
int i = -32768;
/* If pSchema is NULL, then return -1000000. This happens when code in
/* If pSchema is NULL, then return -32768. This happens when code in
** expr.c is trying to resolve a reference to a transient table (i.e. one
** created by a sub-select). In this case the return value of this
** function should never be used.
**
** We return -1000000 instead of the more usual -1 simply because using
** -1000000 as the incorrect index into db->aDb[] is much
** We return -32768 instead of the more usual -1 simply because using
** -32768 as the incorrect index into db->aDb[] is much
** more likely to cause a segfault than -1 (of course there are assert()
** statements too, but it never hurts to play the odds).
** statements too, but it never hurts to play the odds) and
** -32768 will still fit into a 16-bit signed integer.
*/
assert( sqlite3_mutex_held(db->mutex) );
if( pSchema ){
@@ -742,7 +756,7 @@ static int sqlite3LockAndPrepare(
**
** If the statement is successfully recompiled, return SQLITE_OK. Otherwise,
** if the statement cannot be recompiled because another connection has
** locked the sqlite3_master table, return SQLITE_LOCKED. If any other error
** locked the sqlite3_schema table, return SQLITE_LOCKED. If any other error
** occurs, return SQLITE_SCHEMA.
*/
int sqlite3Reprepare(Vdbe *p){
+2 -2
View File
@@ -407,11 +407,11 @@ void sqlite3_str_vappendf(
case etPOINTER:
flag_long = sizeof(char*)==sizeof(i64) ? 2 :
sizeof(char*)==sizeof(long int) ? 1 : 0;
/* Fall through into the next case */
/* no break */ deliberate_fall_through
case etORDINAL:
case etRADIX:
cThousand = 0;
/* Fall through into the next case */
/* no break */ deliberate_fall_through
case etDECIMAL:
if( infop->flags & FLAG_SIGNED ){
i64 v;
+14 -11
View File
@@ -16,6 +16,11 @@
*/
#include "sqliteInt.h"
/*
** Magic table number to mean the EXCLUDED table in an UPSERT statement.
*/
#define EXCLUDED_TABLE_NUMBER 2
/*
** Walk the expression tree pExpr and increase the aggregate function
** depth (the Expr.op2 field) by N on every TK_AGG_FUNCTION node.
@@ -386,7 +391,7 @@ static int lookupName(
Upsert *pUpsert = pNC->uNC.pUpsert;
if( pUpsert && sqlite3StrICmp("excluded",zTab)==0 ){
pTab = pUpsert->pUpsertSrc->a[0].pTab;
pExpr->iTable = 2;
pExpr->iTable = EXCLUDED_TABLE_NUMBER;
}
}
#endif /* SQLITE_OMIT_UPSERT */
@@ -411,14 +416,15 @@ static int lookupName(
if( iCol<pTab->nCol ){
cnt++;
#ifndef SQLITE_OMIT_UPSERT
if( pExpr->iTable==2 ){
if( pExpr->iTable==EXCLUDED_TABLE_NUMBER ){
testcase( iCol==(-1) );
if( IN_RENAME_OBJECT ){
pExpr->iColumn = iCol;
pExpr->y.pTab = pTab;
eNewExprOp = TK_COLUMN;
}else{
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
pExpr->iTable = pNC->uNC.pUpsert->regData +
sqlite3TableColumnToStorage(pTab, iCol);
eNewExprOp = TK_REGISTER;
ExprSetProperty(pExpr, EP_Alias);
}
@@ -750,26 +756,23 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
#endif
switch( pExpr->op ){
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
/* The special operator TK_ROW means use the rowid for the first
** column in the FROM clause. This is used by the LIMIT and ORDER BY
** clause processing on UPDATE and DELETE statements.
** clause processing on UPDATE and DELETE statements, and by
** UPDATE ... FROM statement processing.
*/
case TK_ROW: {
SrcList *pSrcList = pNC->pSrcList;
struct SrcList_item *pItem;
assert( pSrcList && pSrcList->nSrc==1 );
assert( pSrcList && pSrcList->nSrc>=1 );
pItem = pSrcList->a;
assert( HasRowid(pItem->pTab) && pItem->pTab->pSelect==0 );
pExpr->op = TK_COLUMN;
pExpr->y.pTab = pItem->pTab;
pExpr->iTable = pItem->iCursor;
pExpr->iColumn = -1;
pExpr->iColumn--;
pExpr->affExpr = SQLITE_AFF_INTEGER;
break;
}
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
&& !defined(SQLITE_OMIT_SUBQUERY) */
/* A column name: ID
** Or table name and column name: ID.ID
@@ -1081,7 +1084,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
return WRC_Continue;
}
}
/* Fall thru */
/* no break */ deliberate_fall_through
}
case TK_BETWEEN:
case TK_EQ:
+121 -83
View File
@@ -14,20 +14,6 @@
*/
#include "sqliteInt.h"
/*
** Trace output macros
*/
#if SELECTTRACE_ENABLED
/***/ int sqlite3SelectTrace = 0;
# define SELECTTRACE(K,P,S,X) \
if(sqlite3SelectTrace&(K)) \
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
#endif
/*
** An instance of the following object is used to record information about
** how to process the DISTINCT keyword, to simplify passing that information
@@ -117,6 +103,7 @@ static void clearSelect(sqlite3 *db, Select *p, int bFree){
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
pDest->eDest = (u8)eDest;
pDest->iSDParm = iParm;
pDest->iSDParm2 = 0;
pDest->zAffSdst = 0;
pDest->iSdst = 0;
pDest->nSdst = 0;
@@ -138,9 +125,9 @@ Select *sqlite3SelectNew(
u32 selFlags, /* Flag parameters, such as SF_Distinct */
Expr *pLimit /* LIMIT value. NULL means not used */
){
Select *pNew;
Select *pNew, *pAllocated;
Select standin;
pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
pAllocated = pNew = sqlite3DbMallocRawNN(pParse->db, sizeof(*pNew) );
if( pNew==0 ){
assert( pParse->db->mallocFailed );
pNew = &standin;
@@ -174,12 +161,11 @@ Select *sqlite3SelectNew(
#endif
if( pParse->db->mallocFailed ) {
clearSelect(pParse->db, pNew, pNew!=&standin);
pNew = 0;
pAllocated = 0;
}else{
assert( pNew->pSrc!=0 || pParse->nErr>0 );
}
assert( pNew!=&standin );
return pNew;
return pAllocated;
}
@@ -190,21 +176,6 @@ void sqlite3SelectDelete(sqlite3 *db, Select *p){
if( OK_IF_ALWAYS_TRUE(p) ) clearSelect(db, p, 1);
}
/*
** Delete all the substructure for p, but keep p allocated. Redefine
** p to be a single SELECT where every column of the result set has a
** value of NULL.
*/
void sqlite3SelectReset(Parse *pParse, Select *p){
if( ALWAYS(p) ){
clearSelect(pParse->db, p, 0);
memset(&p->iLimit, 0, sizeof(Select) - offsetof(Select,iLimit));
p->pEList = sqlite3ExprListAppend(pParse, 0,
sqlite3ExprAlloc(pParse->db,TK_NULL,0,0));
p->pSrc = sqlite3DbMallocZero(pParse->db, sizeof(SrcList));
}
}
/*
** Return a pointer to the right-most SELECT statement in a compound.
*/
@@ -293,8 +264,10 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
*/
static int columnIndex(Table *pTab, const char *zCol){
int i;
for(i=0; i<pTab->nCol; i++){
if( sqlite3StrICmp(pTab->aCol[i].zName, zCol)==0 ) return i;
u8 h = sqlite3StrIHash(zCol);
Column *pCol;
for(pCol=pTab->aCol, i=0; i<pTab->nCol; pCol++, i++){
if( pCol->hName==h && sqlite3StrICmp(pCol->zName, zCol)==0 ) return i;
}
return -1;
}
@@ -1005,7 +978,8 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
assert( eDest==SRT_Set || eDest==SRT_Mem
|| eDest==SRT_Coroutine || eDest==SRT_Output );
|| eDest==SRT_Coroutine || eDest==SRT_Output
|| eDest==SRT_Upfrom );
}
sRowLoadInfo.regResult = regResult;
sRowLoadInfo.ecelFlags = ecelFlags;
@@ -1154,6 +1128,30 @@ static void selectInnerLoop(
break;
}
case SRT_Upfrom: {
if( pSort ){
pushOntoSorter(
pParse, pSort, p, regResult, regOrig, nResultCol, nPrefixReg);
}else{
int i2 = pDest->iSDParm2;
int r1 = sqlite3GetTempReg(pParse);
/* If the UPDATE FROM join is an aggregate that matches no rows, it
** might still be trying to return one row, because that is what
** aggregates do. Don't record that empty row in the output table. */
sqlite3VdbeAddOp2(v, OP_IsNull, regResult, iBreak); VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_MakeRecord,
regResult+(i2<0), nResultCol-(i2<0), r1);
if( i2<0 ){
sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regResult);
}else{
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regResult, i2);
}
}
break;
}
#ifndef SQLITE_OMIT_SUBQUERY
/* If we are creating a set for an "expr IN (SELECT ...)" construct,
** then there should be a single item on the stack. Write this
@@ -1178,6 +1176,7 @@ static void selectInnerLoop(
break;
}
/* If any row exist in the result set, record that fact and abort.
*/
case SRT_Exists: {
@@ -1585,6 +1584,17 @@ static void generateSortTail(
break;
}
#endif
case SRT_Upfrom: {
int i2 = pDest->iSDParm2;
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord,regRow+(i2<0),nColumn-(i2<0),r1);
if( i2<0 ){
sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, regRow);
}else{
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iParm, r1, regRow, i2);
}
break;
}
default: {
assert( eDest==SRT_Output || eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
@@ -3171,7 +3181,7 @@ static int multiSelectOrderBy(
sqlite3 *db; /* Database connection */
ExprList *pOrderBy; /* The ORDER BY clause */
int nOrderBy; /* Number of terms in the ORDER BY clause */
int *aPermute; /* Mapping from ORDER BY terms to result set columns */
u32 *aPermute; /* Mapping from ORDER BY terms to result set columns */
assert( p->pOrderBy!=0 );
assert( pKeyDup==0 ); /* "Managed" code needs this. Ticket #3382. */
@@ -3220,7 +3230,7 @@ static int multiSelectOrderBy(
** to the right and the left are evaluated, they use the correct
** collation.
*/
aPermute = sqlite3DbMallocRawNN(db, sizeof(int)*(nOrderBy + 1));
aPermute = sqlite3DbMallocRawNN(db, sizeof(u32)*(nOrderBy + 1));
if( aPermute ){
struct ExprList_item *pItem;
aPermute[0] = nOrderBy;
@@ -4176,7 +4186,7 @@ static int flattenSubquery(
sqlite3SelectDelete(db, pSub1);
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After flattening:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -4999,8 +5009,8 @@ static int selectExpander(Walker *pWalker, Select *p){
for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
Table *pTab;
assert( pFrom->fg.isRecursive==0 || pFrom->pTab!=0 );
if( pFrom->fg.isRecursive ) continue;
assert( pFrom->pTab==0 );
if( pFrom->pTab ) continue;
assert( pFrom->fg.isRecursive==0 );
#ifndef SQLITE_OMIT_CTE
if( withExpand(pWalker, pFrom) ) return WRC_Abort;
if( pFrom->pTab ) {} else
@@ -5388,7 +5398,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
struct AggInfo_func *pFunc;
int nReg = pAggInfo->nFunc + pAggInfo->nColumn;
if( nReg==0 ) return;
if( pParse->nErr ) return;
if( pParse->nErr || pParse->db->mallocFailed ) return;
#ifdef SQLITE_DEBUG
/* Verify that all AggInfo registers are within the range specified by
** AggInfo.mnReg..AggInfo.mxReg */
@@ -5405,7 +5415,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
sqlite3VdbeAddOp3(v, OP_Null, 0, pAggInfo->mnReg, pAggInfo->mxReg);
for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
if( pFunc->iDistinct>=0 ){
Expr *pE = pFunc->pExpr;
Expr *pE = pFunc->pFExpr;
assert( !ExprHasProperty(pE, EP_xIsSelect) );
if( pE->x.pList==0 || pE->x.pList->nExpr!=1 ){
sqlite3ErrorMsg(pParse, "DISTINCT aggregates must have exactly one "
@@ -5429,8 +5439,8 @@ static void finalizeAggFunctions(Parse *pParse, AggInfo *pAggInfo){
int i;
struct AggInfo_func *pF;
for(i=0, pF=pAggInfo->aFunc; i<pAggInfo->nFunc; i++, pF++){
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
ExprList *pList = pF->pFExpr->x.pList;
assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
sqlite3VdbeAddOp2(v, OP_AggFinal, pF->iMem, pList ? pList->nExpr : 0);
sqlite3VdbeAppendP4(v, pF->pFunc, P4_FUNCDEF);
}
@@ -5459,22 +5469,26 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
int nArg;
int addrNext = 0;
int regAgg;
ExprList *pList = pF->pExpr->x.pList;
assert( !ExprHasProperty(pF->pExpr, EP_xIsSelect) );
assert( !IsWindowFunc(pF->pExpr) );
if( ExprHasProperty(pF->pExpr, EP_WinFunc) ){
Expr *pFilter = pF->pExpr->y.pWin->pFilter;
ExprList *pList = pF->pFExpr->x.pList;
assert( !ExprHasProperty(pF->pFExpr, EP_xIsSelect) );
assert( !IsWindowFunc(pF->pFExpr) );
if( ExprHasProperty(pF->pFExpr, EP_WinFunc) ){
Expr *pFilter = pF->pFExpr->y.pWin->pFilter;
if( pAggInfo->nAccumulator
&& (pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
&& regAcc
){
/* If regAcc==0, there there exists some min() or max() function
** without a FILTER clause that will ensure the magnet registers
** are populated. */
if( regHit==0 ) regHit = ++pParse->nMem;
/* If this is the first row of the group (regAcc==0), clear the
/* If this is the first row of the group (regAcc contains 0), clear the
** "magnet" register regHit so that the accumulator registers
** are populated if the FILTER clause jumps over the the
** invocation of min() or max() altogether. Or, if this is not
** the first row (regAcc==1), set the magnet register so that the
** accumulators are not populated unless the min()/max() is invoked and
** indicates that they should be. */
** the first row (regAcc contains 1), set the magnet register so that
** the accumulators are not populated unless the min()/max() is invoked
** and indicates that they should be. */
sqlite3VdbeAddOp2(v, OP_Copy, regAcc, regHit);
}
addrNext = sqlite3VdbeMakeLabel(pParse);
@@ -5525,7 +5539,7 @@ static void updateAccumulator(Parse *pParse, int regAcc, AggInfo *pAggInfo){
addrHitTest = sqlite3VdbeAddOp1(v, OP_If, regHit); VdbeCoverage(v);
}
for(i=0, pC=pAggInfo->aCol; i<pAggInfo->nAccumulator; i++, pC++){
sqlite3ExprCode(pParse, pC->pExpr, pC->iMem);
sqlite3ExprCode(pParse, pC->pCExpr, pC->iMem);
}
pAggInfo->directMode = 0;
@@ -5610,7 +5624,7 @@ static void havingToWhere(Parse *pParse, Select *p){
sWalker.u.pSelect = p;
sqlite3WalkExpr(&sWalker, p->pHaving);
#if SELECTTRACE_ENABLED
if( sWalker.eCode && (sqlite3SelectTrace & 0x100)!=0 ){
if( sWalker.eCode && (sqlite3_unsupported_selecttrace & 0x100)!=0 ){
SELECTTRACE(0x100,pParse,p,("Move HAVING terms into WHERE:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5732,7 +5746,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
p->selFlags &= ~SF_Aggregate;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After count-of-view optimization:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5785,7 +5799,7 @@ int sqlite3Select(
if( sqlite3AuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;
#if SELECTTRACE_ENABLED
SELECTTRACE(1,pParse,p, ("begin processing:\n", pParse->addrExplain));
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -5812,12 +5826,30 @@ int sqlite3Select(
}
assert( p->pEList!=0 );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x104 ){
if( sqlite3_unsupported_selecttrace & 0x104 ){
SELECTTRACE(0x104,pParse,p, ("after name resolution:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
#endif
/* If the SF_UpdateFrom flag is set, then this function is being called
** as part of populating the temp table for an UPDATE...FROM statement.
** In this case, it is an error if the target object (pSrc->a[0]) name
** or alias is duplicated within FROM clause (pSrc->a[1..n]). */
if( p->selFlags & SF_UpdateFrom ){
struct SrcList_item *p0 = &p->pSrc->a[0];
for(i=1; i<p->pSrc->nSrc; i++){
struct SrcList_item *p1 = &p->pSrc->a[i];
if( p0->pTab==p1->pTab && 0==sqlite3_stricmp(p0->zAlias, p1->zAlias) ){
sqlite3ErrorMsg(pParse,
"target object/alias may not appear in FROM clause: %s",
p0->zAlias ? p0->zAlias : p0->pTab->zName
);
goto select_end;
}
}
}
if( pDest->eDest==SRT_Output ){
generateColumnNames(pParse, p);
}
@@ -5829,7 +5861,7 @@ int sqlite3Select(
goto select_end;
}
#if SELECTTRACE_ENABLED
if( p->pWin && (sqlite3SelectTrace & 0x108)!=0 ){
if( p->pWin && (sqlite3_unsupported_selecttrace & 0x108)!=0 ){
SELECTTRACE(0x104,pParse,p, ("after window rewrite:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -5840,7 +5872,7 @@ int sqlite3Select(
memset(&sSort, 0, sizeof(sSort));
sSort.pOrderBy = p->pOrderBy;
/* Try to various optimizations (flattening subqueries, and strength
/* Try to do various optimizations (flattening subqueries, and strength
** reduction of join operators) in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@@ -5849,6 +5881,11 @@ int sqlite3Select(
Select *pSub = pItem->pSelect;
Table *pTab = pItem->pTab;
/* The expander should have already created transient Table objects
** even for FROM clause elements such as subqueries that do not correspond
** to a real table */
assert( pTab!=0 );
/* Convert LEFT JOIN into JOIN if there are terms of the right table
** of the LEFT JOIN used in the WHERE clause.
*/
@@ -5931,7 +5968,7 @@ int sqlite3Select(
rc = multiSelect(pParse, p, pDest);
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end compound-select processing\n"));
if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
@@ -5950,7 +5987,7 @@ int sqlite3Select(
&& propagateConstants(pParse, p)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,("After constant propagation:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6038,7 +6075,7 @@ int sqlite3Select(
(pItem->fg.jointype & JT_OUTER)!=0)
){
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x100 ){
if( sqlite3_unsupported_selecttrace & 0x100 ){
SELECTTRACE(0x100,pParse,p,
("After WHERE-clause push-down into subquery %d:\n", pSub->selId));
sqlite3TreeViewSelect(0, p, 0);
@@ -6138,7 +6175,7 @@ int sqlite3Select(
sDistinct.isTnct = (p->selFlags & SF_Distinct)!=0;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("After all FROM-clause analysis:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6174,7 +6211,7 @@ int sqlite3Select(
assert( sDistinct.isTnct );
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
SELECTTRACE(0x400,pParse,p,("Transform DISTINCT into GROUP BY:\n"));
sqlite3TreeViewSelect(0, p, 0);
}
@@ -6240,7 +6277,7 @@ int sqlite3Select(
u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0)
| (p->selFlags & SF_FixedLimit);
#ifndef SQLITE_OMIT_WINDOWFUNC
Window *pWin = p->pWin; /* Master window object (or NULL) */
Window *pWin = p->pWin; /* Main window object (or NULL) */
if( pWin ){
sqlite3WindowCodeInit(pParse, p);
}
@@ -6379,6 +6416,7 @@ int sqlite3Select(
}
pAggInfo->pNext = pParse->pAggList;
pParse->pAggList = pAggInfo;
pAggInfo->selId = p->selId;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pParse;
sNC.pSrcList = pTabList;
@@ -6401,12 +6439,12 @@ int sqlite3Select(
}
pAggInfo->nAccumulator = pAggInfo->nColumn;
if( p->pGroupBy==0 && p->pHaving==0 && pAggInfo->nFunc==1 ){
minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pExpr, &pMinMaxOrderBy);
minMaxFlag = minMaxQuery(db, pAggInfo->aFunc[0].pFExpr, &pMinMaxOrderBy);
}else{
minMaxFlag = WHERE_ORDERBY_NORMAL;
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pExpr;
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
sNC.ncFlags |= NC_InAggFunc;
sqlite3ExprAnalyzeAggList(&sNC, pExpr->x.pList);
@@ -6421,19 +6459,19 @@ int sqlite3Select(
pAggInfo->mxReg = pParse->nMem;
if( db->mallocFailed ) goto select_end;
#if SELECTTRACE_ENABLED
if( sqlite3SelectTrace & 0x400 ){
if( sqlite3_unsupported_selecttrace & 0x400 ){
int ii;
SELECTTRACE(0x400,pParse,p,("After aggregate analysis %p:\n", pAggInfo));
sqlite3TreeViewSelect(0, p, 0);
for(ii=0; ii<pAggInfo->nColumn; ii++){
sqlite3DebugPrintf("agg-column[%d] iMem=%d\n",
ii, pAggInfo->aCol[ii].iMem);
sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pExpr, 0);
sqlite3TreeViewExpr(0, pAggInfo->aCol[ii].pCExpr, 0);
}
for(ii=0; ii<pAggInfo->nFunc; ii++){
sqlite3DebugPrintf("agg-func[%d]: iMem=%d\n",
ii, pAggInfo->aFunc[ii].iMem);
sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pExpr, 0);
sqlite3TreeViewExpr(0, pAggInfo->aFunc[ii].pFExpr, 0);
}
}
#endif
@@ -6685,7 +6723,7 @@ int sqlite3Select(
Index *pIdx; /* Iterator variable */
KeyInfo *pKeyInfo = 0; /* Keyinfo for scanned index */
Index *pBest = 0; /* Best index found so far */
int iRoot = pTab->tnum; /* Root page of scanned b-tree */
Pgno iRoot = pTab->tnum; /* Root page of scanned b-tree */
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
@@ -6717,7 +6755,7 @@ int sqlite3Select(
}
/* Open a read-only cursor, execute the OP_Count, close the cursor. */
sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, iRoot, iDb, 1);
sqlite3VdbeAddOp4Int(v, OP_OpenRead, iCsr, (int)iRoot, iDb, 1);
if( pKeyInfo ){
sqlite3VdbeChangeP4(v, -1, (char *)pKeyInfo, P4_KEYINFO);
}
@@ -6726,6 +6764,7 @@ int sqlite3Select(
explainSimpleCount(pParse, pTab, pBest);
}else{
int regAcc = 0; /* "populate accumulators" flag */
int addrSkip;
/* If there are accumulator registers but no min() or max() functions
** without FILTER clauses, allocate register regAcc. Register regAcc
@@ -6738,7 +6777,7 @@ int sqlite3Select(
** function visits zero rows. */
if( pAggInfo->nAccumulator ){
for(i=0; i<pAggInfo->nFunc; i++){
if( ExprHasProperty(pAggInfo->aFunc[i].pExpr, EP_WinFunc) ){
if( ExprHasProperty(pAggInfo->aFunc[i].pFExpr, EP_WinFunc) ){
continue;
}
if( pAggInfo->aFunc[i].pFunc->funcFlags&SQLITE_FUNC_NEEDCOLL ){
@@ -6774,10 +6813,9 @@ int sqlite3Select(
}
updateAccumulator(pParse, regAcc, pAggInfo);
if( regAcc ) sqlite3VdbeAddOp2(v, OP_Integer, 1, regAcc);
if( sqlite3WhereIsOrdered(pWInfo)>0 ){
sqlite3VdbeGoto(v, sqlite3WhereBreakLabel(pWInfo));
VdbeComment((v, "%s() by index",
(minMaxFlag==WHERE_ORDERBY_MIN?"min":"max")));
addrSkip = sqlite3WhereOrderByLimitOptLabel(pWInfo);
if( addrSkip!=sqlite3WhereContinueLabel(pWInfo) ){
sqlite3VdbeGoto(v, addrSkip);
}
sqlite3WhereEnd(pWInfo);
finalizeAggFunctions(pParse, pAggInfo);
@@ -6822,14 +6860,14 @@ select_end:
#ifdef SQLITE_DEBUG
if( pAggInfo && !db->mallocFailed ){
for(i=0; i<pAggInfo->nColumn; i++){
Expr *pExpr = pAggInfo->aCol[i].pExpr;
Expr *pExpr = pAggInfo->aCol[i].pCExpr;
assert( pExpr!=0 || db->mallocFailed );
if( pExpr==0 ) continue;
assert( pExpr->pAggInfo==pAggInfo );
assert( pExpr->iAgg==i );
}
for(i=0; i<pAggInfo->nFunc; i++){
Expr *pExpr = pAggInfo->aFunc[i].pExpr;
Expr *pExpr = pAggInfo->aFunc[i].pFExpr;
assert( pExpr!=0 || db->mallocFailed );
if( pExpr==0 ) continue;
assert( pExpr->pAggInfo==pAggInfo );
@@ -6840,7 +6878,7 @@ select_end:
#if SELECTTRACE_ENABLED
SELECTTRACE(0x1,pParse,p,("end processing\n"));
if( (sqlite3SelectTrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
if( (sqlite3_unsupported_selecttrace & 0x2000)!=0 && ExplainQueryPlanParent(pParse)==0 ){
sqlite3TreeViewSelect(0, p, 0);
}
#endif
+523 -154
View File
File diff suppressed because it is too large Load Diff
+16 -10
View File
@@ -564,7 +564,7 @@ int sqlite3_exec(
#define SQLITE_OPEN_MAIN_JOURNAL 0x00000800 /* VFS only */
#define SQLITE_OPEN_TEMP_JOURNAL 0x00001000 /* VFS only */
#define SQLITE_OPEN_SUBJOURNAL 0x00002000 /* VFS only */
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
#define SQLITE_OPEN_SUPER_JOURNAL 0x00004000 /* VFS only */
#define SQLITE_OPEN_NOMUTEX 0x00008000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */
#define SQLITE_OPEN_SHAREDCACHE 0x00020000 /* Ok for sqlite3_open_v2() */
@@ -573,6 +573,9 @@ int sqlite3_exec(
#define SQLITE_OPEN_NOFOLLOW 0x01000000 /* Ok for sqlite3_open_v2() */
/* Reserved: 0x00F00000 */
/* Legacy compatibility: */
#define SQLITE_OPEN_MASTER_JOURNAL 0x00004000 /* VFS only */
/*
** CAPI3REF: Device Characteristics
@@ -870,7 +873,7 @@ struct sqlite3_io_methods {
** of the xSync method. In most cases, the pointer argument passed with
** this file-control is NULL. However, if the database file is being synced
** as part of a multi-database commit, the argument points to a nul-terminated
** string containing the transactions master-journal file name. VFSes that
** string containing the transactions super-journal file name. VFSes that
** do not need this signal should silently ignore this opcode. Applications
** should not call [sqlite3_file_control()] with this opcode as doing so may
** disrupt the operation of the specialized VFSes that do require it.
@@ -1267,7 +1270,7 @@ typedef struct sqlite3_api_routines sqlite3_api_routines;
** <li> [SQLITE_OPEN_TEMP_JOURNAL]
** <li> [SQLITE_OPEN_TRANSIENT_DB]
** <li> [SQLITE_OPEN_SUBJOURNAL]
** <li> [SQLITE_OPEN_MASTER_JOURNAL]
** <li> [SQLITE_OPEN_SUPER_JOURNAL]
** <li> [SQLITE_OPEN_WAL]
** </ul>)^
**
@@ -1645,7 +1648,7 @@ int sqlite3_db_config(sqlite3*, int op, ...);
** by xInit. The pAppData pointer is used as the only parameter to
** xInit and xShutdown.
**
** SQLite holds the [SQLITE_MUTEX_STATIC_MASTER] mutex when it invokes
** SQLite holds the [SQLITE_MUTEX_STATIC_MAIN] mutex when it invokes
** the xInit method, so the xInit method need not be threadsafe. The
** xShutdown method is only called from [sqlite3_shutdown()] so it does
** not need to be threadsafe either. For all other methods, SQLite
@@ -2283,8 +2286,7 @@ struct sqlite3_mem_methods {
** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]]
** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td>
** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to
** assume that database schemas (the contents of the [sqlite_master] tables)
** are untainted by malicious content.
** assume that database schemas are untainted by malicious content.
** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite
** takes additional defensive steps to protect the application from harm
** including:
@@ -6274,7 +6276,7 @@ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** ^In the case of an update, this is the [rowid] after the update takes place.
**
** ^(The update hook is not invoked when internal system tables are
** modified (i.e. sqlite_master and sqlite_sequence).)^
** modified (i.e. sqlite_sequence).)^
** ^The update hook is not invoked when [WITHOUT ROWID] tables are modified.
**
** ^In the current implementation, the update hook
@@ -7376,7 +7378,7 @@ int sqlite3_vfs_unregister(sqlite3_vfs*);
** <ul>
** <li> SQLITE_MUTEX_FAST
** <li> SQLITE_MUTEX_RECURSIVE
** <li> SQLITE_MUTEX_STATIC_MASTER
** <li> SQLITE_MUTEX_STATIC_MAIN
** <li> SQLITE_MUTEX_STATIC_MEM
** <li> SQLITE_MUTEX_STATIC_OPEN
** <li> SQLITE_MUTEX_STATIC_PRNG
@@ -7578,7 +7580,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
*/
#define SQLITE_MUTEX_FAST 0
#define SQLITE_MUTEX_RECURSIVE 1
#define SQLITE_MUTEX_STATIC_MASTER 2
#define SQLITE_MUTEX_STATIC_MAIN 2
#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
@@ -7593,6 +7595,10 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
#define SQLITE_MUTEX_STATIC_VFS2 12 /* For use by extension VFS */
#define SQLITE_MUTEX_STATIC_VFS3 13 /* For use by application VFS */
/* Legacy compatibility: */
#define SQLITE_MUTEX_STATIC_MASTER 2
/*
** CAPI3REF: Retrieve the mutex for a database connection
** METHOD: sqlite3
@@ -9388,7 +9394,7 @@ int sqlite3_db_cacheflush(sqlite3*);
**
** ^The preupdate hook only fires for changes to real database tables; the
** preupdate hook is not invoked for changes to [virtual tables] or to
** system tables like sqlite_master or sqlite_stat1.
** system tables like sqlite_sequence or sqlite_stat1.
**
** ^The second parameter to the preupdate callback is a pointer to
** the [database connection] that registered the preupdate hook.
+78 -44
View File
@@ -128,6 +128,15 @@
# define _BSD_SOURCE
#endif
/*
** Macro to disable warnings about missing "break" at the end of a "case".
*/
#if GCC_VERSION>=7000000
# define deliberate_fall_through __attribute__((fallthrough));
#else
# define deliberate_fall_through
#endif
/*
** For MinGW, check to see if we can include the header file containing its
** version information, among other things. Normally, this internal MinGW
@@ -190,10 +199,10 @@
** WAL mode depends on atomic aligned 32-bit loads and stores in a few
** places. The following macros try to make this explicit.
*/
#ifndef __has_feature
# define __has_feature(x) 0 /* compatibility with non-clang compilers */
#ifndef __has_extension
# define __has_extension(x) 0 /* compatibility with non-clang compilers */
#endif
#if GCC_VERSION>=4007000 || __has_feature(c_atomic)
#if GCC_VERSION>=4007000 || __has_extension(c_atomic)
# define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED)
# define AtomicStore(PTR,VAL) __atomic_store_n((PTR),(VAL),__ATOMIC_RELAXED)
#else
@@ -902,6 +911,7 @@ typedef INT16_TYPE LogEst;
** compilers.
*/
#define LARGEST_INT64 (0xffffffff|(((i64)0x7fffffff)<<32))
#define LARGEST_UINT64 (0xffffffff|(((u64)0xffffffff)<<32))
#define SMALLEST_INT64 (((i64)-1) - LARGEST_INT64)
/*
@@ -979,6 +989,16 @@ typedef INT16_TYPE LogEst;
#else
# define SELECTTRACE_ENABLED 0
#endif
#if defined(SQLITE_ENABLE_SELECTTRACE)
# define SELECTTRACE_ENABLED 1
# define SELECTTRACE(K,P,S,X) \
if(sqlite3_unsupported_selecttrace&(K)) \
sqlite3DebugPrintf("%u/%d/%p: ",(S)->selId,(P)->addrExplain,(S)),\
sqlite3DebugPrintf X
#else
# define SELECTTRACE(K,P,S,X)
# define SELECTTRACE_ENABLED 0
#endif
/*
** An instance of the following structure is used to store the busy-handler
@@ -997,22 +1017,24 @@ struct BusyHandler {
};
/*
** Name of the master database table. The master database table
** is a special table that holds the names and attributes of all
** user tables and indices.
** Name of table that holds the database schema.
*/
#define MASTER_NAME "sqlite_master"
#define TEMP_MASTER_NAME "sqlite_temp_master"
#define DFLT_SCHEMA_TABLE "sqlite_master"
#define DFLT_TEMP_SCHEMA_TABLE "sqlite_temp_master"
#define ALT_SCHEMA_TABLE "sqlite_schema"
#define ALT_TEMP_SCHEMA_TABLE "sqlite_temp_schema"
/*
** The root-page of the master database table.
** The root-page of the schema table.
*/
#define MASTER_ROOT 1
#define SCHEMA_ROOT 1
/*
** The name of the schema table.
** The name of the schema table. The name is different for TEMP.
*/
#define SCHEMA_TABLE(x) ((!OMIT_TEMPDB)&&(x==1)?TEMP_MASTER_NAME:MASTER_NAME)
#define SCHEMA_TABLE(x) \
((!OMIT_TEMPDB)&&(x==1)?DFLT_TEMP_SCHEMA_TABLE:DFLT_SCHEMA_TABLE)
/*
** A convenience macro that returns the number of elements in
@@ -1033,7 +1055,7 @@ struct BusyHandler {
** pointer will work here as long as it is distinct from SQLITE_STATIC
** and SQLITE_TRANSIENT.
*/
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3MallocSize)
#define SQLITE_DYNAMIC ((sqlite3_destructor_type)sqlite3OomFault)
/*
** When SQLITE_OMIT_WSD is defined, it means that the target platform does
@@ -1173,9 +1195,9 @@ typedef int VList;
** "BusyHandler" typedefs. vdbe.h also requires a few of the opaque
** pointer types (i.e. FuncDef) defined above.
*/
#include "pager.h"
#include "btree.h"
#include "vdbe.h"
#include "pager.h"
#include "pcache.h"
#include "os.h"
#include "mutex.h"
@@ -1469,7 +1491,7 @@ struct sqlite3 {
int aLimit[SQLITE_N_LIMIT]; /* Limits */
int nMaxSorterMmap; /* Maximum size of regions mapped by sorter */
struct sqlite3InitInfo { /* Information used during initialization */
int newTnum; /* Rootpage of table being initialized */
Pgno newTnum; /* Rootpage of table being initialized */
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
unsigned orphanTrigger : 1; /* Last statement is orphaned TEMP trigger */
@@ -1484,7 +1506,10 @@ struct sqlite3 {
int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
int (*xTrace)(u32,void*,void*,void*); /* Trace function */
union {
void (*xLegacy)(void*,const char*); /* Legacy trace function */
int (*xV2)(u32,void*,void*,void*); /* V2 Trace function */
} trace;
void *pTraceArg; /* Argument to the trace function */
#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
@@ -1546,7 +1571,7 @@ struct sqlite3 {
i64 nDeferredImmCons; /* Net deferred immediate constraints */
int *pnBytesFreed; /* If not NULL, increment this in DbFree() */
#ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
/* The following variables are all protected by the STATIC_MASTER
/* The following variables are all protected by the STATIC_MAIN
** mutex, not by sqlite3.mutex. They are used by code in notify.c.
**
** When X.pUnlockConnection==Y, that means that X is waiting for Y to
@@ -1588,7 +1613,7 @@ struct sqlite3 {
** SQLITE_CkptFullFSync == PAGER_CKPT_FULLFSYNC
** SQLITE_CacheSpill == PAGER_CACHE_SPILL
*/
#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_MASTER */
#define SQLITE_WriteSchema 0x00000001 /* OK to update SQLITE_SCHEMA */
#define SQLITE_LegacyFileFmt 0x00000002 /* Create new databases in format 1 */
#define SQLITE_FullColNames 0x00000004 /* Show full column names on SELECT */
#define SQLITE_FullFSync 0x00000008 /* Use full fsync on the backend */
@@ -2108,7 +2133,7 @@ struct Table {
char *zColAff; /* String defining the affinity of each column */
ExprList *pCheck; /* All CHECK constraints */
/* ... also used as column name list in a VIEW */
int tnum; /* Root BTree page for this table */
Pgno tnum; /* Root BTree page for this table */
u32 nTabRef; /* Number of pointers to this Table */
u32 tabFlags; /* Mask of TF_* values */
i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
@@ -2382,7 +2407,7 @@ struct UnpackedRecord {
** element.
**
** While parsing a CREATE TABLE or CREATE INDEX statement in order to
** generate VDBE code (as opposed to parsing one read from an sqlite_master
** generate VDBE code (as opposed to parsing one read from an sqlite_schema
** table as part of parsing an existing database schema), transient instances
** of this structure may be created. In this case the Index.tnum variable is
** used to store the address of a VDBE instruction, not a database page
@@ -2401,7 +2426,7 @@ struct Index {
const char **azColl; /* Array of collation sequence names for index */
Expr *pPartIdxWhere; /* WHERE clause for partial indices */
ExprList *aColExpr; /* Column expressions */
int tnum; /* DB Page containing root of this index */
Pgno tnum; /* DB Page containing root of this index */
LogEst szIdxRow; /* Estimated average row size in bytes */
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
@@ -2506,7 +2531,7 @@ struct AggInfo {
ExprList *pGroupBy; /* The group by clause */
struct AggInfo_col { /* For each column used in source tables */
Table *pTab; /* Source table */
Expr *pExpr; /* The original expression */
Expr *pCExpr; /* The original expression */
int iTable; /* Cursor number of the source table */
int iMem; /* Memory location that acts as accumulator */
i16 iColumn; /* Column number within the source table */
@@ -2517,23 +2542,16 @@ struct AggInfo {
** Additional columns are used only as parameters to
** aggregate functions */
struct AggInfo_func { /* For each aggregate function */
Expr *pExpr; /* Expression encoding the function */
Expr *pFExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
int iDistinct; /* Ephemeral table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
#ifdef SQLITE_DEBUG
int iAggMagic; /* Magic number when valid */
#endif
u32 selId; /* Select to which this AggInfo belongs */
AggInfo *pNext; /* Next in list of them all */
};
/*
** Value for AggInfo.iAggMagic when the structure is valid
*/
#define AggInfoMagic 0x2059e99e
/*
** The datatype ynVar is a signed integer, either 16-bit or 32-bit.
** Usually it is 16-bits. But if SQLITE_MAX_VARIABLE_NUMBER is greater
@@ -2710,7 +2728,7 @@ struct Expr {
#define EP_Static 0x8000000 /* Held in memory not obtained from malloc() */
#define EP_IsTrue 0x10000000 /* Always has boolean value of TRUE */
#define EP_IsFalse 0x20000000 /* Always has boolean value of FALSE */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_master */
#define EP_FromDDL 0x40000000 /* Originates from sqlite_schema */
/* 0x80000000 // Available */
/*
@@ -2890,7 +2908,7 @@ struct SrcList {
unsigned isCorrelated :1; /* True if sub-query is correlated */
unsigned viaCoroutine :1; /* Implemented as a co-routine */
unsigned isRecursive :1; /* True for recursive reference in WITH */
unsigned fromDDL :1; /* Comes from sqlite_master */
unsigned fromDDL :1; /* Comes from sqlite_schema */
} fg;
int iCursor; /* The VDBE cursor number used to access this table */
Expr *pOn; /* The ON clause of a join */
@@ -3011,7 +3029,7 @@ struct NameContext {
#define NC_HasWin 0x08000 /* One or more window functions seen */
#define NC_IsDDL 0x10000 /* Resolving names in a CREATE statement */
#define NC_InAggFunc 0x20000 /* True if analyzing arguments to an agg func */
#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_master */
#define NC_FromDDL 0x40000 /* SQL text comes from sqlite_schema */
/*
** An instance of the following object describes a single ON CONFLICT
@@ -3115,6 +3133,7 @@ struct Select {
#define SF_WinRewrite 0x0100000 /* Window function rewrite accomplished */
#define SF_View 0x0200000 /* SELECT statement is a view */
#define SF_NoopOrderBy 0x0400000 /* ORDER BY is ignored for this query */
#define SF_UpdateFrom 0x0800000 /* Statement is an UPDATE...FROM */
/*
** The results of a SELECT can be distributed in several ways, as defined
@@ -3179,6 +3198,14 @@ struct Select {
** SRT_DistQueue Store results in priority queue pDest->iSDParm only if
** the same record has never been stored before. The
** index at pDest->iSDParm+1 hold all prior stores.
**
** SRT_Upfrom Store results in the temporary table already opened by
** pDest->iSDParm. If (pDest->iSDParm<0), then the temp
** table is an intkey table - in this case the first
** column returned by the SELECT is used as the integer
** key. If (pDest->iSDParm>0), then the table is an index
** table. (pDest->iSDParm) is the number of key columns in
** each index record in this case.
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
@@ -3198,14 +3225,16 @@ struct Select {
#define SRT_EphemTab 12 /* Create transient tab and store like SRT_Table */
#define SRT_Coroutine 13 /* Generate a single row of result */
#define SRT_Table 14 /* Store result as data with an automatic rowid */
#define SRT_Upfrom 15 /* Store result as data with rowid */
/*
** An instance of this object describes where to put of the results of
** a SELECT statement.
*/
struct SelectDest {
u8 eDest; /* How to dispose of the results. On of SRT_* above. */
u8 eDest; /* How to dispose of the results. One of SRT_* above. */
int iSDParm; /* A parameter used by the eDest disposal method */
int iSDParm2; /* A second parameter for 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 */
@@ -3361,9 +3390,7 @@ struct Parse {
ynVar nVar; /* Number of '?' variables seen in the SQL so far */
u8 iPkSortOrder; /* ASC or DESC for INTEGER PRIMARY KEY */
u8 explain; /* True if the EXPLAIN flag is found on the query */
#if !(defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_OMIT_ALTERTABLE))
u8 eParseMode; /* PARSE_MODE_XXX constant */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
int nVtabLock; /* Number of virtual tables to lock */
#endif
@@ -3551,6 +3578,7 @@ struct TriggerStep {
Trigger *pTrig; /* The trigger that this step is a part of */
Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
SrcList *pFrom; /* FROM clause for UPDATE statement (if any) */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
ExprList *pExprList; /* SET clause for UPDATE */
IdList *pIdList; /* Column names for INSERT */
@@ -3606,6 +3634,7 @@ typedef struct {
int rc; /* Result code stored here */
u32 mInitFlags; /* Flags controlling error messages */
u32 nInitRow; /* Number of rows processed */
Pgno mxPage; /* Maximum page number. 0 for no limit. */
} InitData;
/*
@@ -4136,7 +4165,7 @@ void sqlite3DeleteColumnNames(sqlite3*,Table*);
int sqlite3ColumnsFromExprList(Parse*,ExprList*,i16*,Column**);
void sqlite3SelectAddColumnTypeAndCollation(Parse*,Table*,Select*,char);
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
void sqlite3OpenMasterTable(Parse *, int);
void sqlite3OpenSchemaTable(Parse *, int);
Index *sqlite3PrimaryKeyIndex(Table*);
i16 sqlite3TableColumnToIndex(Index*, i16);
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
@@ -4219,6 +4248,7 @@ void *sqlite3ArrayAllocate(sqlite3*,void*,int,int*,int*);
IdList *sqlite3IdListAppend(Parse*, IdList*, Token*);
int sqlite3IdListIndex(IdList*,const char*);
SrcList *sqlite3SrcListEnlarge(Parse*, SrcList*, int, int);
SrcList *sqlite3SrcListAppendList(Parse *pParse, SrcList *p1, SrcList *p2);
SrcList *sqlite3SrcListAppend(Parse*, SrcList*, Token*, Token*);
SrcList *sqlite3SrcListAppendFromTerm(Parse*, SrcList*, Token*, Token*,
Token*, Select*, Expr*, IdList*);
@@ -4237,7 +4267,6 @@ int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
Expr*,ExprList*,u32,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
void sqlite3SelectReset(Parse*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
@@ -4389,13 +4418,14 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
TriggerStep *sqlite3TriggerInsertStep(Parse*,Token*, IdList*,
Select*,u8,Upsert*,
const char*,const char*);
TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,ExprList*, Expr*, u8,
const char*,const char*);
TriggerStep *sqlite3TriggerUpdateStep(Parse*,Token*,SrcList*,ExprList*,
Expr*, u8, const char*,const char*);
TriggerStep *sqlite3TriggerDeleteStep(Parse*,Token*, Expr*,
const char*,const char*);
void sqlite3DeleteTrigger(sqlite3*, Trigger*);
void sqlite3UnlinkAndDeleteTrigger(sqlite3*,int,const char*);
u32 sqlite3TriggerColmask(Parse*,Trigger*,ExprList*,int,int,Table*,int);
SrcList *sqlite3TriggerStepSrc(Parse*, TriggerStep*);
# define sqlite3ParseToplevel(p) ((p)->pToplevel ? (p)->pToplevel : (p))
# define sqlite3IsToplevel(p) ((p)->pToplevel==0)
#else
@@ -4409,6 +4439,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
# define sqlite3ParseToplevel(p) p
# define sqlite3IsToplevel(p) 1
# define sqlite3TriggerColmask(A,B,C,D,E,F,G) 0
# define sqlite3TriggerStepSrc(A,B) 0
#endif
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
@@ -4437,8 +4468,10 @@ int sqlite3FixExpr(DbFixer*, Expr*);
int sqlite3FixExprList(DbFixer*, ExprList*);
int sqlite3FixTriggerStep(DbFixer*, TriggerStep*);
int sqlite3RealSameAsInt(double,sqlite3_int64);
void sqlite3Int64ToText(i64,char*);
int sqlite3AtoF(const char *z, double*, int, u8);
int sqlite3GetInt32(const char *, int*);
int sqlite3GetUInt32(const char*, u32*);
int sqlite3Atoi(const char*);
#ifndef SQLITE_OMIT_UTF16
int sqlite3Utf16ByteLen(const void *pData, int nChar);
@@ -4558,14 +4591,15 @@ extern const unsigned char sqlite3UpperToLower[];
extern const unsigned char sqlite3CtypeMap[];
extern SQLITE_WSD struct Sqlite3Config sqlite3Config;
extern FuncDefHash sqlite3BuiltinFunctions;
extern u32 sqlite3_unsupported_selecttrace;
#ifndef SQLITE_OMIT_WSD
extern int sqlite3PendingByte;
#endif
#endif
#endif /* SQLITE_AMALGAMATION */
#ifdef VDBE_PROFILE
extern sqlite3_uint64 sqlite3NProfileCnt;
#endif
void sqlite3RootPageMoved(sqlite3*, int, int, int);
void sqlite3RootPageMoved(sqlite3*, int, Pgno, Pgno);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
@@ -4679,7 +4713,7 @@ void sqlite3AutoLoadExtensions(sqlite3*);
#endif
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3TableLock(Parse *, int, int, u8, const char *);
void sqlite3TableLock(Parse *, int, Pgno, u8, const char *);
#else
#define sqlite3TableLock(v,w,x,y,z)
#endif
+1 -1
View File
@@ -352,7 +352,7 @@ int sqlite3_db_status(
*/
case SQLITE_DBSTATUS_CACHE_SPILL:
op = SQLITE_DBSTATUS_CACHE_WRITE+1;
/* Fall through into the next case */
/* no break */ deliberate_fall_through
case SQLITE_DBSTATUS_CACHE_HIT:
case SQLITE_DBSTATUS_CACHE_MISS:
case SQLITE_DBSTATUS_CACHE_WRITE:{
+67 -4
View File
@@ -4630,7 +4630,7 @@ static int SQLITE_TCLAPI test_open_v2(
{ "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
{ "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
{ "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
{ "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
{ "SQLITE_OPEN_SUPER_JOURNAL", SQLITE_OPEN_SUPER_JOURNAL },
{ "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
{ "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
{ "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
@@ -6437,6 +6437,30 @@ static int SQLITE_TCLAPI prng_seed(
return TCL_OK;
}
/*
** tclcmd: extra_schema_checks BOOLEAN
**
** Enable or disable schema checks when parsing the sqlite_schema file.
** This is always enabled in production, but it is sometimes useful to
** disable the checks in order to make some internal error states reachable
** for testing.
*/
static int SQLITE_TCLAPI extra_schema_checks(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
int i = 0;
if( objc!=2 ){
Tcl_WrongNumArgs(interp, 1, objv, "BOOLEAN");
return TCL_ERROR;
}
if( Tcl_GetBooleanFromObj(interp,objv[1],&i) ) return TCL_ERROR;
sqlite3_test_control(SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS, i);
return TCL_OK;
}
/*
** tclcmd: database_may_be_corrupt
**
@@ -7257,6 +7281,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_explain_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_decimal_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
@@ -7282,6 +7307,7 @@ static int SQLITE_TCLAPI tclLoadStaticExtensionCmd(
{ "carray", sqlite3_carray_init },
{ "closure", sqlite3_closure_init },
{ "csv", sqlite3_csv_init },
{ "decimal", sqlite3_decimal_init },
{ "eval", sqlite3_eval_init },
{ "explain", sqlite3_explain_init },
{ "fileio", sqlite3_fileio_init },
@@ -7776,6 +7802,41 @@ static int SQLITE_TCLAPI test_mmap_warm(
}
}
/*
** Usage: test_write_db DB OFFSET DATA
**
** Obtain the sqlite3_file* object for the database file for the "main" db
** of handle DB. Then invoke its xWrite method to write data DATA to offset
** OFFSET.
*/
static int SQLITE_TCLAPI test_write_db(
void * clientData,
Tcl_Interp *interp,
int objc,
Tcl_Obj *CONST objv[]
){
sqlite3 *db = 0;
Tcl_WideInt iOff = 0;
const unsigned char *aData = 0;
int nData = 0;
sqlite3_file *pFile = 0;
int rc;
if( objc!=4 ){
Tcl_WrongNumArgs(interp, 1, objv, "DB OFFSET DATA");
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
if( Tcl_GetWideIntFromObj(interp, objv[2], &iOff) ) return TCL_ERROR;
aData = Tcl_GetByteArrayFromObj(objv[3], &nData);
sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, (void*)&pFile);
rc = pFile->pMethods->xWrite(pFile, aData, nData, iOff);
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
return TCL_OK;
}
/*
** Usage: decode_hexdb TEXT
**
@@ -8001,6 +8062,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "restore_prng_state", restore_prng_state, 0 },
{ "reset_prng_state", reset_prng_state, 0 },
{ "prng_seed", prng_seed, 0 },
{ "extra_schema_checks", extra_schema_checks, 0},
{ "database_never_corrupt", database_never_corrupt, 0},
{ "database_may_be_corrupt", database_may_be_corrupt, 0},
{ "optimization_control", optimization_control,0},
@@ -8139,6 +8201,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_mmap_warm", test_mmap_warm, 0 },
{ "sqlite3_config_sorterref", test_config_sorterref, 0 },
{ "decode_hexdb", test_decode_hexdb, 0 },
{ "test_write_db", test_write_db, 0 },
};
static int bitmask_size = sizeof(Bitmask)*8;
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
@@ -8164,7 +8227,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
#endif
#endif
#if defined(SQLITE_ENABLE_SELECTTRACE)
extern int sqlite3SelectTrace;
extern u32 sqlite3_unsupported_selecttrace;
#endif
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
@@ -8252,8 +8315,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
Tcl_LinkVar(interp, "sqlite_fullsync_count",
(char*)&sqlite3_fullsync_count, TCL_LINK_INT);
#if defined(SQLITE_ENABLE_SELECTTRACE)
Tcl_LinkVar(interp, "sqlite3SelectTrace",
(char*)&sqlite3SelectTrace, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite3_unsupported_selecttrace",
(char*)&sqlite3_unsupported_selecttrace, TCL_LINK_INT);
#endif
#if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
+2 -2
View File
@@ -32,7 +32,7 @@ extern const char *sqlite3ErrName(int);
*/
typedef struct Thread Thread;
struct Thread {
/* The first group of fields are writable by the master and read-only
/* The first group of fields are writable by the leader and read-only
** to the thread. */
char *zFilename; /* Name of database file */
void (*xOp)(Thread*); /* next operation to do */
@@ -41,7 +41,7 @@ struct Thread {
int busy; /* True if this thread is in use */
/* The next group of fields are writable by the thread but read-only to the
** master. */
** leader. */
int completed; /* Number of operations completed */
sqlite3 *db; /* Open database */
sqlite3_stmt *pStmt; /* Pending operation */
+1 -1
View File
@@ -341,7 +341,7 @@ static int echoDeclareVtab(
if( pVtab->zTableName ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare(db,
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
"SELECT sql FROM sqlite_schema WHERE type = 'table' AND name = ?",
-1, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_text(pStmt, 1, pVtab->zTableName, -1, 0);
+3 -36
View File
@@ -112,32 +112,6 @@ static void *faultsimRealloc(void *pOld, int n){
return p;
}
/*
** The following method calls are passed directly through to the underlying
** malloc system:
**
** xFree
** xSize
** xRoundup
** xInit
** xShutdown
*/
static void faultsimFree(void *p){
memfault.m.xFree(p);
}
static int faultsimSize(void *p){
return memfault.m.xSize(p);
}
static int faultsimRoundup(int n){
return memfault.m.xRoundup(n);
}
static int faultsimInit(void *p){
return memfault.m.xInit(memfault.m.pAppData);
}
static void faultsimShutdown(void *p){
memfault.m.xShutdown(memfault.m.pAppData);
}
/*
** This routine configures the malloc failure simulation. After
** calling this routine, the next nDelay mallocs will succeed, followed
@@ -204,16 +178,6 @@ static void faultsimEndBenign(void){
** the argument is non-zero, the
*/
static int faultsimInstall(int install){
static struct sqlite3_mem_methods m = {
faultsimMalloc, /* xMalloc */
faultsimFree, /* xFree */
faultsimRealloc, /* xRealloc */
faultsimSize, /* xSize */
faultsimRoundup, /* xRoundup */
faultsimInit, /* xInit */
faultsimShutdown, /* xShutdown */
0 /* pAppData */
};
int rc;
install = (install ? 1 : 0);
@@ -227,6 +191,9 @@ static int faultsimInstall(int install){
rc = sqlite3_config(SQLITE_CONFIG_GETMALLOC, &memfault.m);
assert(memfault.m.xMalloc);
if( rc==SQLITE_OK ){
sqlite3_mem_methods m = memfault.m;
m.xMalloc = faultsimMalloc;
m.xRealloc = faultsimRealloc;
rc = sqlite3_config(SQLITE_CONFIG_MALLOC, &m);
}
sqlite3_test_control(SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS,
+3 -3
View File
@@ -545,7 +545,7 @@ static int multiplexOpen(
rc = pSubOpen->pMethods->xFileSize(pSubOpen, &sz64);
if( rc==SQLITE_OK && zName ){
int bExists;
if( flags & SQLITE_OPEN_MASTER_JOURNAL ){
if( flags & SQLITE_OPEN_SUPER_JOURNAL ){
pGroup->bEnabled = 0;
}else
if( sz64==0 ){
@@ -591,9 +591,9 @@ static int multiplexOpen(
if( rc==SQLITE_OK ){
if( pSubOpen->pMethods->iVersion==1 ){
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV1;
pConn->pMethods = &gMultiplex.sIoMethodsV1;
}else{
pMultiplexOpen->base.pMethods = &gMultiplex.sIoMethodsV2;
pConn->pMethods = &gMultiplex.sIoMethodsV2;
}
}else{
multiplexFreeComponents(pGroup);
+1 -1
View File
@@ -30,7 +30,7 @@
extern const char *sqlite3ErrName(int);
static const char *aName[MAX_MUTEXES+1] = {
"fast", "recursive", "static_master", "static_mem",
"fast", "recursive", "static_main", "static_mem",
"static_open", "static_prng", "static_lru", "static_pmem",
"static_app1", "static_app2", "static_app3", "static_vfs1",
"static_vfs2", "static_vfs3", 0
+2 -2
View File
@@ -740,7 +740,7 @@ int sqlite3_vfslog_new(
zFile = (char *)&p->base.zName[nVfs+1];
pParent->xFullPathname(pParent, zLog, pParent->mxPathname, zFile);
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_MASTER_JOURNAL;
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE|SQLITE_OPEN_SUPER_JOURNAL;
pParent->xDelete(pParent, zFile, 0);
rc = pParent->xOpen(pParent, zFile, p->pLog, flags, &flags);
if( rc==SQLITE_OK ){
@@ -893,7 +893,7 @@ static int vlogConnect(
pVfs->xFullPathname(pVfs, zFile, pVfs->mxPathname, p->zFile);
sqlite3_free(zFile);
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_MASTER_JOURNAL;
flags = SQLITE_OPEN_READWRITE|SQLITE_OPEN_SUPER_JOURNAL;
rc = pVfs->xOpen(pVfs, p->zFile, p->pFd, flags, &flags);
if( rc==SQLITE_OK ){
+3 -3
View File
@@ -192,18 +192,18 @@ static int schemaNext(sqlite3_vtab_cursor *cur){
}
/* Set zSql to the SQL to pull the list of tables from the
** sqlite_master (or sqlite_temp_master) table of the database
** sqlite_schema (or sqlite_temp_schema) table of the database
** identified by the row pointed to by the SQL statement pCur->pDbList
** (iterating through a "PRAGMA database_list;" statement).
*/
if( sqlite3_column_int(pCur->pDbList, 0)==1 ){
zSql = sqlite3_mprintf(
"SELECT name FROM sqlite_temp_master WHERE type='table'"
"SELECT name FROM sqlite_temp_schema WHERE type='table'"
);
}else{
sqlite3_stmt *pDbList = pCur->pDbList;
zSql = sqlite3_mprintf(
"SELECT name FROM %Q.sqlite_master WHERE type='table'",
"SELECT name FROM %Q.sqlite_schema WHERE type='table'",
sqlite3_column_text(pDbList, 1)
);
}
+8 -8
View File
@@ -118,7 +118,7 @@ struct SLConn {
/* This object is a singleton that keeps track of all data loggers.
*/
static struct SLGlobal {
/* Protected by MUTEX_STATIC_MASTER */
/* Protected by MUTEX_STATIC_MAIN */
sqlite3_mutex *mutex; /* Recursive mutex */
int nConn; /* Size of aConn[] array */
@@ -467,28 +467,28 @@ static int sqllogTraceDb(sqlite3 *db){
*/
static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
struct SLConn *p = 0;
sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex *mainmtx = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MAIN);
assert( eType==0 || eType==1 || eType==2 );
assert( (eType==2)==(zSql==0) );
/* This is a database open command. */
if( eType==0 ){
sqlite3_mutex_enter(master);
sqlite3_mutex_enter(mainmtx);
if( sqllogglobal.mutex==0 ){
sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE);
}
sqlite3_mutex_leave(master);
sqlite3_mutex_leave(mainmtx);
sqlite3_mutex_enter(sqllogglobal.mutex);
if( sqllogglobal.bRec==0 && sqllogTraceDb(db) ){
sqlite3_mutex_enter(master);
sqlite3_mutex_enter(mainmtx);
p = &sqllogglobal.aConn[sqllogglobal.nConn++];
p->fd = 0;
p->db = db;
p->iLog = sqllogglobal.iNextLog++;
sqlite3_mutex_leave(master);
sqlite3_mutex_leave(mainmtx);
/* Open the log and take a copy of the main database file */
sqllogOpenlog(p);
@@ -507,7 +507,7 @@ static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
/* A database handle close command */
if( eType==2 ){
sqlite3_mutex_enter(master);
sqlite3_mutex_enter(mainmtx);
if( i<sqllogglobal.nConn ){
if( p->fd ) fclose(p->fd);
p->db = 0;
@@ -524,7 +524,7 @@ static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){
memmove(p, &p[1], nShift*sizeof(struct SLConn));
}
}
sqlite3_mutex_leave(master);
sqlite3_mutex_leave(mainmtx);
/* An ordinary SQL command. */
}else if( i<sqllogglobal.nConn && p->fd ){
+2
View File
@@ -422,6 +422,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
}
/* If the next character is a digit, this is a floating point
** number that begins with ".". Fall thru into the next case */
/* no break */ deliberate_fall_through
}
case CC_DIGIT: {
testcase( z[0]=='0' ); testcase( z[0]=='1' ); testcase( z[0]=='2' );
@@ -526,6 +527,7 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
#endif
/* If it is not a BLOB literal, then it must be an ID, since no
** SQL keywords start with the letter 'x'. Fall through */
/* no break */ deliberate_fall_through
}
case CC_ID: {
i = 1;

Some files were not shown because too many files have changed in this diff Show More