Compare commits
161 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ba5f5b5d2 | |||
| e893e2e4ee | |||
| 4344dbd3ab | |||
| 0f86c9d8fa | |||
| 416a801600 | |||
| 8cdafc384e | |||
| fc232d6f65 | |||
| 5d3112872d | |||
| 8e02a180b9 | |||
| 6a8b94e266 | |||
| 3e62ddbf13 | |||
| ea93e2804d | |||
| 867e6de4d7 | |||
| 59ee43a78e | |||
| 1d40cdbd4b | |||
| d3e17ffbb7 | |||
| 66e82b47d9 | |||
| fecfb3189b | |||
| 50baf3d525 | |||
| 341141c339 | |||
| 4031bafafb | |||
| 9201184711 | |||
| 7fc86b96ba | |||
| 338e311acb | |||
| 30fc7f8009 | |||
| c8c9cdd9dd | |||
| b9cd2c4536 | |||
| bbd574bc37 | |||
| cf8784cd8f | |||
| 7458a9f3f7 | |||
| 4c57e326ef | |||
| 186ebd41cf | |||
| e8cf689df3 | |||
| 16d261b3ef | |||
| 9e80403bfc | |||
| a02fd67b99 | |||
| 136c9903bf | |||
| 252f39619a | |||
| bc30e2023b | |||
| 8d1751b6fa | |||
| 6c319e1238 | |||
| be4ccb2838 | |||
| d0f9cdcc63 | |||
| 1f22f62582 | |||
| 26fb126622 | |||
| 7578456c25 | |||
| 1e76c22b4a | |||
| e297196524 | |||
| f80bba9d8d | |||
| dd7460f0fd | |||
| a44005af4f | |||
| 492ad131bd | |||
| a090ab90d6 | |||
| a3926f4bbf | |||
| fc97c1c8cb | |||
| 69ed38a822 | |||
| 1615c37e48 | |||
| fc29a86eee | |||
| 003edba0da | |||
| f2072d136d | |||
| cb38809159 | |||
| f0f9dbd384 | |||
| 446135d724 | |||
| 0cdbe1aee0 | |||
| 721e8539c3 | |||
| 4c54045372 | |||
| f2cf412a0a | |||
| 5ecf9039b0 | |||
| 89ee229810 | |||
| d720d394d0 | |||
| e3c05a5597 | |||
| e2188f0b0f | |||
| 30f7a25325 | |||
| 60208c34bb | |||
| c6f36fa33a | |||
| 6fcf83a503 | |||
| cb737dc29e | |||
| e3d511c078 | |||
| e632ae796a | |||
| 5d72d9245d | |||
| 4388522561 | |||
| 5e8b9853da | |||
| 34b27edc80 | |||
| 98b677f2cb | |||
| 4d79983ca5 | |||
| d5aa9262a6 | |||
| da65fc6e32 | |||
| 4f84e9c7e2 | |||
| 9b03192e15 | |||
| 3de5d16cf7 | |||
| fa16f5d9d6 | |||
| cdf88760da | |||
| b3f0276b9e | |||
| 84a01debf9 | |||
| 85a40ebc03 | |||
| 03c3905f94 | |||
| fa5c69f5cb | |||
| 07430a8caf | |||
| c631ded5e8 | |||
| e2ca99c907 | |||
| 8c2e6c5fe0 | |||
| bbd4ae5a2f | |||
| b57e3ec5d8 | |||
| 2b137d65f5 | |||
| a19d09677b | |||
| 7df011969c | |||
| 46462e35d3 | |||
| 1efa8023a1 | |||
| 6bfd973ce6 | |||
| 542805d174 | |||
| c1e1ffeafb | |||
| 0314cf3aa5 | |||
| 95d5ae19d1 | |||
| 03db962ab5 | |||
| 0ef54fa6e8 | |||
| ef9e3d78f2 | |||
| 6876dccbfe | |||
| c040e2b186 | |||
| f226f03d4f | |||
| 909066bba0 | |||
| de7ca50dac | |||
| 896494e8ad | |||
| 1e08074906 | |||
| fc0ec3e5e8 | |||
| 7eabc44dee | |||
| d11b8f671f | |||
| b2c8559fad | |||
| 3215872446 | |||
| ccb9eb782c | |||
| 820fcd2ce9 | |||
| c447595df5 | |||
| cd90ca7ded | |||
| cb23e5d5d1 | |||
| 5776c139a4 | |||
| 4da04f784f | |||
| 4b5345ccc7 | |||
| 4d3e61403a | |||
| 8349c11d02 | |||
| 5279af8061 | |||
| f49ff6ffb3 | |||
| fbe07539d3 | |||
| 48d219af4c | |||
| f20609d107 | |||
| e2243d26f3 | |||
| 1bddf23b89 | |||
| b3b0d317e0 | |||
| 4751b87f19 | |||
| 05ef50d08a | |||
| fd39c5874a | |||
| 539e741e50 | |||
| 42d181604c | |||
| fb32c44e41 | |||
| f3d7bbb767 | |||
| 9f88e6d861 | |||
| 340e9e125b | |||
| 4b8bd84302 | |||
| 7c48360d7c | |||
| ac9151d848 | |||
| 9cadb2308b | |||
| 224d92c8c0 | |||
| 4da91eed80 |
+2
-1
@@ -572,7 +572,8 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata2.db \
|
||||
$(TOP)/test/fuzzdata3.db \
|
||||
$(TOP)/test/fuzzdata4.db \
|
||||
$(TOP)/test/fuzzdata5.db
|
||||
$(TOP)/test/fuzzdata5.db \
|
||||
$(TOP)/test/fuzzdata6.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
|
||||
+2
-1
@@ -1599,7 +1599,8 @@ FUZZDATA = \
|
||||
$(TOP)\test\fuzzdata2.db \
|
||||
$(TOP)\test\fuzzdata3.db \
|
||||
$(TOP)\test\fuzzdata4.db \
|
||||
$(TOP)\test\fuzzdata5.db
|
||||
$(TOP)\test\fuzzdata5.db \
|
||||
$(TOP)\test\fuzzdata6.db
|
||||
# <</mark>>
|
||||
|
||||
# Additional compiler options for the shell. These are only effective
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE
|
||||
AM_CFLAGS = @THREADSAFE_FLAGS@ @DYNAMIC_EXTENSION_FLAGS@ @FTS5_FLAGS@ @JSON1_FLAGS@ @ZLIB_FLAGS@ @SESSION_FLAGS@ -DSQLITE_ENABLE_FTS3 -DSQLITE_ENABLE_RTREE @DEBUG_FLAGS@
|
||||
|
||||
lib_LTLIBRARIES = libsqlite3.la
|
||||
libsqlite3_la_SOURCES = sqlite3.c
|
||||
@@ -14,7 +14,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
|
||||
EXTRA_DIST = sqlite3.1 tea Makefile.msc sqlite3.rc README.txt Replace.cs Makefile.fallback
|
||||
pkgconfigdir = ${libdir}/pkgconfig
|
||||
pkgconfig_DATA = sqlite3.pc
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/make
|
||||
#
|
||||
# If the configure script does not work, then this Makefile is available
|
||||
# as a backup. Manually configure the variables below.
|
||||
#
|
||||
# Note: This makefile works out-of-the-box on MacOS 10.2 (Jaguar)
|
||||
#
|
||||
CC = gcc
|
||||
CFLAGS = -O0 -I.
|
||||
LIBS = -lz
|
||||
COPTS += -D_BSD_SOURCE
|
||||
COPTS += -DSQLITE_ENABLE_LOCKING_STYLE=0
|
||||
COPTS += -DSQLITE_THREADSAFE=0
|
||||
COPTS += -DSQLITE_OMIT_LOAD_EXTENSION
|
||||
COPTS += -DSQLITE_WITHOUT_ZONEMALLOC
|
||||
COPTS += -DSQLITE_ENABLE_RTREE
|
||||
|
||||
sqlite3: shell.c sqlite3.c
|
||||
$(CC) $(CFLAGS) $(COPTS) -o sqlite3 shell.c sqlite3.c $(LIBS)
|
||||
+16
-4
@@ -115,8 +115,8 @@ AC_SUBST(DYNAMIC_EXTENSION_FLAGS)
|
||||
# --enable-fts5
|
||||
#
|
||||
AC_ARG_ENABLE(fts5, [AS_HELP_STRING(
|
||||
[--enable-fts5], [include fts5 support [default=no]])],
|
||||
[], [enable_fts5=no])
|
||||
[--enable-fts5], [include fts5 support [default=yes]])],
|
||||
[], [enable_fts5=yes])
|
||||
if test x"$enable_fts5" = "xyes"; then
|
||||
AC_SEARCH_LIBS(log, m)
|
||||
FTS5_FLAGS=-DSQLITE_ENABLE_FTS5
|
||||
@@ -128,8 +128,8 @@ AC_SUBST(FTS5_FLAGS)
|
||||
# --enable-json1
|
||||
#
|
||||
AC_ARG_ENABLE(json1, [AS_HELP_STRING(
|
||||
[--enable-json1], [include json1 support [default=no]])],
|
||||
[], [enable_json1=no])
|
||||
[--enable-json1], [include json1 support [default=yes]])],
|
||||
[], [enable_json1=yes])
|
||||
if test x"$enable_json1" = "xyes"; then
|
||||
JSON1_FLAGS=-DSQLITE_ENABLE_JSON1
|
||||
fi
|
||||
@@ -148,6 +148,18 @@ fi
|
||||
AC_SUBST(SESSION_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-debug
|
||||
#
|
||||
AC_ARG_ENABLE(debug, [AS_HELP_STRING(
|
||||
[--enable-debug], [build with debugging features enabled [default=no]])],
|
||||
[], [enable_session=no])
|
||||
if test x"$enable_debug" = "xyes"; then
|
||||
DEBUG_FLAGS="-DSQLITE_DEBUG -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE"
|
||||
fi
|
||||
AC_SUBST(DEBUG_FLAGS)
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# --enable-static-shell
|
||||
#
|
||||
|
||||
@@ -99,6 +99,9 @@ Show only the basis for each parser state in the report file.
|
||||
<li><b>-c</b>
|
||||
Do not compress the generated action tables. The parser will be a
|
||||
little larger and slower, but it will detect syntax errors sooner.
|
||||
<li><b>-d</b><i>directory</i>
|
||||
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
|
||||
@@ -679,6 +682,30 @@ of type "MyStruct*" and all action routines will have access to
|
||||
a variable named "pAbc" that is the value of the 4th parameter
|
||||
in the most recent call to Parse().</p>
|
||||
|
||||
<p>The <tt>%extra_context</tt> directive works the same except that it
|
||||
is passed in on the ParseAlloc() or ParseInit() routines instead of
|
||||
on Parse().
|
||||
|
||||
<a name='extractx'></a>
|
||||
<h4>The <tt>%extra_context</tt> directive</h4>
|
||||
|
||||
The <tt>%extra_context</tt> directive instructs Lemon to add a 2th parameter
|
||||
to the parameter list of the ParseAlloc() and ParseInif() functions. Lemon
|
||||
doesn't do anything itself with these extra argument, but it does
|
||||
store the value make it available to C-code action routines, destructors,
|
||||
and so forth. For example, if the grammar file contains:</p>
|
||||
|
||||
<p><pre>
|
||||
%extra_context { MyStruct *pAbc }
|
||||
</pre></p>
|
||||
|
||||
<p>Then the ParseAlloc() and ParseInit() functions will have an 2th parameter
|
||||
of type "MyStruct*" and all action routines will have access to
|
||||
a variable named "pAbc" that is the value of that 2th parameter.</p>
|
||||
|
||||
<p>The <tt>%extra_argument</tt> directive works the same except that it
|
||||
is passed in on the Parse() routine instead of on ParseAlloc()/ParseInit().
|
||||
|
||||
<a name='pfallback'></a>
|
||||
<h4>The <tt>%fallback</tt> directive</h4>
|
||||
|
||||
|
||||
+25
-25
@@ -95,7 +95,7 @@ do_setup_rec_test $tn.1 { CREATE TABLE t1(a, b, c) } {
|
||||
SELECT * FROM t1
|
||||
} {
|
||||
(no new indexes)
|
||||
0|0|0|SCAN TABLE t1
|
||||
SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.2 {
|
||||
@@ -104,7 +104,7 @@ do_setup_rec_test $tn.2 {
|
||||
SELECT * FROM t1 WHERE b>?;
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b);
|
||||
0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
|
||||
SEARCH TABLE t1 USING INDEX t1_idx_00000062 (b>?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.3 {
|
||||
@@ -113,7 +113,7 @@ do_setup_rec_test $tn.3 {
|
||||
SELECT * FROM t1 WHERE b COLLATE nocase BETWEEN ? AND ?
|
||||
} {
|
||||
CREATE INDEX t1_idx_3e094c27 ON t1(b COLLATE NOCASE);
|
||||
0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
|
||||
SEARCH TABLE t1 USING INDEX t1_idx_3e094c27 (b>? AND b<?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.4 {
|
||||
@@ -122,7 +122,7 @@ do_setup_rec_test $tn.4 {
|
||||
SELECT a FROM t1 ORDER BY b;
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000062 ON t1(b);
|
||||
0|0|0|SCAN TABLE t1 USING INDEX t1_idx_00000062
|
||||
SCAN TABLE t1 USING INDEX t1_idx_00000062
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.5 {
|
||||
@@ -131,7 +131,7 @@ do_setup_rec_test $tn.5 {
|
||||
SELECT a FROM t1 WHERE a=? ORDER BY b;
|
||||
} {
|
||||
CREATE INDEX t1_idx_000123a7 ON t1(a, b);
|
||||
0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
|
||||
SEARCH TABLE t1 USING COVERING INDEX t1_idx_000123a7 (a=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.6 {
|
||||
@@ -140,7 +140,7 @@ do_setup_rec_test $tn.6 {
|
||||
SELECT min(a) FROM t1
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a);
|
||||
0|0|0|SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
|
||||
SEARCH TABLE t1 USING COVERING INDEX t1_idx_00000061
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.7 {
|
||||
@@ -149,7 +149,7 @@ do_setup_rec_test $tn.7 {
|
||||
SELECT * FROM t1 ORDER BY a, b, c;
|
||||
} {
|
||||
CREATE INDEX t1_idx_033e95fe ON t1(a, b, c);
|
||||
0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
|
||||
SCAN TABLE t1 USING COVERING INDEX t1_idx_033e95fe
|
||||
}
|
||||
|
||||
#do_setup_rec_test $tn.1.8 {
|
||||
@@ -167,7 +167,7 @@ do_setup_rec_test $tn.8.1 {
|
||||
SELECT * FROM t1 WHERE a=?
|
||||
} {
|
||||
CREATE INDEX t1_idx_00000061 ON t1(a);
|
||||
0|0|0|SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
|
||||
SEARCH TABLE t1 USING INDEX t1_idx_00000061 (a=?)
|
||||
}
|
||||
do_setup_rec_test $tn.8.2 {
|
||||
CREATE TABLE t1(a, b COLLATE nocase, c);
|
||||
@@ -175,7 +175,7 @@ do_setup_rec_test $tn.8.2 {
|
||||
SELECT * FROM t1 ORDER BY a ASC, b DESC, c ASC;
|
||||
} {
|
||||
CREATE INDEX t1_idx_5cb97285 ON t1(a, b DESC, c);
|
||||
0|0|0|SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
|
||||
SCAN TABLE t1 USING COVERING INDEX t1_idx_5cb97285
|
||||
}
|
||||
|
||||
|
||||
@@ -187,7 +187,7 @@ do_setup_rec_test $tn.9.1 {
|
||||
SELECT * FROM "t t" WHERE a=?
|
||||
} {
|
||||
CREATE INDEX 't t_idx_00000061' ON 't t'(a);
|
||||
0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
|
||||
SEARCH TABLE t t USING INDEX t t_idx_00000061 (a=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.9.2 {
|
||||
@@ -196,7 +196,7 @@ do_setup_rec_test $tn.9.2 {
|
||||
SELECT * FROM "t t" WHERE b BETWEEN ? AND ?
|
||||
} {
|
||||
CREATE INDEX 't t_idx_00000062' ON 't t'(b);
|
||||
0|0|0|SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
|
||||
SEARCH TABLE t t USING INDEX t t_idx_00000062 (b>? AND b<?)
|
||||
}
|
||||
|
||||
# Columns with names that require quotes.
|
||||
@@ -207,7 +207,7 @@ do_setup_rec_test $tn.10.1 {
|
||||
SELECT * FROM t3 WHERE "b b" = ?
|
||||
} {
|
||||
CREATE INDEX t3_idx_00050c52 ON t3('b b');
|
||||
0|0|0|SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
|
||||
SEARCH TABLE t3 USING INDEX t3_idx_00050c52 (b b=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.10.2 {
|
||||
@@ -216,7 +216,7 @@ do_setup_rec_test $tn.10.2 {
|
||||
SELECT * FROM t3 ORDER BY "b b"
|
||||
} {
|
||||
CREATE INDEX t3_idx_00050c52 ON t3('b b');
|
||||
0|0|0|SCAN TABLE t3 USING INDEX t3_idx_00050c52
|
||||
SCAN TABLE t3 USING INDEX t3_idx_00050c52
|
||||
}
|
||||
|
||||
# Transitive constraints
|
||||
@@ -229,8 +229,8 @@ do_setup_rec_test $tn.11.1 {
|
||||
} {
|
||||
CREATE INDEX t5_idx_000123a7 ON t5(a, b);
|
||||
CREATE INDEX t6_idx_00000063 ON t6(c);
|
||||
0|0|1|SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
|
||||
0|1|0|SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
|
||||
SEARCH TABLE t6 USING INDEX t6_idx_00000063 (c=?)
|
||||
SEARCH TABLE t5 USING COVERING INDEX t5_idx_000123a7 (a=? AND b=?)
|
||||
}
|
||||
|
||||
# OR terms.
|
||||
@@ -242,8 +242,9 @@ do_setup_rec_test $tn.12.1 {
|
||||
} {
|
||||
CREATE INDEX t7_idx_00000062 ON t7(b);
|
||||
CREATE INDEX t7_idx_00000061 ON t7(a);
|
||||
0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
|
||||
0|0|0|SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
|
||||
MULTI-INDEX OR
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000061 (a=?)
|
||||
SEARCH TABLE t7 USING INDEX t7_idx_00000062 (b=?)
|
||||
}
|
||||
|
||||
# rowid terms.
|
||||
@@ -254,7 +255,7 @@ do_setup_rec_test $tn.13.1 {
|
||||
SELECT * FROM t8 WHERE rowid=?
|
||||
} {
|
||||
(no new indexes)
|
||||
0|0|0|SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH TABLE t8 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
do_setup_rec_test $tn.13.2 {
|
||||
CREATE TABLE t8(a, b);
|
||||
@@ -262,7 +263,7 @@ do_setup_rec_test $tn.13.2 {
|
||||
SELECT * FROM t8 ORDER BY rowid
|
||||
} {
|
||||
(no new indexes)
|
||||
0|0|0|SCAN TABLE t8
|
||||
SCAN TABLE t8
|
||||
}
|
||||
do_setup_rec_test $tn.13.3 {
|
||||
CREATE TABLE t8(a, b);
|
||||
@@ -270,7 +271,7 @@ do_setup_rec_test $tn.13.3 {
|
||||
SELECT * FROM t8 WHERE a=? ORDER BY rowid
|
||||
} {
|
||||
CREATE INDEX t8_idx_00000061 ON t8(a);
|
||||
0|0|0|SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
|
||||
SEARCH TABLE t8 USING INDEX t8_idx_00000061 (a=?)
|
||||
}
|
||||
|
||||
# Triggers
|
||||
@@ -285,7 +286,7 @@ do_setup_rec_test $tn.14 {
|
||||
INSERT INTO t9 VALUES(?, ?, ?);
|
||||
} {
|
||||
CREATE INDEX t10_idx_00000062 ON t10(b);
|
||||
0|0|0|SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
|
||||
SEARCH TABLE t10 USING INDEX t10_idx_00000062 (b=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.15 {
|
||||
@@ -301,8 +302,8 @@ do_setup_rec_test $tn.15 {
|
||||
SELECT * FROM t2, t1 WHERE b=? AND d=? AND t2.rowid=t1.rowid
|
||||
} {
|
||||
CREATE INDEX t2_idx_00000064 ON t2(d);
|
||||
0|0|0|SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
|
||||
0|1|1|SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
SEARCH TABLE t2 USING INDEX t2_idx_00000064 (d=?)
|
||||
SEARCH TABLE t1 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_setup_rec_test $tn.16 {
|
||||
@@ -311,7 +312,7 @@ do_setup_rec_test $tn.16 {
|
||||
SELECT * FROM t1 WHERE b IS NOT NULL;
|
||||
} {
|
||||
(no new indexes)
|
||||
0|0|0|SCAN TABLE t1
|
||||
SCAN TABLE t1
|
||||
}
|
||||
|
||||
}
|
||||
@@ -379,4 +380,3 @@ do_execsql_test 3.2 {
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -1123,9 +1123,9 @@ int idxFindIndexes(
|
||||
"EXPLAIN QUERY PLAN %s", pStmt->zSql
|
||||
);
|
||||
while( rc==SQLITE_OK && sqlite3_step(pExplain)==SQLITE_ROW ){
|
||||
int iSelectid = sqlite3_column_int(pExplain, 0);
|
||||
int iOrder = sqlite3_column_int(pExplain, 1);
|
||||
int iFrom = sqlite3_column_int(pExplain, 2);
|
||||
/* int iId = sqlite3_column_int(pExplain, 0); */
|
||||
/* int iParent = sqlite3_column_int(pExplain, 1); */
|
||||
/* int iNotUsed = sqlite3_column_int(pExplain, 2); */
|
||||
const char *zDetail = (const char*)sqlite3_column_text(pExplain, 3);
|
||||
int nDetail = STRLEN(zDetail);
|
||||
int i;
|
||||
@@ -1152,9 +1152,9 @@ int idxFindIndexes(
|
||||
}
|
||||
}
|
||||
|
||||
pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%d|%d|%d|%s\n",
|
||||
iSelectid, iOrder, iFrom, zDetail
|
||||
);
|
||||
if( zDetail[0]!='-' ){
|
||||
pStmt->zEQP = idxAppendText(&rc, pStmt->zEQP, "%s\n", zDetail);
|
||||
}
|
||||
}
|
||||
|
||||
for(pEntry=hIdx.pFirst; pEntry; pEntry=pEntry->pNext){
|
||||
|
||||
+1
-1
@@ -3963,7 +3963,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
||||
|
||||
#ifdef SQLITE_TEST
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db);
|
||||
rc = sqlite3Fts3ExprInitTestInterface(db, pHash);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+1
-1
@@ -584,7 +584,7 @@ int sqlite3Fts3ExprParse(sqlite3_tokenizer *, int,
|
||||
);
|
||||
void sqlite3Fts3ExprFree(Fts3Expr *);
|
||||
#ifdef SQLITE_TEST
|
||||
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db);
|
||||
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash*);
|
||||
int sqlite3Fts3InitTerm(sqlite3 *db);
|
||||
#endif
|
||||
|
||||
|
||||
+36
-53
@@ -1108,34 +1108,6 @@ void sqlite3Fts3ExprFree(Fts3Expr *pDel){
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*
|
||||
** Function to query the hash-table of tokenizers (see README.tokenizers).
|
||||
*/
|
||||
static int queryTestTokenizer(
|
||||
sqlite3 *db,
|
||||
const char *zName,
|
||||
const sqlite3_tokenizer_module **pp
|
||||
){
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
const char zSql[] = "SELECT fts3_tokenizer(?)";
|
||||
|
||||
*pp = 0;
|
||||
rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
return rc;
|
||||
}
|
||||
|
||||
sqlite3_bind_text(pStmt, 1, zName, -1, SQLITE_STATIC);
|
||||
if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
if( sqlite3_column_type(pStmt, 0)==SQLITE_BLOB ){
|
||||
memcpy((void *)pp, sqlite3_column_blob(pStmt, 0), sizeof(*pp));
|
||||
}
|
||||
}
|
||||
|
||||
return sqlite3_finalize(pStmt);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to a buffer containing a text representation of the
|
||||
** expression passed as the first argument. The buffer is obtained from
|
||||
@@ -1203,12 +1175,12 @@ static char *exprToString(Fts3Expr *pExpr, char *zBuf){
|
||||
**
|
||||
** SELECT fts3_exprtest('simple', 'Bill col2:Bloggs', 'col1', 'col2');
|
||||
*/
|
||||
static void fts3ExprTest(
|
||||
static void fts3ExprTestCommon(
|
||||
int bRebalance,
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3_tokenizer_module const *pModule = 0;
|
||||
sqlite3_tokenizer *pTokenizer = 0;
|
||||
int rc;
|
||||
char **azCol = 0;
|
||||
@@ -1218,7 +1190,9 @@ static void fts3ExprTest(
|
||||
int ii;
|
||||
Fts3Expr *pExpr;
|
||||
char *zBuf = 0;
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
Fts3Hash *pHash = (Fts3Hash*)sqlite3_user_data(context);
|
||||
const char *zTokenizer = 0;
|
||||
char *zErr = 0;
|
||||
|
||||
if( argc<3 ){
|
||||
sqlite3_result_error(context,
|
||||
@@ -1227,24 +1201,18 @@ static void fts3ExprTest(
|
||||
return;
|
||||
}
|
||||
|
||||
rc = queryTestTokenizer(db,
|
||||
(const char *)sqlite3_value_text(argv[0]), &pModule);
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
goto exprtest_out;
|
||||
}else if( !pModule ){
|
||||
sqlite3_result_error(context, "No such tokenizer module", -1);
|
||||
goto exprtest_out;
|
||||
zTokenizer = (const char*)sqlite3_value_text(argv[0]);
|
||||
rc = sqlite3Fts3InitTokenizer(pHash, zTokenizer, &pTokenizer, &zErr);
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
}
|
||||
sqlite3_free(zErr);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = pModule->xCreate(0, 0, &pTokenizer);
|
||||
assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
|
||||
if( rc==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
goto exprtest_out;
|
||||
}
|
||||
pTokenizer->pModule = pModule;
|
||||
|
||||
zExpr = (const char *)sqlite3_value_text(argv[1]);
|
||||
nExpr = sqlite3_value_bytes(argv[1]);
|
||||
nCol = argc-2;
|
||||
@@ -1257,7 +1225,7 @@ static void fts3ExprTest(
|
||||
azCol[ii] = (char *)sqlite3_value_text(argv[ii+2]);
|
||||
}
|
||||
|
||||
if( sqlite3_user_data(context) ){
|
||||
if( bRebalance ){
|
||||
char *zDummy = 0;
|
||||
rc = sqlite3Fts3ExprParse(
|
||||
pTokenizer, 0, azCol, 0, nCol, nCol, zExpr, nExpr, &pExpr, &zDummy
|
||||
@@ -1283,23 +1251,38 @@ static void fts3ExprTest(
|
||||
sqlite3Fts3ExprFree(pExpr);
|
||||
|
||||
exprtest_out:
|
||||
if( pModule && pTokenizer ){
|
||||
rc = pModule->xDestroy(pTokenizer);
|
||||
if( pTokenizer ){
|
||||
rc = pTokenizer->pModule->xDestroy(pTokenizer);
|
||||
}
|
||||
sqlite3_free(azCol);
|
||||
}
|
||||
|
||||
static void fts3ExprTest(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
fts3ExprTestCommon(0, context, argc, argv);
|
||||
}
|
||||
static void fts3ExprTestRebalance(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
fts3ExprTestCommon(1, context, argc, argv);
|
||||
}
|
||||
|
||||
/*
|
||||
** Register the query expression parser test function fts3_exprtest()
|
||||
** with database connection db.
|
||||
*/
|
||||
int sqlite3Fts3ExprInitTestInterface(sqlite3* db){
|
||||
int sqlite3Fts3ExprInitTestInterface(sqlite3 *db, Fts3Hash *pHash){
|
||||
int rc = sqlite3_create_function(
|
||||
db, "fts3_exprtest", -1, SQLITE_UTF8, 0, fts3ExprTest, 0, 0
|
||||
db, "fts3_exprtest", -1, SQLITE_UTF8, (void*)pHash, fts3ExprTest, 0, 0
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_function(db, "fts3_exprtest_rebalance",
|
||||
-1, SQLITE_UTF8, (void *)1, fts3ExprTest, 0, 0
|
||||
-1, SQLITE_UTF8, (void*)pHash, fts3ExprTestRebalance, 0, 0
|
||||
);
|
||||
}
|
||||
return rc;
|
||||
|
||||
+13
-14
@@ -29,38 +29,37 @@ do_execsql_test 1.0 {
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM t1, f1 WHERE f1 MATCH t1.x
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1, f1 WHERE f1 > t1.x
|
||||
} {
|
||||
0 0 1 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 0 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM f1 WHERE f1 MATCH ? ORDER BY ff
|
||||
} {
|
||||
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 65537:
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM f1 ORDER BY rank
|
||||
} {
|
||||
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 0:}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE f1 VIRTUAL TABLE INDEX 0:
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM f1 WHERE rank MATCH ?
|
||||
} {
|
||||
0 0 0 {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
|
||||
}
|
||||
|
||||
|
||||
|
||||
} {SCAN TABLE f1 VIRTUAL TABLE INDEX 2:}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -41,7 +41,6 @@ foreach {tn t} {1 ascii 2 unicode61} {
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that "unicode61" really is the default tokenizer.
|
||||
#
|
||||
|
||||
do_execsql_test 2.0 "
|
||||
CREATE VIRTUAL TABLE t1 USING fts5(x);
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(x, tokenize = unicode61);
|
||||
@@ -56,5 +55,31 @@ do_execsql_test 2.1 "
|
||||
SELECT 't3' FROM t3 WHERE t3 MATCH '\xE0\xE8\xEC';
|
||||
" {t1 t2}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that codepoints that require 4 bytes to store in utf-8 (those that
|
||||
# require 17 or more bits to store).
|
||||
#
|
||||
|
||||
set A [db one {SELECT char(0x1F75E)}] ;# Type So
|
||||
set B [db one {SELECT char(0x1F5FD)}] ;# Type So
|
||||
set C [db one {SELECT char(0x2F802)}] ;# Type Lo
|
||||
set D [db one {SELECT char(0x2F808)}] ;# Type Lo
|
||||
|
||||
do_execsql_test 3.0 "
|
||||
CREATE VIRTUAL TABLE xyz USING fts5(x,
|
||||
tokenize = \"unicode61 separators '$C' tokenchars '$A'\"
|
||||
);
|
||||
CREATE VIRTUAL TABLE xyz_v USING fts5vocab(xyz, row);
|
||||
|
||||
INSERT INTO xyz VALUES('$A$B$C$D');
|
||||
"
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
SELECT * FROM xyz_v;
|
||||
} [list $A 1 1 $D 1 1]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+12
-6
@@ -826,17 +826,12 @@ static int closureBestIndex(
|
||||
int iPlan = 0;
|
||||
int i;
|
||||
int idx = 1;
|
||||
int seenMatch = 0;
|
||||
const struct sqlite3_index_constraint *pConstraint;
|
||||
closure_vtab *pVtab = (closure_vtab*)pTab;
|
||||
double rCost = 10000000.0;
|
||||
|
||||
pConstraint = pIdxInfo->aConstraint;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
if( pConstraint->iColumn==CLOSURE_COL_ROOT
|
||||
&& pConstraint->op==SQLITE_INDEX_CONSTRAINT_EQ ){
|
||||
seenMatch = 1;
|
||||
}
|
||||
if( pConstraint->usable==0 ) continue;
|
||||
if( (iPlan & 1)==0
|
||||
&& pConstraint->iColumn==CLOSURE_COL_ROOT
|
||||
@@ -893,6 +888,18 @@ static int closureBestIndex(
|
||||
** or else the result is an empty set. */
|
||||
iPlan = 0;
|
||||
}
|
||||
if( (iPlan&1)==0 ){
|
||||
/* If there is no usable "root=?" term, then set the index-type to 0.
|
||||
** Also clear any argvIndex variables already set. This is necessary
|
||||
** to prevent the core from throwing an "xBestIndex malfunction error"
|
||||
** error (because the argvIndex values are not contiguously assigned
|
||||
** starting from 1). */
|
||||
rCost *= 1e30;
|
||||
for(i=0; i<pIdxInfo->nConstraint; i++, pConstraint++){
|
||||
pIdxInfo->aConstraintUsage[i].argvIndex = 0;
|
||||
}
|
||||
iPlan = 0;
|
||||
}
|
||||
pIdxInfo->idxNum = iPlan;
|
||||
if( pIdxInfo->nOrderBy==1
|
||||
&& pIdxInfo->aOrderBy[0].iColumn==CLOSURE_COL_ID
|
||||
@@ -900,7 +907,6 @@ static int closureBestIndex(
|
||||
){
|
||||
pIdxInfo->orderByConsumed = 1;
|
||||
}
|
||||
if( seenMatch && (iPlan&1)==0 ) rCost *= 1e30;
|
||||
pIdxInfo->estimatedCost = rCost;
|
||||
|
||||
return SQLITE_OK;
|
||||
|
||||
+8
-30
@@ -62,6 +62,7 @@ struct completion_cursor {
|
||||
char *zPrefix; /* The prefix for the word we want to complete */
|
||||
char *zLine; /* The whole that we want to complete */
|
||||
const char *zCurrentRow; /* Current output row */
|
||||
int szRow; /* Length of the zCurrentRow string */
|
||||
sqlite3_stmt *pStmt; /* Current statement */
|
||||
sqlite3_int64 iRowid; /* The rowid */
|
||||
int ePhase; /* Current phase */
|
||||
@@ -174,32 +175,6 @@ static int completionClose(sqlite3_vtab_cursor *cur){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** All SQL keywords understood by SQLite
|
||||
*/
|
||||
static const char *completionKwrds[] = {
|
||||
"ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
|
||||
"ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
|
||||
"CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
|
||||
"CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
|
||||
"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
|
||||
"DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
|
||||
"ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
|
||||
"FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
|
||||
"IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
|
||||
"INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
|
||||
"LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
|
||||
"NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
|
||||
"PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
|
||||
"REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
|
||||
"ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
|
||||
"TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
|
||||
"UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
|
||||
"WITH", "WITHOUT",
|
||||
};
|
||||
#define completionKwCount \
|
||||
(int)(sizeof(completionKwrds)/sizeof(completionKwrds[0]))
|
||||
|
||||
/*
|
||||
** Advance a completion_cursor to its next row of output.
|
||||
**
|
||||
@@ -222,11 +197,11 @@ static int completionNext(sqlite3_vtab_cursor *cur){
|
||||
while( pCur->ePhase!=COMPLETION_EOF ){
|
||||
switch( pCur->ePhase ){
|
||||
case COMPLETION_KEYWORDS: {
|
||||
if( pCur->j >= completionKwCount ){
|
||||
if( pCur->j >= sqlite3_keyword_count() ){
|
||||
pCur->zCurrentRow = 0;
|
||||
pCur->ePhase = COMPLETION_DATABASES;
|
||||
}else{
|
||||
pCur->zCurrentRow = completionKwrds[pCur->j++];
|
||||
sqlite3_keyword_name(pCur->j++, &pCur->zCurrentRow, &pCur->szRow);
|
||||
}
|
||||
iCol = -1;
|
||||
break;
|
||||
@@ -298,6 +273,7 @@ static int completionNext(sqlite3_vtab_cursor *cur){
|
||||
if( sqlite3_step(pCur->pStmt)==SQLITE_ROW ){
|
||||
/* Extract the next row of content */
|
||||
pCur->zCurrentRow = (const char*)sqlite3_column_text(pCur->pStmt, iCol);
|
||||
pCur->szRow = sqlite3_column_bytes(pCur->pStmt, iCol);
|
||||
}else{
|
||||
/* When all rows are finished, advance to the next phase */
|
||||
sqlite3_finalize(pCur->pStmt);
|
||||
@@ -307,7 +283,9 @@ static int completionNext(sqlite3_vtab_cursor *cur){
|
||||
}
|
||||
}
|
||||
if( pCur->nPrefix==0 ) break;
|
||||
if( sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0 ){
|
||||
if( pCur->nPrefix<=pCur->szRow
|
||||
&& sqlite3_strnicmp(pCur->zPrefix, pCur->zCurrentRow, pCur->nPrefix)==0
|
||||
){
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -327,7 +305,7 @@ static int completionColumn(
|
||||
completion_cursor *pCur = (completion_cursor*)cur;
|
||||
switch( i ){
|
||||
case COMPLETION_COLUMN_CANDIDATE: {
|
||||
sqlite3_result_text(ctx, pCur->zCurrentRow, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_result_text(ctx, pCur->zCurrentRow, pCur->szRow,SQLITE_TRANSIENT);
|
||||
break;
|
||||
}
|
||||
case COMPLETION_COLUMN_PREFIX: {
|
||||
|
||||
+5
-5
@@ -132,6 +132,7 @@ static int csv_reader_open(
|
||||
}
|
||||
p->in = fopen(zFilename, "rb");
|
||||
if( p->in==0 ){
|
||||
sqlite3_free(p->zIn);
|
||||
csv_reader_reset(p);
|
||||
csv_errmsg(p, "cannot open '%s' for reading", zFilename);
|
||||
return 1;
|
||||
@@ -204,7 +205,8 @@ static int csv_append(CsvReader *p, char c){
|
||||
** + Store the character that terminates the field in p->cTerm. Store
|
||||
** EOF on end-of-file.
|
||||
**
|
||||
** Return "" at EOF. Return 0 on an OOM error.
|
||||
** Return 0 at EOF or on OOM. On EOF, the p->cTerm character will have
|
||||
** been set to EOF.
|
||||
*/
|
||||
static char *csv_read_one_field(CsvReader *p){
|
||||
int c;
|
||||
@@ -212,7 +214,7 @@ static char *csv_read_one_field(CsvReader *p){
|
||||
c = csv_getc(p);
|
||||
if( c==EOF ){
|
||||
p->cTerm = EOF;
|
||||
return "";
|
||||
return 0;
|
||||
}
|
||||
if( c=='"' ){
|
||||
int pc, ppc;
|
||||
@@ -543,8 +545,7 @@ static int csvtabConnect(
|
||||
pNew->nCol = nCol;
|
||||
}else{
|
||||
do{
|
||||
const char *z = csv_read_one_field(&sRdr);
|
||||
if( z==0 ) goto csvtab_connect_oom;
|
||||
csv_read_one_field(&sRdr);
|
||||
pNew->nCol++;
|
||||
}while( sRdr.cTerm==',' );
|
||||
}
|
||||
@@ -662,7 +663,6 @@ static int csvtabNext(sqlite3_vtab_cursor *cur){
|
||||
do{
|
||||
z = csv_read_one_field(&pCur->rdr);
|
||||
if( z==0 ){
|
||||
csv_xfer_error(pTab, &pCur->rdr);
|
||||
break;
|
||||
}
|
||||
if( i<pTab->nCol ){
|
||||
|
||||
+2
-35
@@ -141,45 +141,12 @@ static void appendText(DText *p, char const *zAppend, char quote){
|
||||
** Return '"' if quoting is required. Return 0 if no quoting is required.
|
||||
*/
|
||||
static char quoteChar(const char *zName){
|
||||
/* All SQLite keywords, in alphabetical order */
|
||||
static const char *azKeywords[] = {
|
||||
"ABORT", "ACTION", "ADD", "AFTER", "ALL", "ALTER", "ANALYZE", "AND", "AS",
|
||||
"ASC", "ATTACH", "AUTOINCREMENT", "BEFORE", "BEGIN", "BETWEEN", "BY",
|
||||
"CASCADE", "CASE", "CAST", "CHECK", "COLLATE", "COLUMN", "COMMIT",
|
||||
"CONFLICT", "CONSTRAINT", "CREATE", "CROSS", "CURRENT_DATE",
|
||||
"CURRENT_TIME", "CURRENT_TIMESTAMP", "DATABASE", "DEFAULT", "DEFERRABLE",
|
||||
"DEFERRED", "DELETE", "DESC", "DETACH", "DISTINCT", "DROP", "EACH",
|
||||
"ELSE", "END", "ESCAPE", "EXCEPT", "EXCLUSIVE", "EXISTS", "EXPLAIN",
|
||||
"FAIL", "FOR", "FOREIGN", "FROM", "FULL", "GLOB", "GROUP", "HAVING", "IF",
|
||||
"IGNORE", "IMMEDIATE", "IN", "INDEX", "INDEXED", "INITIALLY", "INNER",
|
||||
"INSERT", "INSTEAD", "INTERSECT", "INTO", "IS", "ISNULL", "JOIN", "KEY",
|
||||
"LEFT", "LIKE", "LIMIT", "MATCH", "NATURAL", "NO", "NOT", "NOTNULL",
|
||||
"NULL", "OF", "OFFSET", "ON", "OR", "ORDER", "OUTER", "PLAN", "PRAGMA",
|
||||
"PRIMARY", "QUERY", "RAISE", "RECURSIVE", "REFERENCES", "REGEXP",
|
||||
"REINDEX", "RELEASE", "RENAME", "REPLACE", "RESTRICT", "RIGHT",
|
||||
"ROLLBACK", "ROW", "SAVEPOINT", "SELECT", "SET", "TABLE", "TEMP",
|
||||
"TEMPORARY", "THEN", "TO", "TRANSACTION", "TRIGGER", "UNION", "UNIQUE",
|
||||
"UPDATE", "USING", "VACUUM", "VALUES", "VIEW", "VIRTUAL", "WHEN", "WHERE",
|
||||
"WITH", "WITHOUT",
|
||||
};
|
||||
int i, lwr, upr, mid, c;
|
||||
int i;
|
||||
if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"';
|
||||
for(i=0; zName[i]; i++){
|
||||
if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"';
|
||||
}
|
||||
lwr = 0;
|
||||
upr = sizeof(azKeywords)/sizeof(azKeywords[0]) - 1;
|
||||
while( lwr<=upr ){
|
||||
mid = (lwr+upr)/2;
|
||||
c = sqlite3_stricmp(azKeywords[mid], zName);
|
||||
if( c==0 ) return '"';
|
||||
if( c<0 ){
|
||||
lwr = mid+1;
|
||||
}else{
|
||||
upr = mid-1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return sqlite3_keyword_check(zName, i) ? '"' : 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -2118,7 +2118,7 @@ static int jsonEachColumn(
|
||||
}
|
||||
if( p->eType==JSON_ARRAY ){
|
||||
jsonPrintf(30, &x, "[%d]", p->iRowid);
|
||||
}else{
|
||||
}else if( p->eType==JSON_OBJECT ){
|
||||
jsonPrintf(pThis->n, &x, ".%.*s", pThis->n-2, pThis->u.zJContent+1);
|
||||
}
|
||||
}
|
||||
|
||||
+25
-9
@@ -10,40 +10,45 @@
|
||||
**
|
||||
*************************************************************************
|
||||
**
|
||||
** This file implements a template virtual-table implementation.
|
||||
** This file implements a template virtual-table.
|
||||
** Developers can make a copy of this file as a baseline for writing
|
||||
** new virtual tables and/or table-valued functions.
|
||||
**
|
||||
** Steps for writing a new virtual table implementation:
|
||||
**
|
||||
** (1) Make a copy of this file. Prehaps "mynewvtab.c"
|
||||
** (1) Make a copy of this file. Perhaps call it "mynewvtab.c"
|
||||
**
|
||||
** (2) Replace this header comment with something appropriate for
|
||||
** the new virtual table
|
||||
**
|
||||
** (3) Change every occurrence of "templatevtab" to some other string
|
||||
** appropriate for the new virtual table. Ideally, the new string
|
||||
** should be the basename of the source file: "mynewvtab".
|
||||
** should be the basename of the source file: "mynewvtab". Also
|
||||
** globally change "TEMPLATEVTAB" to "MYNEWVTAB".
|
||||
**
|
||||
** (4) Run a test compilation to make sure the unmodified virtual
|
||||
** table works.
|
||||
**
|
||||
** (5) Begin making changes to make the new virtual table do what you
|
||||
** want it to do.
|
||||
**
|
||||
** (6) Ensure that all the "FIXME" comments in the file have been dealt
|
||||
** with.
|
||||
** (5) Begin making incremental changes, testing as you go, to evolve
|
||||
** the new virtual table to do what you want it to do.
|
||||
**
|
||||
** This template is minimal, in the sense that it uses only the required
|
||||
** methods on the sqlite3_module object. As a result, templatevtab is
|
||||
** a read-only and eponymous-only table. Those limitation can be removed
|
||||
** by adding new methods.
|
||||
**
|
||||
** This template implements an eponymous-only virtual table with a rowid and
|
||||
** two columns named "a" and "b". The table as 10 rows with fixed integer
|
||||
** values. Usage example:
|
||||
**
|
||||
** SELECT rowid, a, b FROM templatevtab;
|
||||
*/
|
||||
#if !defined(SQLITEINT_H)
|
||||
#include "sqlite3ext.h"
|
||||
#endif
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/* templatevtab_vtab is a subclass of sqlite3_vtab which is
|
||||
** underlying representation of the virtual table
|
||||
@@ -92,6 +97,9 @@ static int templatevtabConnect(
|
||||
rc = sqlite3_declare_vtab(db,
|
||||
"CREATE TABLE x(a,b)"
|
||||
);
|
||||
/* For convenience, define symbolic names for the index to each column. */
|
||||
#define TEMPLATEVTAB_A 0
|
||||
#define TEMPLATEVTAB_B 1
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew = sqlite3_malloc( sizeof(*pNew) );
|
||||
*ppVtab = (sqlite3_vtab*)pNew;
|
||||
@@ -151,7 +159,15 @@ static int templatevtabColumn(
|
||||
int i /* Which column to return */
|
||||
){
|
||||
templatevtab_cursor *pCur = (templatevtab_cursor*)cur;
|
||||
sqlite3_result_int(ctx, (i+1)*1000 + pCur->iRowid);
|
||||
switch( i ){
|
||||
case TEMPLATEVTAB_A:
|
||||
sqlite3_result_int(ctx, 1000 + pCur->iRowid);
|
||||
break;
|
||||
default:
|
||||
assert( i==TEMPLATEVTAB_B );
|
||||
sqlite3_result_int(ctx, 2000 + pCur->iRowid);
|
||||
break;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
+43
-3
@@ -29,7 +29,9 @@ void usage(const char *zArgv0){
|
||||
"Where options are:\n"
|
||||
"\n"
|
||||
" -step NSTEP\n"
|
||||
" -statstep NSTATSTEP\n"
|
||||
" -vacuum\n"
|
||||
" -presql SQL\n"
|
||||
"\n"
|
||||
" If the -vacuum switch is not present, argument RBU-DB must be an RBU\n"
|
||||
" database containing an update suitable for target database TARGET-DB.\n"
|
||||
@@ -79,7 +81,9 @@ int main(int argc, char **argv){
|
||||
char *zErrmsg; /* Error message, if any */
|
||||
sqlite3rbu *pRbu; /* RBU handle */
|
||||
int nStep = 0; /* Maximum number of step() calls */
|
||||
int nStatStep = 0; /* Report stats after this many step calls */
|
||||
int bVacuum = 0;
|
||||
const char *zPreSql = 0;
|
||||
int rc;
|
||||
sqlite3_int64 nProgress = 0;
|
||||
int nArgc = argc-2;
|
||||
@@ -90,9 +94,18 @@ int main(int argc, char **argv){
|
||||
int nArg = strlen(zArg);
|
||||
if( nArg>1 && nArg<=8 && 0==memcmp(zArg, "-vacuum", nArg) ){
|
||||
bVacuum = 1;
|
||||
}else if( nArg>1 && nArg<=7
|
||||
&& 0==memcmp(zArg, "-presql", nArg) && i<nArg-1 ){
|
||||
i++;
|
||||
zPreSql = argv[i];
|
||||
}else if( nArg>1 && nArg<=5 && 0==memcmp(zArg, "-step", nArg) && i<nArg-1 ){
|
||||
i++;
|
||||
nStep = atoi(argv[i]);
|
||||
}else if( nArg>1 && nArg<=9
|
||||
&& 0==memcmp(zArg, "-statstep", nArg) && i<nArg-1
|
||||
){
|
||||
i++;
|
||||
nStatStep = atoi(argv[i]);
|
||||
}else{
|
||||
usage(argv[0]);
|
||||
}
|
||||
@@ -112,13 +125,40 @@ int main(int argc, char **argv){
|
||||
}
|
||||
report_rbu_vfs(pRbu);
|
||||
|
||||
if( zPreSql && pRbu ){
|
||||
sqlite3 *db = sqlite3rbu_db(pRbu, 0);
|
||||
rc = sqlite3_exec(db, zPreSql, 0, 0, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3 *db = sqlite3rbu_db(pRbu, 1);
|
||||
rc = sqlite3_exec(db, zPreSql, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* If nStep is less than or equal to zero, call
|
||||
** sqlite3rbu_step() until either the RBU has been completely applied
|
||||
** or an error occurs. Or, if nStep is greater than zero, call
|
||||
** sqlite3rbu_step() a maximum of nStep times. */
|
||||
for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++);
|
||||
nProgress = sqlite3rbu_progress(pRbu);
|
||||
rc = sqlite3rbu_close(pRbu, &zErrmsg);
|
||||
if( rc==SQLITE_OK ){
|
||||
for(i=0; (nStep<=0 || i<nStep) && sqlite3rbu_step(pRbu)==SQLITE_OK; i++){
|
||||
if( nStatStep>0 && (i % nStatStep)==0 ){
|
||||
sqlite3_int64 nUsed;
|
||||
sqlite3_int64 nHighwater;
|
||||
sqlite3_status64(SQLITE_STATUS_MEMORY_USED, &nUsed, &nHighwater, 0);
|
||||
fprintf(stdout, "memory used=%lld highwater=%lld", nUsed, nHighwater);
|
||||
if( bVacuum==0 ){
|
||||
int one;
|
||||
int two;
|
||||
sqlite3rbu_bp_progress(pRbu, &one, &two);
|
||||
fprintf(stdout, " progress=%d/%d\n", one, two);
|
||||
}else{
|
||||
fprintf(stdout, "\n");
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
nProgress = sqlite3rbu_progress(pRbu);
|
||||
rc = sqlite3rbu_close(pRbu, &zErrmsg);
|
||||
}
|
||||
|
||||
/* Let the user know what happened. */
|
||||
switch( rc ){
|
||||
|
||||
@@ -139,6 +139,7 @@ foreach {tn3 create_vfs destroy_vfs} {
|
||||
foreach {tn2 cmd} {
|
||||
1 run_rbu
|
||||
2 step_rbu 3 step_rbu_uri 4 step_rbu_state
|
||||
5 step_rbu_legacy
|
||||
} {
|
||||
foreach {tn schema} {
|
||||
1 {
|
||||
|
||||
@@ -70,6 +70,22 @@ proc step_rbu {target rbu} {
|
||||
set rc
|
||||
}
|
||||
|
||||
proc step_rbu_legacy {target rbu} {
|
||||
while 1 {
|
||||
sqlite3rbu rbu $target $rbu
|
||||
set state [rbu state]
|
||||
check_prestep_state $target $state
|
||||
set rc [rbu step]
|
||||
check_poststep_state $rc $target $state
|
||||
rbu close
|
||||
if {$rc != "SQLITE_OK"} break
|
||||
sqlite3 tmpdb $rbu
|
||||
tmpdb eval { DELETE FROM rbu_state WHERE k==10 }
|
||||
tmpdb close
|
||||
}
|
||||
set rc
|
||||
}
|
||||
|
||||
proc do_rbu_vacuum_test {tn step} {
|
||||
forcedelete state.db
|
||||
uplevel [list do_test $tn.1 {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
# 2018 April 28
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] rbu_common.tcl]
|
||||
set ::testprefix rbusplit
|
||||
|
||||
db close
|
||||
sqlite3_shutdown
|
||||
sqlite3_config_uri 1
|
||||
|
||||
autoinstall_test_functions
|
||||
|
||||
proc build_db {db} {
|
||||
$db eval {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b, c);
|
||||
CREATE TABLE t2(a PRIMARY KEY, b, c);
|
||||
|
||||
CREATE INDEX t1c ON t1(c);
|
||||
}
|
||||
}
|
||||
|
||||
proc build_rbu {filename} {
|
||||
forcedelete $filename
|
||||
sqlite3 dbRbu $filename
|
||||
dbRbu eval {
|
||||
CREATE TABLE data0_t1(a, b, c, rbu_control);
|
||||
CREATE TABLE data1_t1(a, b, c, rbu_control);
|
||||
CREATE TABLE data2_t1(a, b, c, rbu_control);
|
||||
CREATE TABLE data3_t1(a, b, c, rbu_control);
|
||||
|
||||
CREATE TABLE data_t2(a, b, c, rbu_control);
|
||||
|
||||
INSERT INTO data0_t1 VALUES(1, 1, 1, 0);
|
||||
INSERT INTO data0_t1 VALUES(2, 2, 2, 0);
|
||||
INSERT INTO data0_t1 VALUES(3, 3, 3, 0);
|
||||
INSERT INTO data0_t1 VALUES(4, 4, 4, 0);
|
||||
INSERT INTO data1_t1 VALUES(5, 5, 5, 0);
|
||||
INSERT INTO data1_t1 VALUES(6, 6, 6, 0);
|
||||
INSERT INTO data1_t1 VALUES(7, 7, 7, 0);
|
||||
INSERT INTO data1_t1 VALUES(8, 8, 8, 0);
|
||||
INSERT INTO data3_t1 VALUES(9, 9, 9, 0);
|
||||
|
||||
INSERT INTO data_t2 VALUES(1, 1, 1, 0);
|
||||
INSERT INTO data_t2 VALUES(2, 2, 2, 0);
|
||||
INSERT INTO data_t2 VALUES(3, 3, 3, 0);
|
||||
INSERT INTO data_t2 VALUES(4, 4, 4, 0);
|
||||
INSERT INTO data_t2 VALUES(5, 5, 5, 0);
|
||||
INSERT INTO data_t2 VALUES(6, 6, 6, 0);
|
||||
INSERT INTO data_t2 VALUES(7, 7, 7, 0);
|
||||
INSERT INTO data_t2 VALUES(8, 8, 8, 0);
|
||||
INSERT INTO data_t2 VALUES(9, 9, 9, 0);
|
||||
}
|
||||
|
||||
dbRbu close
|
||||
}
|
||||
|
||||
foreach {tn cmd} {
|
||||
1 run_rbu
|
||||
2 step_rbu
|
||||
} {
|
||||
reset_db
|
||||
build_db db
|
||||
build_rbu testrbu.db
|
||||
|
||||
do_test 1.$tn.1 {
|
||||
$cmd test.db testrbu.db
|
||||
} {SQLITE_DONE}
|
||||
do_execsql_test 1.$tn.1 {
|
||||
SELECT * FROM t1;
|
||||
} {
|
||||
1 1 1 2 2 2 3 3 3 4 4 4
|
||||
5 5 5 6 6 6 7 7 7 8 8 8
|
||||
9 9 9
|
||||
}
|
||||
do_execsql_test 1.$tn.2 {
|
||||
SELECT * FROM t2;
|
||||
} {
|
||||
1 1 1 2 2 2 3 3 3 4 4 4
|
||||
5 5 5 6 6 6 7 7 7 8 8 8
|
||||
9 9 9
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+17
-3
@@ -153,6 +153,10 @@
|
||||
**
|
||||
** RBU_STATE_OALSZ:
|
||||
** Valid if STAGE==1. The size in bytes of the *-oal file.
|
||||
**
|
||||
** RBU_STATE_DATATBL:
|
||||
** Only valid if STAGE==1. The RBU database name of the table
|
||||
** currently being read.
|
||||
*/
|
||||
#define RBU_STATE_STAGE 1
|
||||
#define RBU_STATE_TBL 2
|
||||
@@ -163,6 +167,7 @@
|
||||
#define RBU_STATE_COOKIE 7
|
||||
#define RBU_STATE_OALSZ 8
|
||||
#define RBU_STATE_PHASEONESTEP 9
|
||||
#define RBU_STATE_DATATBL 10
|
||||
|
||||
#define RBU_STAGE_OAL 1
|
||||
#define RBU_STAGE_MOVE 2
|
||||
@@ -205,6 +210,7 @@ typedef sqlite3_int64 i64;
|
||||
struct RbuState {
|
||||
int eStage;
|
||||
char *zTbl;
|
||||
char *zDataTbl;
|
||||
char *zIdx;
|
||||
i64 iWalCksum;
|
||||
int nRow;
|
||||
@@ -2268,6 +2274,7 @@ static sqlite3 *rbuOpenDbhandle(
|
||||
static void rbuFreeState(RbuState *p){
|
||||
if( p ){
|
||||
sqlite3_free(p->zTbl);
|
||||
sqlite3_free(p->zDataTbl);
|
||||
sqlite3_free(p->zIdx);
|
||||
sqlite3_free(p);
|
||||
}
|
||||
@@ -2338,6 +2345,10 @@ static RbuState *rbuLoadState(sqlite3rbu *p){
|
||||
pRet->nPhaseOneStep = sqlite3_column_int64(pStmt, 1);
|
||||
break;
|
||||
|
||||
case RBU_STATE_DATATBL:
|
||||
pRet->zDataTbl = rbuStrndup((char*)sqlite3_column_text(pStmt, 1), &rc);
|
||||
break;
|
||||
|
||||
default:
|
||||
rc = SQLITE_CORRUPT;
|
||||
break;
|
||||
@@ -3112,7 +3123,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
|
||||
"(%d, %lld), "
|
||||
"(%d, %lld), "
|
||||
"(%d, %lld), "
|
||||
"(%d, %lld) ",
|
||||
"(%d, %lld), "
|
||||
"(%d, %Q) ",
|
||||
p->zStateDb,
|
||||
RBU_STATE_STAGE, eStage,
|
||||
RBU_STATE_TBL, p->objiter.zTbl,
|
||||
@@ -3122,7 +3134,8 @@ static void rbuSaveState(sqlite3rbu *p, int eStage){
|
||||
RBU_STATE_CKPT, p->iWalCksum,
|
||||
RBU_STATE_COOKIE, (i64)pFd->iCookie,
|
||||
RBU_STATE_OALSZ, p->iOalSz,
|
||||
RBU_STATE_PHASEONESTEP, p->nPhaseOneStep
|
||||
RBU_STATE_PHASEONESTEP, p->nPhaseOneStep,
|
||||
RBU_STATE_DATATBL, p->objiter.zDataTbl
|
||||
)
|
||||
);
|
||||
assert( pInsert==0 || rc==SQLITE_OK );
|
||||
@@ -3378,7 +3391,8 @@ static void rbuSetupOal(sqlite3rbu *p, RbuState *pState){
|
||||
|
||||
while( rc==SQLITE_OK && pIter->zTbl && (pIter->bCleanup
|
||||
|| rbuStrCompare(pIter->zIdx, pState->zIdx)
|
||||
|| rbuStrCompare(pIter->zTbl, pState->zTbl)
|
||||
|| (pState->zDataTbl==0 && rbuStrCompare(pIter->zTbl, pState->zTbl))
|
||||
|| (pState->zDataTbl && rbuStrCompare(pIter->zDataTbl, pState->zDataTbl))
|
||||
)){
|
||||
rc = rbuObjIterNext(p, pIter);
|
||||
}
|
||||
|
||||
+244
-88
@@ -24,14 +24,15 @@
|
||||
**
|
||||
** CREATE TABLE %_node(nodeno INTEGER PRIMARY KEY, data BLOB)
|
||||
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
|
||||
**
|
||||
** The data for each node of the r-tree structure is stored in the %_node
|
||||
** table. For each node that is not the root node of the r-tree, there is
|
||||
** an entry in the %_parent table associating the node with its parent.
|
||||
** And for each row of data in the table, there is an entry in the %_rowid
|
||||
** table that maps from the entries rowid to the id of the node that it
|
||||
** is stored on.
|
||||
** is stored on. If the r-tree contains auxiliary columns, those are stored
|
||||
** on the end of the %_rowid table.
|
||||
**
|
||||
** The root node of an r-tree always exists, even if the r-tree table is
|
||||
** empty. The nodeno of the root node is always 1. All other nodes in the
|
||||
@@ -94,6 +95,9 @@ typedef struct RtreeSearchPoint RtreeSearchPoint;
|
||||
/* The rtree may have between 1 and RTREE_MAX_DIMENSIONS dimensions. */
|
||||
#define RTREE_MAX_DIMENSIONS 5
|
||||
|
||||
/* Maximum number of auxiliary columns */
|
||||
#define RTREE_MAX_AUX_COLUMN 100
|
||||
|
||||
/* Size of hash table Rtree.aHash. This hash table is not expected to
|
||||
** ever contain very many entries, so a fixed number of buckets is
|
||||
** used.
|
||||
@@ -122,12 +126,15 @@ struct Rtree {
|
||||
u8 eCoordType; /* RTREE_COORD_REAL32 or RTREE_COORD_INT32 */
|
||||
u8 nBytesPerCell; /* Bytes consumed per cell */
|
||||
u8 inWrTrans; /* True if inside write transaction */
|
||||
u8 nAux; /* # of auxiliary columns in %_rowid */
|
||||
int iDepth; /* Current depth of the r-tree structure */
|
||||
char *zDb; /* Name of database containing r-tree table */
|
||||
char *zName; /* Name of r-tree table */
|
||||
u32 nBusy; /* Current number of users of this structure */
|
||||
i64 nRowEst; /* Estimated number of rows in this table */
|
||||
u32 nCursor; /* Number of open cursors */
|
||||
u32 nNodeRef; /* Number RtreeNodes with positive nRef */
|
||||
char *zReadAuxSql; /* SQL for statement to read aux data */
|
||||
|
||||
/* List of nodes removed during a CondenseTree operation. List is
|
||||
** linked together via the pointer normally used for hash chains -
|
||||
@@ -154,6 +161,9 @@ struct Rtree {
|
||||
sqlite3_stmt *pWriteParent;
|
||||
sqlite3_stmt *pDeleteParent;
|
||||
|
||||
/* Statement for writing to the "aux:" fields, if there are any */
|
||||
sqlite3_stmt *pWriteAux;
|
||||
|
||||
RtreeNode *aHash[HASHSIZE]; /* Hash table of in-memory nodes. */
|
||||
};
|
||||
|
||||
@@ -230,6 +240,7 @@ struct RtreeCursor {
|
||||
sqlite3_vtab_cursor base; /* Base class. Must be first */
|
||||
u8 atEOF; /* True if at end of search */
|
||||
u8 bPoint; /* True if sPoint is valid */
|
||||
u8 bAuxValid; /* True if pReadAux is valid */
|
||||
int iStrategy; /* Copy of idxNum search parameter */
|
||||
int nConstraint; /* Number of entries in aConstraint */
|
||||
RtreeConstraint *aConstraint; /* Search constraints. */
|
||||
@@ -237,6 +248,7 @@ struct RtreeCursor {
|
||||
int nPoint; /* Number of slots used in aPoint[] */
|
||||
int mxLevel; /* iLevel value for root of the tree */
|
||||
RtreeSearchPoint *aPoint; /* Priority queue for search points */
|
||||
sqlite3_stmt *pReadAux; /* Statement to read aux-data */
|
||||
RtreeSearchPoint sPoint; /* Cached next search point */
|
||||
RtreeNode *aNode[RTREE_CACHE_SZ]; /* Rtree node cache */
|
||||
u32 anQueue[RTREE_MAX_DEPTH+1]; /* Number of queued entries by iLevel */
|
||||
@@ -523,6 +535,7 @@ static int writeInt64(u8 *p, i64 i){
|
||||
*/
|
||||
static void nodeReference(RtreeNode *p){
|
||||
if( p ){
|
||||
assert( p->nRef>0 );
|
||||
p->nRef++;
|
||||
}
|
||||
}
|
||||
@@ -590,6 +603,7 @@ static RtreeNode *nodeNew(Rtree *pRtree, RtreeNode *pParent){
|
||||
memset(pNode, 0, sizeof(RtreeNode) + pRtree->iNodeSize);
|
||||
pNode->zData = (u8 *)&pNode[1];
|
||||
pNode->nRef = 1;
|
||||
pRtree->nNodeRef++;
|
||||
pNode->pParent = pParent;
|
||||
pNode->isDirty = 1;
|
||||
nodeReference(pParent);
|
||||
@@ -623,10 +637,10 @@ static int nodeAcquire(
|
||||
/* Check if the requested node is already in the hash table. If so,
|
||||
** increase its reference count and return it.
|
||||
*/
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode)) ){
|
||||
if( (pNode = nodeHashLookup(pRtree, iNode))!=0 ){
|
||||
assert( !pParent || !pNode->pParent || pNode->pParent==pParent );
|
||||
if( pParent && !pNode->pParent ){
|
||||
nodeReference(pParent);
|
||||
pParent->nRef++;
|
||||
pNode->pParent = pParent;
|
||||
}
|
||||
pNode->nRef++;
|
||||
@@ -665,6 +679,7 @@ static int nodeAcquire(
|
||||
pNode->pParent = pParent;
|
||||
pNode->zData = (u8 *)&pNode[1];
|
||||
pNode->nRef = 1;
|
||||
pRtree->nNodeRef++;
|
||||
pNode->iNode = iNode;
|
||||
pNode->isDirty = 0;
|
||||
pNode->pNext = 0;
|
||||
@@ -705,7 +720,10 @@ static int nodeAcquire(
|
||||
}
|
||||
*ppNode = pNode;
|
||||
}else{
|
||||
sqlite3_free(pNode);
|
||||
if( pNode ){
|
||||
pRtree->nNodeRef--;
|
||||
sqlite3_free(pNode);
|
||||
}
|
||||
*ppNode = 0;
|
||||
}
|
||||
|
||||
@@ -802,8 +820,10 @@ static int nodeRelease(Rtree *pRtree, RtreeNode *pNode){
|
||||
int rc = SQLITE_OK;
|
||||
if( pNode ){
|
||||
assert( pNode->nRef>0 );
|
||||
assert( pRtree->nNodeRef>0 );
|
||||
pNode->nRef--;
|
||||
if( pNode->nRef==0 ){
|
||||
pRtree->nNodeRef--;
|
||||
if( pNode->iNode==1 ){
|
||||
pRtree->iDepth = -1;
|
||||
}
|
||||
@@ -920,8 +940,9 @@ static void rtreeRelease(Rtree *pRtree){
|
||||
pRtree->nBusy--;
|
||||
if( pRtree->nBusy==0 ){
|
||||
pRtree->inWrTrans = 0;
|
||||
pRtree->nCursor = 0;
|
||||
assert( pRtree->nCursor==0 );
|
||||
nodeBlobReset(pRtree);
|
||||
assert( pRtree->nNodeRef==0 );
|
||||
sqlite3_finalize(pRtree->pWriteNode);
|
||||
sqlite3_finalize(pRtree->pDeleteNode);
|
||||
sqlite3_finalize(pRtree->pReadRowid);
|
||||
@@ -930,6 +951,8 @@ static void rtreeRelease(Rtree *pRtree){
|
||||
sqlite3_finalize(pRtree->pReadParent);
|
||||
sqlite3_finalize(pRtree->pWriteParent);
|
||||
sqlite3_finalize(pRtree->pDeleteParent);
|
||||
sqlite3_finalize(pRtree->pWriteAux);
|
||||
sqlite3_free(pRtree->zReadAuxSql);
|
||||
sqlite3_free(pRtree);
|
||||
}
|
||||
}
|
||||
@@ -1018,6 +1041,7 @@ static int rtreeClose(sqlite3_vtab_cursor *cur){
|
||||
RtreeCursor *pCsr = (RtreeCursor *)cur;
|
||||
assert( pRtree->nCursor>0 );
|
||||
freeCursorConstraints(pCsr);
|
||||
sqlite3_finalize(pCsr->pReadAux);
|
||||
sqlite3_free(pCsr->aPoint);
|
||||
for(ii=0; ii<RTREE_CACHE_SZ; ii++) nodeRelease(pRtree, pCsr->aNode[ii]);
|
||||
sqlite3_free(pCsr);
|
||||
@@ -1389,7 +1413,7 @@ static RtreeSearchPoint *rtreeSearchPointNew(
|
||||
if( ii<RTREE_CACHE_SZ ){
|
||||
assert( pCur->aNode[ii]==0 );
|
||||
pCur->aNode[ii] = pCur->aNode[0];
|
||||
}else{
|
||||
}else{
|
||||
nodeRelease(RTREE_OF_CURSOR(pCur), pCur->aNode[0]);
|
||||
}
|
||||
pCur->aNode[0] = 0;
|
||||
@@ -1560,6 +1584,10 @@ static int rtreeNext(sqlite3_vtab_cursor *pVtabCursor){
|
||||
|
||||
/* Move to the next entry that matches the configured constraints. */
|
||||
RTREE_QUEUE_TRACE(pCsr, "POP-Nx:");
|
||||
if( pCsr->bAuxValid ){
|
||||
pCsr->bAuxValid = 0;
|
||||
sqlite3_reset(pCsr->pReadAux);
|
||||
}
|
||||
rtreeSearchPointPop(pCsr);
|
||||
rc = rtreeStepToLeaf(pCsr);
|
||||
return rc;
|
||||
@@ -1594,7 +1622,7 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
if( p==0 ) return SQLITE_OK;
|
||||
if( i==0 ){
|
||||
sqlite3_result_int64(ctx, nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
}else{
|
||||
}else if( i<=pRtree->nDim2 ){
|
||||
nodeGetCoord(pRtree, pNode, p->iCell, i-1, &c);
|
||||
#ifndef SQLITE_RTREE_INT_ONLY
|
||||
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
|
||||
@@ -1605,7 +1633,27 @@ static int rtreeColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
assert( pRtree->eCoordType==RTREE_COORD_INT32 );
|
||||
sqlite3_result_int(ctx, c.i);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if( !pCsr->bAuxValid ){
|
||||
if( pCsr->pReadAux==0 ){
|
||||
rc = sqlite3_prepare_v3(pRtree->db, pRtree->zReadAuxSql, -1, 0,
|
||||
&pCsr->pReadAux, 0);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
sqlite3_bind_int64(pCsr->pReadAux, 1,
|
||||
nodeGetRowid(pRtree, pNode, p->iCell));
|
||||
rc = sqlite3_step(pCsr->pReadAux);
|
||||
if( rc==SQLITE_ROW ){
|
||||
pCsr->bAuxValid = 1;
|
||||
}else{
|
||||
sqlite3_reset(pCsr->pReadAux);
|
||||
if( rc==SQLITE_DONE ) rc = SQLITE_OK;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
sqlite3_result_value(ctx,
|
||||
sqlite3_column_value(pCsr->pReadAux, i - pRtree->nDim2 + 1));
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -1683,14 +1731,17 @@ static int rtreeFilter(
|
||||
int ii;
|
||||
int rc = SQLITE_OK;
|
||||
int iCell = 0;
|
||||
sqlite3_stmt *pStmt;
|
||||
|
||||
rtreeReference(pRtree);
|
||||
|
||||
/* Reset the cursor to the same state as rtreeOpen() leaves it in. */
|
||||
freeCursorConstraints(pCsr);
|
||||
sqlite3_free(pCsr->aPoint);
|
||||
pStmt = pCsr->pReadAux;
|
||||
memset(pCsr, 0, sizeof(RtreeCursor));
|
||||
pCsr->base.pVtab = (sqlite3_vtab*)pRtree;
|
||||
pCsr->pReadAux = pStmt;
|
||||
|
||||
pCsr->iStrategy = idxNum;
|
||||
if( idxNum==1 ){
|
||||
@@ -1853,10 +1904,14 @@ static int rtreeBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
*/
|
||||
pIdxInfo->estimatedCost = 30.0;
|
||||
pIdxInfo->estimatedRows = 1;
|
||||
pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
if( p->usable && (p->iColumn>0 || p->op==SQLITE_INDEX_CONSTRAINT_MATCH) ){
|
||||
if( p->usable
|
||||
&& ((p->iColumn>0 && p->iColumn<=pRtree->nDim2)
|
||||
|| p->op==SQLITE_INDEX_CONSTRAINT_MATCH)
|
||||
){
|
||||
u8 op;
|
||||
switch( p->op ){
|
||||
case SQLITE_INDEX_CONSTRAINT_EQ: op = RTREE_EQ; break;
|
||||
@@ -2429,7 +2484,7 @@ static int SplitNode(
|
||||
}else{
|
||||
pLeft = pNode;
|
||||
pRight = nodeNew(pRtree, pLeft->pParent);
|
||||
nodeReference(pLeft);
|
||||
pLeft->nRef++;
|
||||
}
|
||||
|
||||
if( !pLeft || !pRight ){
|
||||
@@ -2919,6 +2974,7 @@ static int rtreeDeleteRowid(Rtree *pRtree, sqlite3_int64 iDelete){
|
||||
rc = reinsertNodeContent(pRtree, pLeaf);
|
||||
}
|
||||
pRtree->pDeleted = pLeaf->pNext;
|
||||
pRtree->nNodeRef--;
|
||||
sqlite3_free(pLeaf);
|
||||
}
|
||||
|
||||
@@ -3015,7 +3071,7 @@ static int rtreeConstraintError(Rtree *pRtree, int iCol){
|
||||
static int rtreeUpdate(
|
||||
sqlite3_vtab *pVtab,
|
||||
int nData,
|
||||
sqlite3_value **azData,
|
||||
sqlite3_value **aData,
|
||||
sqlite_int64 *pRowid
|
||||
){
|
||||
Rtree *pRtree = (Rtree *)pVtab;
|
||||
@@ -3023,6 +3079,12 @@ static int rtreeUpdate(
|
||||
RtreeCell cell; /* New cell to insert if nData>1 */
|
||||
int bHaveRowid = 0; /* Set to 1 after new rowid is determined */
|
||||
|
||||
if( pRtree->nNodeRef ){
|
||||
/* Unable to write to the btree while another cursor is reading from it,
|
||||
** since the write might do a rebalance which would disrupt the read
|
||||
** cursor. */
|
||||
return SQLITE_LOCKED_VTAB;
|
||||
}
|
||||
rtreeReference(pRtree);
|
||||
assert(nData>=1);
|
||||
|
||||
@@ -3041,8 +3103,10 @@ static int rtreeUpdate(
|
||||
*/
|
||||
if( nData>1 ){
|
||||
int ii;
|
||||
int nn = nData - 4;
|
||||
|
||||
/* Populate the cell.aCoord[] array. The first coordinate is azData[3].
|
||||
if( nn > pRtree->nDim2 ) nn = pRtree->nDim2;
|
||||
/* Populate the cell.aCoord[] array. The first coordinate is aData[3].
|
||||
**
|
||||
** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
|
||||
** with "column" that are interpreted as table constraints.
|
||||
@@ -3050,13 +3114,12 @@ static int rtreeUpdate(
|
||||
** This problem was discovered after years of use, so we silently ignore
|
||||
** these kinds of misdeclared tables to avoid breaking any legacy.
|
||||
*/
|
||||
assert( nData<=(pRtree->nDim2 + 3) );
|
||||
|
||||
#ifndef SQLITE_RTREE_INT_ONLY
|
||||
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
|
||||
for(ii=0; ii<nData-4; ii+=2){
|
||||
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
|
||||
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
|
||||
for(ii=0; ii<nn; ii+=2){
|
||||
cell.aCoord[ii].f = rtreeValueDown(aData[ii+3]);
|
||||
cell.aCoord[ii+1].f = rtreeValueUp(aData[ii+4]);
|
||||
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
|
||||
rc = rtreeConstraintError(pRtree, ii+1);
|
||||
goto constraint;
|
||||
@@ -3065,9 +3128,9 @@ static int rtreeUpdate(
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
for(ii=0; ii<nData-4; ii+=2){
|
||||
cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
|
||||
cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
|
||||
for(ii=0; ii<nn; ii+=2){
|
||||
cell.aCoord[ii].i = sqlite3_value_int(aData[ii+3]);
|
||||
cell.aCoord[ii+1].i = sqlite3_value_int(aData[ii+4]);
|
||||
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
|
||||
rc = rtreeConstraintError(pRtree, ii+1);
|
||||
goto constraint;
|
||||
@@ -3077,10 +3140,10 @@ static int rtreeUpdate(
|
||||
|
||||
/* If a rowid value was supplied, check if it is already present in
|
||||
** the table. If so, the constraint has failed. */
|
||||
if( sqlite3_value_type(azData[2])!=SQLITE_NULL ){
|
||||
cell.iRowid = sqlite3_value_int64(azData[2]);
|
||||
if( sqlite3_value_type(azData[0])==SQLITE_NULL
|
||||
|| sqlite3_value_int64(azData[0])!=cell.iRowid
|
||||
if( sqlite3_value_type(aData[2])!=SQLITE_NULL ){
|
||||
cell.iRowid = sqlite3_value_int64(aData[2]);
|
||||
if( sqlite3_value_type(aData[0])==SQLITE_NULL
|
||||
|| sqlite3_value_int64(aData[0])!=cell.iRowid
|
||||
){
|
||||
int steprc;
|
||||
sqlite3_bind_int64(pRtree->pReadRowid, 1, cell.iRowid);
|
||||
@@ -3099,16 +3162,16 @@ static int rtreeUpdate(
|
||||
}
|
||||
}
|
||||
|
||||
/* If azData[0] is not an SQL NULL value, it is the rowid of a
|
||||
/* If aData[0] is not an SQL NULL value, it is the rowid of a
|
||||
** record to delete from the r-tree table. The following block does
|
||||
** just that.
|
||||
*/
|
||||
if( sqlite3_value_type(azData[0])!=SQLITE_NULL ){
|
||||
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(azData[0]));
|
||||
if( sqlite3_value_type(aData[0])!=SQLITE_NULL ){
|
||||
rc = rtreeDeleteRowid(pRtree, sqlite3_value_int64(aData[0]));
|
||||
}
|
||||
|
||||
/* If the azData[] array contains more than one element, elements
|
||||
** (azData[2]..azData[argc-1]) contain a new record to insert into
|
||||
/* If the aData[] array contains more than one element, elements
|
||||
** (aData[2]..aData[argc-1]) contain a new record to insert into
|
||||
** the r-tree structure.
|
||||
*/
|
||||
if( rc==SQLITE_OK && nData>1 ){
|
||||
@@ -3133,6 +3196,16 @@ static int rtreeUpdate(
|
||||
rc = rc2;
|
||||
}
|
||||
}
|
||||
if( pRtree->nAux ){
|
||||
sqlite3_stmt *pUp = pRtree->pWriteAux;
|
||||
int jj;
|
||||
sqlite3_bind_int64(pUp, 1, *pRowid);
|
||||
for(jj=0; jj<pRtree->nAux; jj++){
|
||||
sqlite3_bind_value(pUp, jj+2, aData[pRtree->nDim2+3+jj]);
|
||||
}
|
||||
sqlite3_step(pUp);
|
||||
rc = sqlite3_reset(pUp);
|
||||
}
|
||||
}
|
||||
|
||||
constraint:
|
||||
@@ -3289,18 +3362,18 @@ static int rtreeSqlInit(
|
||||
#define N_STATEMENT 8
|
||||
static const char *azSql[N_STATEMENT] = {
|
||||
/* Write the xxx_node table */
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(:1, :2)",
|
||||
"DELETE FROM '%q'.'%q_node' WHERE nodeno = :1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_node' VALUES(?1, ?2)",
|
||||
"DELETE FROM '%q'.'%q_node' WHERE nodeno = ?1",
|
||||
|
||||
/* Read and write the xxx_rowid table */
|
||||
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = :1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(:1, :2)",
|
||||
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = :1",
|
||||
"SELECT nodeno FROM '%q'.'%q_rowid' WHERE rowid = ?1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_rowid' VALUES(?1, ?2)",
|
||||
"DELETE FROM '%q'.'%q_rowid' WHERE rowid = ?1",
|
||||
|
||||
/* Read and write the xxx_parent table */
|
||||
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = :1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(:1, :2)",
|
||||
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = :1"
|
||||
"SELECT parentnode FROM '%q'.'%q_parent' WHERE nodeno = ?1",
|
||||
"INSERT OR REPLACE INTO '%q'.'%q_parent' VALUES(?1, ?2)",
|
||||
"DELETE FROM '%q'.'%q_parent' WHERE nodeno = ?1"
|
||||
};
|
||||
sqlite3_stmt **appStmt[N_STATEMENT];
|
||||
int i;
|
||||
@@ -3308,14 +3381,25 @@ static int rtreeSqlInit(
|
||||
pRtree->db = db;
|
||||
|
||||
if( isCreate ){
|
||||
char *zCreate = sqlite3_mprintf(
|
||||
"CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY, data BLOB);"
|
||||
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY, nodeno INTEGER);"
|
||||
"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,"
|
||||
" parentnode INTEGER);"
|
||||
"INSERT INTO '%q'.'%q_node' VALUES(1, zeroblob(%d))",
|
||||
zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, zDb, zPrefix, pRtree->iNodeSize
|
||||
);
|
||||
char *zCreate;
|
||||
sqlite3_str *p = sqlite3_str_new(db);
|
||||
int ii;
|
||||
sqlite3_str_appendf(p,
|
||||
"CREATE TABLE \"%w\".\"%w_rowid\"(rowid INTEGER PRIMARY KEY,nodeno",
|
||||
zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
sqlite3_str_appendf(p,",a%d",ii);
|
||||
}
|
||||
sqlite3_str_appendf(p,
|
||||
");CREATE TABLE \"%w\".\"%w_node\"(nodeno INTEGER PRIMARY KEY,data);",
|
||||
zDb, zPrefix);
|
||||
sqlite3_str_appendf(p,
|
||||
"CREATE TABLE \"%w\".\"%w_parent\"(nodeno INTEGER PRIMARY KEY,parentnode);",
|
||||
zDb, zPrefix);
|
||||
sqlite3_str_appendf(p,
|
||||
"INSERT INTO \"%w\".\"%w_node\"VALUES(1,zeroblob(%d))",
|
||||
zDb, zPrefix, pRtree->iNodeSize);
|
||||
zCreate = sqlite3_str_finish(p);
|
||||
if( !zCreate ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
@@ -3337,7 +3421,17 @@ static int rtreeSqlInit(
|
||||
|
||||
rc = rtreeQueryStat1(db, pRtree);
|
||||
for(i=0; i<N_STATEMENT && rc==SQLITE_OK; i++){
|
||||
char *zSql = sqlite3_mprintf(azSql[i], zDb, zPrefix);
|
||||
char *zSql;
|
||||
const char *zFormat;
|
||||
if( i!=3 || pRtree->nAux==0 ){
|
||||
zFormat = azSql[i];
|
||||
}else {
|
||||
/* An UPSERT is very slightly slower than REPLACE, but it is needed
|
||||
** if there are auxiliary columns */
|
||||
zFormat = "INSERT INTO\"%w\".\"%w_rowid\"(rowid,nodeno)VALUES(?1,?2)"
|
||||
"ON CONFLICT(rowid)DO UPDATE SET nodeno=excluded.nodeno";
|
||||
}
|
||||
zSql = sqlite3_mprintf(zFormat, zDb, zPrefix);
|
||||
if( zSql ){
|
||||
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
appStmt[i], 0);
|
||||
@@ -3346,6 +3440,32 @@ static int rtreeSqlInit(
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
if( pRtree->nAux ){
|
||||
pRtree->zReadAuxSql = sqlite3_mprintf(
|
||||
"SELECT * FROM \"%w\".\"%w_rowid\" WHERE rowid=?1",
|
||||
zDb, zPrefix);
|
||||
if( pRtree->zReadAuxSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_str *p = sqlite3_str_new(db);
|
||||
int ii;
|
||||
char *zSql;
|
||||
sqlite3_str_appendf(p, "UPDATE \"%w\".\"%w_rowid\"SET ", zDb, zPrefix);
|
||||
for(ii=0; ii<pRtree->nAux; ii++){
|
||||
if( ii ) sqlite3_str_append(p, ",", 1);
|
||||
sqlite3_str_appendf(p,"a%d=?%d",ii,ii+2);
|
||||
}
|
||||
sqlite3_str_appendf(p, " WHERE rowid=?1");
|
||||
zSql = sqlite3_str_finish(p);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v3(db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
|
||||
&pRtree->pWriteAux, 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -3448,17 +3568,22 @@ static int rtreeInit(
|
||||
int nDb; /* Length of string argv[1] */
|
||||
int nName; /* Length of string argv[2] */
|
||||
int eCoordType = (pAux ? RTREE_COORD_INT32 : RTREE_COORD_REAL32);
|
||||
sqlite3_str *pSql;
|
||||
char *zSql;
|
||||
int ii = 4;
|
||||
int iErr;
|
||||
|
||||
const char *aErrMsg[] = {
|
||||
0, /* 0 */
|
||||
"Wrong number of columns for an rtree table", /* 1 */
|
||||
"Too few columns for an rtree table", /* 2 */
|
||||
"Too many columns for an rtree table" /* 3 */
|
||||
"Too many columns for an rtree table", /* 3 */
|
||||
"Auxiliary rtree columns must be last" /* 4 */
|
||||
};
|
||||
|
||||
int iErr = (argc<6) ? 2 : argc>(RTREE_MAX_DIMENSIONS*2+4) ? 3 : argc%2;
|
||||
if( aErrMsg[iErr] ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
|
||||
assert( RTREE_MAX_AUX_COLUMN<256 ); /* Aux columns counted by a u8 */
|
||||
if( argc>RTREE_MAX_AUX_COLUMN+3 ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[3]);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
@@ -3476,53 +3601,73 @@ static int rtreeInit(
|
||||
pRtree->base.pModule = &rtreeModule;
|
||||
pRtree->zDb = (char *)&pRtree[1];
|
||||
pRtree->zName = &pRtree->zDb[nDb+1];
|
||||
pRtree->nDim = (u8)((argc-4)/2);
|
||||
pRtree->nDim2 = pRtree->nDim*2;
|
||||
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
|
||||
pRtree->eCoordType = (u8)eCoordType;
|
||||
memcpy(pRtree->zDb, argv[1], nDb);
|
||||
memcpy(pRtree->zName, argv[2], nName);
|
||||
|
||||
/* Figure out the node size to use. */
|
||||
rc = getNodeSize(db, pRtree, isCreate, pzErr);
|
||||
|
||||
/* Create/Connect to the underlying relational database schema. If
|
||||
** that is successful, call sqlite3_declare_vtab() to configure
|
||||
** the r-tree table schema.
|
||||
*/
|
||||
if( rc==SQLITE_OK ){
|
||||
if( (rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
pSql = sqlite3_str_new(db);
|
||||
sqlite3_str_appendf(pSql, "CREATE TABLE x(%s", argv[3]);
|
||||
for(ii=4; ii<argc; ii++){
|
||||
if( argv[ii][0]=='+' ){
|
||||
pRtree->nAux++;
|
||||
sqlite3_str_appendf(pSql, ",%s", argv[ii]+1);
|
||||
}else if( pRtree->nAux>0 ){
|
||||
break;
|
||||
}else{
|
||||
char *zSql = sqlite3_mprintf("CREATE TABLE x(%s", argv[3]);
|
||||
char *zTmp;
|
||||
int ii;
|
||||
for(ii=4; zSql && ii<argc; ii++){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s, %s", zTmp, argv[ii]);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( zSql ){
|
||||
zTmp = zSql;
|
||||
zSql = sqlite3_mprintf("%s);", zTmp);
|
||||
sqlite3_free(zTmp);
|
||||
}
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
pRtree->nDim2++;
|
||||
sqlite3_str_appendf(pSql, ",%s", argv[ii]);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
*ppVtab = (sqlite3_vtab *)pRtree;
|
||||
}else{
|
||||
assert( *ppVtab==0 );
|
||||
assert( pRtree->nBusy==1 );
|
||||
rtreeRelease(pRtree);
|
||||
sqlite3_str_appendf(pSql, ");");
|
||||
zSql = sqlite3_str_finish(pSql);
|
||||
if( !zSql ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else if( ii<argc ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[4]);
|
||||
rc = SQLITE_ERROR;
|
||||
}else if( SQLITE_OK!=(rc = sqlite3_declare_vtab(db, zSql)) ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
if( rc ) goto rtreeInit_fail;
|
||||
pRtree->nDim = pRtree->nDim2/2;
|
||||
if( pRtree->nDim<1 ){
|
||||
iErr = 2;
|
||||
}else if( pRtree->nDim2>RTREE_MAX_DIMENSIONS*2 ){
|
||||
iErr = 3;
|
||||
}else if( pRtree->nDim2 % 2 ){
|
||||
iErr = 1;
|
||||
}else{
|
||||
iErr = 0;
|
||||
}
|
||||
if( iErr ){
|
||||
*pzErr = sqlite3_mprintf("%s", aErrMsg[iErr]);
|
||||
goto rtreeInit_fail;
|
||||
}
|
||||
pRtree->nBytesPerCell = 8 + pRtree->nDim2*4;
|
||||
|
||||
/* Figure out the node size to use. */
|
||||
rc = getNodeSize(db, pRtree, isCreate, pzErr);
|
||||
if( rc ) goto rtreeInit_fail;
|
||||
rc = rtreeSqlInit(pRtree, db, argv[1], argv[2], isCreate);
|
||||
if( rc ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
goto rtreeInit_fail;
|
||||
}
|
||||
|
||||
*ppVtab = (sqlite3_vtab *)pRtree;
|
||||
return SQLITE_OK;
|
||||
|
||||
rtreeInit_fail:
|
||||
if( rc==SQLITE_OK ) rc = SQLITE_ERROR;
|
||||
assert( *ppVtab==0 );
|
||||
assert( pRtree->nBusy==1 );
|
||||
rtreeRelease(pRtree);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3751,7 +3896,7 @@ static u8 *rtreeCheckGetNode(RtreeCheck *pCheck, i64 iNode, int *pnNode){
|
||||
** two tables are:
|
||||
**
|
||||
** CREATE TABLE %_parent(nodeno INTEGER PRIMARY KEY, parentnode INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER)
|
||||
** CREATE TABLE %_rowid(rowid INTEGER PRIMARY KEY, nodeno INTEGER, ...)
|
||||
**
|
||||
** In both cases, this function checks that there exists an entry with
|
||||
** IPK value iKey and the second column set to iVal.
|
||||
@@ -3766,8 +3911,8 @@ static void rtreeCheckMapping(
|
||||
int rc;
|
||||
sqlite3_stmt *pStmt;
|
||||
const char *azSql[2] = {
|
||||
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?",
|
||||
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?"
|
||||
"SELECT parentnode FROM %Q.'%q_parent' WHERE nodeno=?1",
|
||||
"SELECT nodeno FROM %Q.'%q_rowid' WHERE rowid=?1"
|
||||
};
|
||||
|
||||
assert( bLeaf==0 || bLeaf==1 );
|
||||
@@ -3951,6 +4096,7 @@ static int rtreeCheckTable(
|
||||
RtreeCheck check; /* Common context for various routines */
|
||||
sqlite3_stmt *pStmt = 0; /* Used to find column count of rtree table */
|
||||
int bEnd = 0; /* True if transaction should be closed */
|
||||
int nAux = 0; /* Number of extra columns. */
|
||||
|
||||
/* Initialize the context object */
|
||||
memset(&check, 0, sizeof(check));
|
||||
@@ -3966,11 +4112,21 @@ static int rtreeCheckTable(
|
||||
bEnd = 1;
|
||||
}
|
||||
|
||||
/* Find the number of auxiliary columns */
|
||||
if( check.rc==SQLITE_OK ){
|
||||
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.'%q_rowid'", zDb, zTab);
|
||||
if( pStmt ){
|
||||
nAux = sqlite3_column_count(pStmt) - 2;
|
||||
sqlite3_finalize(pStmt);
|
||||
}
|
||||
check.rc = SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Find number of dimensions in the rtree table. */
|
||||
pStmt = rtreeCheckPrepare(&check, "SELECT * FROM %Q.%Q", zDb, zTab);
|
||||
if( pStmt ){
|
||||
int rc;
|
||||
check.nDim = (sqlite3_column_count(pStmt) - 1) / 2;
|
||||
check.nDim = (sqlite3_column_count(pStmt) - 1 - nAux) / 2;
|
||||
if( check.nDim<1 ){
|
||||
rtreeCheckAppendMsg(&check, "Schema corrupt or not an rtree");
|
||||
}else if( SQLITE_ROW==sqlite3_step(pStmt) ){
|
||||
|
||||
+43
-5
@@ -476,11 +476,11 @@ foreach {tn sql_template testdata} {
|
||||
}
|
||||
|
||||
3 "UPDATE %CONF% t1 SET idx = 2 WHERE idx = 4" {
|
||||
ROLLBACK 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
|
||||
ABORT 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
IGNORE 1 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
FAIL 1 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
REPLACE 1 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
|
||||
ROLLBACK 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6}
|
||||
ABORT 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
IGNORE 0 0 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
FAIL 0 1 {1 1 2 3 4 2 2 3 4 5 3 3 4 5 6 4 4 5 6 7}
|
||||
REPLACE 0 0 {1 1 2 3 4 2 4 5 6 7 3 3 4 5 6}
|
||||
}
|
||||
|
||||
3 "UPDATE %CONF% t1 SET idx = ((idx+1)%5)+1 WHERE idx > 2" {
|
||||
@@ -609,5 +609,43 @@ do_execsql_test 15.2 {
|
||||
COMMIT;
|
||||
}
|
||||
|
||||
# Test cases for the new auxiliary columns feature
|
||||
#
|
||||
do_catchsql_test 16.100 {
|
||||
CREATE VIRTUAL TABLE t16 USING rtree(id,x0,x1,y0,+aux1,x1);
|
||||
} {1 {Auxiliary rtree columns must be last}}
|
||||
do_test 16.110 {
|
||||
set sql {
|
||||
CREATE VIRTUAL TABLE t16 USING rtree(
|
||||
id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
|
||||
}
|
||||
for {set i 12} {$i<=100} {incr i} {
|
||||
append sql ", +a$i"
|
||||
}
|
||||
append sql ");"
|
||||
execsql $sql
|
||||
} {}
|
||||
do_test 16.120 {
|
||||
set sql {
|
||||
CREATE VIRTUAL TABLE t16b USING rtree(
|
||||
id, x00, x01, x10, x11, x20, x21, x30, x31, x40, x41
|
||||
}
|
||||
for {set i 12} {$i<=101} {incr i} {
|
||||
append sql ", +a$i"
|
||||
}
|
||||
append sql ");"
|
||||
catchsql $sql
|
||||
} {1 {Too many columns for an rtree table}}
|
||||
|
||||
do_execsql_test 16.130 {
|
||||
DROP TABLE IF EXISTS rt1;
|
||||
CREATE VIRTUAL TABLE rt1 USING rtree(id, x1, x2, +aux);
|
||||
INSERT INTO rt1 VALUES(1, 1, 2, 'aux1');
|
||||
INSERT INTO rt1 VALUES(2, 2, 3, 'aux2');
|
||||
INSERT INTO rt1 VALUES(3, 3, 4, 'aux3');
|
||||
INSERT INTO rt1 VALUES(4, 4, 5, 'aux4');
|
||||
SELECT * FROM rt1 WHERE id IN (1, 2, 3, 4);
|
||||
} {1 1.0 2.0 aux1 2 2.0 3.0 aux2 3 3.0 4.0 aux3 4 4.0 5.0 aux4}
|
||||
|
||||
expand_all_sql db
|
||||
finish_test
|
||||
|
||||
@@ -81,7 +81,7 @@ do_faultsim_test rtree3-2 -faults oom* -prep {
|
||||
do_malloc_test rtree3-3.prep {
|
||||
faultsim_delete_and_reopen
|
||||
execsql {
|
||||
CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(ii, x1, x2, y1, y2, +a1, +a2);
|
||||
INSERT INTO rt VALUES(NULL, 3, 5, 7, 9);
|
||||
}
|
||||
faultsim_save_and_close
|
||||
|
||||
+18
-12
@@ -74,42 +74,48 @@ do_test rtree6-1.5 {
|
||||
do_eqp_test rtree6.2.1 {
|
||||
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
|
||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.2 {
|
||||
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
|
||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.3 {
|
||||
SELECT * FROM t1,t2 WHERE k=ii
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:}
|
||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.4.1 {
|
||||
SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
|
||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
|
||||
`--SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)
|
||||
}
|
||||
do_eqp_test rtree6.2.4.2 {
|
||||
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
|
||||
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1
|
||||
`--SEARCH TABLE t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?)
|
||||
}
|
||||
|
||||
do_eqp_test rtree6.2.5 {
|
||||
SELECT * FROM t1,t2 WHERE k=ii AND x1<v
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:}
|
||||
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
}
|
||||
|
||||
do_execsql_test rtree6-3.1 {
|
||||
|
||||
+36
-3
@@ -38,11 +38,20 @@ do_test rtree8-1.1.1 {
|
||||
} {}
|
||||
do_test rtree8-1.1.2 {
|
||||
set res [list]
|
||||
db eval { SELECT * FROM t1 } {
|
||||
lappend res $x1 $x2
|
||||
set rc [catch {
|
||||
db eval { SELECT * FROM t1 } {
|
||||
lappend res $x1 $x2
|
||||
if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
|
||||
}
|
||||
} msg];
|
||||
lappend rc $msg
|
||||
set rc
|
||||
} {1 {database table is locked}}
|
||||
do_test rtree8-1.1.2b {
|
||||
db eval { SELECT * FROM t1 ORDER BY +id } {
|
||||
if {$id==3} { db eval { DELETE FROM t1 WHERE id>3 } }
|
||||
}
|
||||
set res
|
||||
db eval {SELECT x1, x2 FROM t1}
|
||||
} {1 3 2 4 3 5}
|
||||
do_test rtree8-1.1.3 {
|
||||
execsql { SELECT * FROM t1 }
|
||||
@@ -170,5 +179,29 @@ do_test rtree8-5.4 {
|
||||
} {}
|
||||
do_rtree_integrity_test rtree8-5.5 t2
|
||||
|
||||
# 2018-05-24
|
||||
# The following script caused an assertion fault and/or segfault
|
||||
# prior to the fix that prevents simultaneous reads and writes on
|
||||
# the same rtree virtual table.
|
||||
#
|
||||
do_test rtree8-6.1 {
|
||||
db close
|
||||
sqlite3 db :memory:
|
||||
db eval {
|
||||
PRAGMA page_size=512;
|
||||
CREATE VIRTUAL TABLE t1 USING rtree(id,x1,x2,y1,y2);
|
||||
WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<49)
|
||||
INSERT INTO t1 SELECT x, x, x+1, x, x+1 FROM c;
|
||||
}
|
||||
set rc [catch {
|
||||
db eval {SELECT id FROM t1} x {
|
||||
db eval {DELETE FROM t1 WHERE id=$x(id)}
|
||||
}
|
||||
} msg]
|
||||
lappend rc $msg
|
||||
} {1 {database table is locked}}
|
||||
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+73
-49
@@ -29,31 +29,35 @@ do_eqp_test 1.1 {
|
||||
SELECT * FROM r_tree, t
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t}
|
||||
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t, r_tree
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t}
|
||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM t, r_tree
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t}
|
||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM t, r_tree
|
||||
} {
|
||||
0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:}
|
||||
0 1 0 {SCAN TABLE t}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN TABLE t
|
||||
}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
@@ -82,31 +86,35 @@ do_eqp_test 2.1 {
|
||||
SELECT * FROM r_tree, t
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
0 0 1 {SCAN TABLE t}
|
||||
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 2.2 {
|
||||
SELECT * FROM t, r_tree
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t}
|
||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 2.3 {
|
||||
SELECT * FROM t, r_tree
|
||||
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t}
|
||||
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t
|
||||
`--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0
|
||||
}
|
||||
|
||||
do_eqp_test 2.5 {
|
||||
SELECT * FROM t, r_tree
|
||||
} {
|
||||
0 0 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:}
|
||||
0 1 0 {SCAN TABLE t}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN TABLE t
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -119,20 +127,25 @@ do_execsql_test 3.1 {
|
||||
}
|
||||
|
||||
do_eqp_test 3.2.1 { SELECT * FROM t1 CROSS JOIN t2 } {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE t2}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE t2
|
||||
}
|
||||
do_eqp_test 3.2.2 { SELECT * FROM t2 CROSS JOIN t1 } {
|
||||
0 0 0 {SCAN TABLE t2} 0 1 1 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
do_eqp_test 3.3.1 { SELECT * FROM t1 CROSS JOIN t3 } {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
|
||||
}
|
||||
do_eqp_test 3.3.2 { SELECT * FROM t3 CROSS JOIN t1 } {
|
||||
0 0 0 {SCAN TABLE t3 VIRTUAL TABLE INDEX 2:}
|
||||
0 1 1 {SCAN TABLE t1}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t3 VIRTUAL TABLE INDEX 2:
|
||||
`--SCAN TABLE t1
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -165,7 +178,7 @@ do_execsql_test 4.3 {
|
||||
reset_db
|
||||
do_execsql_test 5.1 {
|
||||
CREATE TABLE t1(x PRIMARY KEY, y);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2);
|
||||
CREATE VIRTUAL TABLE rt USING rtree(id, x1, x2, +d1);
|
||||
|
||||
INSERT INTO t1(x) VALUES(1);
|
||||
INSERT INTO t1(x) SELECT x+1 FROM t1; -- 2
|
||||
@@ -179,7 +192,7 @@ do_execsql_test 5.1 {
|
||||
INSERT INTO t1(x) SELECT x+256 FROM t1; -- 512
|
||||
INSERT INTO t1(x) SELECT x+512 FROM t1; --1024
|
||||
|
||||
INSERT INTO rt SELECT x, x, x+1 FROM t1 WHERE x<=5;
|
||||
INSERT INTO rt SELECT x, x, x+1, printf('x%04xy',x) FROM t1 WHERE x<=5;
|
||||
}
|
||||
do_rtree_integrity_test 5.1.1 rt
|
||||
|
||||
@@ -189,8 +202,9 @@ do_rtree_integrity_test 5.1.1 rt
|
||||
do_eqp_test 5.2 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
|
||||
# Now create enough ANALYZE data to tell SQLite that virtual table "rt"
|
||||
@@ -205,8 +219,9 @@ sqlite3 db test.db
|
||||
do_eqp_test 5.4 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:}
|
||||
0 1 0 {SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:
|
||||
`--SEARCH TABLE t1 USING INDEX sqlite_autoindex_t1_1 (x=?)
|
||||
}
|
||||
|
||||
# Delete the ANALYZE data. "t1" should be the outer loop again.
|
||||
@@ -217,8 +232,9 @@ sqlite3 db test.db
|
||||
do_eqp_test 5.6 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
|
||||
# This time create and attach a database that contains ANALYZE data for
|
||||
@@ -241,8 +257,9 @@ do_test 5.7 {
|
||||
do_eqp_test 5.8 {
|
||||
SELECT * FROM t1, rt WHERE x==id;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 1:}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 1:
|
||||
}
|
||||
|
||||
#--------------------------------------------------------------------
|
||||
@@ -299,9 +316,9 @@ do_execsql_test 7.0 {
|
||||
|
||||
}
|
||||
|
||||
proc do_eqp_execsql_test {tn sql res} {
|
||||
set query "EXPLAIN QUERY PLAN $sql ; $sql "
|
||||
uplevel [list do_execsql_test $tn $query $res]
|
||||
proc do_eqp_execsql_test {tn sql res1 res2} {
|
||||
do_eqp_test $tn.1 $sql $res1
|
||||
do_execsql_test $tn.2 $sql $res2
|
||||
}
|
||||
|
||||
do_eqp_execsql_test 7.1 {
|
||||
@@ -309,9 +326,11 @@ do_eqp_execsql_test 7.1 {
|
||||
ON (y1 BETWEEN ymin AND ymax)
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE xdir}
|
||||
0 1 2 {SCAN TABLE ydir}
|
||||
0 2 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE ydir
|
||||
`--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B2D3B0D1
|
||||
} {
|
||||
2 4
|
||||
}
|
||||
|
||||
@@ -320,10 +339,11 @@ do_eqp_execsql_test 7.2 {
|
||||
ON (y1 BETWEEN ymin AND ymax)
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE xdir}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
|
||||
0 2 2 {SCAN TABLE ydir}
|
||||
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN TABLE ydir
|
||||
} {
|
||||
5 1 2 7 12 14 {}
|
||||
5 2 2 7 8 12 10
|
||||
5 4 5 5 10 10 10
|
||||
@@ -334,9 +354,11 @@ do_eqp_execsql_test 7.3 {
|
||||
ON (y1 BETWEEN ymin AND ymax)
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE xdir}
|
||||
0 1 1 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
|
||||
0 2 2 {SCAN TABLE ydir}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN TABLE ydir
|
||||
} {
|
||||
2 4
|
||||
}
|
||||
|
||||
@@ -345,9 +367,11 @@ do_eqp_execsql_test 7.4 {
|
||||
ON (y1 BETWEEN ymin AND ymax)
|
||||
WHERE (x1 BETWEEN xmin AND xmax);
|
||||
} {
|
||||
0 0 1 {SCAN TABLE xdir}
|
||||
0 1 0 {SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1}
|
||||
0 2 2 {SCAN TABLE ydir}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE xdir
|
||||
|--SCAN TABLE rt VIRTUAL TABLE INDEX 2:B0D1
|
||||
`--SCAN TABLE ydir
|
||||
} {
|
||||
2 4
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
# 2018-05-16
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file contains tests for the r-tree module, specifically the
|
||||
# auxiliary column mechanism.
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] rtree_util.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !rtree { finish_test ; return }
|
||||
|
||||
do_execsql_test rtreeH-100 {
|
||||
CREATE VIRTUAL TABLE t1 USING rtree(id,x0,x1,y0,y1,+label,+other);
|
||||
INSERT INTO t1(x0,x1,y0,y1,label) VALUES
|
||||
(0,10,0,10,'lower-left corner'),
|
||||
(0,10,90,100,'upper-left corner'),
|
||||
(90,100,0,10,'lower-right corner'),
|
||||
(90,100,90,100,'upper-right corner'),
|
||||
(40,60,40,60,'center'),
|
||||
(0,5,0,100,'left edge'),
|
||||
(95,100,0,100,'right edge'),
|
||||
(0,100,0,5,'bottom edge'),
|
||||
(0,100,95,100,'top edge'),
|
||||
(0,100,0,100,'the whole thing'),
|
||||
(0,50,0,100,'left half'),
|
||||
(51,100,0,100,'right half'),
|
||||
(0,100,0,50,'bottom half'),
|
||||
(0,100,51,100,'top half');
|
||||
} {}
|
||||
do_execsql_test rtreeH-101 {
|
||||
SELECT * FROM t1_rowid ORDER BY rowid
|
||||
} {1 1 {lower-left corner} {} 2 1 {upper-left corner} {} 3 1 {lower-right corner} {} 4 1 {upper-right corner} {} 5 1 center {} 6 1 {left edge} {} 7 1 {right edge} {} 8 1 {bottom edge} {} 9 1 {top edge} {} 10 1 {the whole thing} {} 11 1 {left half} {} 12 1 {right half} {} 13 1 {bottom half} {} 14 1 {top half} {}}
|
||||
|
||||
do_execsql_test rtreeH-102 {
|
||||
SELECT * FROM t1 WHERE rowid=5;
|
||||
} {5 40.0 60.0 40.0 60.0 center {}}
|
||||
do_execsql_test rtreeH-103 {
|
||||
SELECT * FROM t1 WHERE label='center';
|
||||
} {5 40.0 60.0 40.0 60.0 center {}}
|
||||
|
||||
do_rtree_integrity_test rtreeH-110 t1
|
||||
|
||||
do_execsql_test rtreeH-120 {
|
||||
SELECT label FROM t1 WHERE x1<=50 ORDER BY id
|
||||
} {{lower-left corner} {upper-left corner} {left edge} {left half}}
|
||||
do_execsql_test rtreeH-121 {
|
||||
SELECT label FROM t1 WHERE x1<=50 AND label NOT LIKE '%corner%' ORDER BY id
|
||||
} {{left edge} {left half}}
|
||||
|
||||
do_execsql_test rtreeH-200 {
|
||||
WITH RECURSIVE
|
||||
c1(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c1 WHERE x<99),
|
||||
c2(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM c2 WHERE y<99)
|
||||
INSERT INTO t1(id, x0,x1,y0,y1,label)
|
||||
SELECT 1000+x+y*100, x, x+1, y, y+1, printf('box-%d,%d',x,y) FROM c1, c2;
|
||||
} {}
|
||||
|
||||
do_execsql_test rtreeH-210 {
|
||||
SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
|
||||
ORDER BY id;
|
||||
} {box-48,48 box-49,48 box-48,49 box-49,49}
|
||||
|
||||
do_execsql_test rtreeH-300 {
|
||||
UPDATE t1 SET label='x'||label
|
||||
WHERE x0>=49 AND x1<=50 AND y0>=49 AND y1<=50;
|
||||
SELECT label FROM t1 WHERE x0>=48 AND x1<=50 AND y0>=48 AND y1<=50
|
||||
ORDER BY id;
|
||||
} {box-48,48 box-49,48 box-48,49 xbox-49,49}
|
||||
|
||||
|
||||
finish_test
|
||||
@@ -501,7 +501,8 @@ FUZZDATA = \
|
||||
$(TOP)/test/fuzzdata2.db \
|
||||
$(TOP)/test/fuzzdata3.db \
|
||||
$(TOP)/test/fuzzdata4.db \
|
||||
$(TOP)/test/fuzzdata5.db
|
||||
$(TOP)/test/fuzzdata5.db \
|
||||
$(TOP)/test/fuzzdata6.db
|
||||
|
||||
# Standard options to testfixture
|
||||
#
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
C Improved\sVDBE\scomment\son\sUPSERT\scode.
|
||||
D 2018-04-20T16:49:51.077
|
||||
C Work\saround\sa\ssanitizer\swarning\sabout\sa\spointer\sbeing\sonly\s4-byte\saligned\ninstead\sof\s8-byte\saligned.
|
||||
D 2018-06-02T16:32:04.483
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 5ce9343cba9c189046f1afe6d2bcc1f68079439febc05267b98aec6ecc752439
|
||||
F Makefile.in bfc40f350586923e0419d2ea4b559c37ec10ee4b6e210e08c14401f8e340f0da
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 59179295f6a9b433e3f59a6dc2fcf6db6fcac35d92015294beb5d27f2924ebb9
|
||||
F Makefile.msc 681fb88cccf1fd58c0b9648f6a09b75332206ef72ca76012ad11699c320cec5f
|
||||
F README.md 7764d56778d567913ef11c82da9ab94aefa0826f7c243351e4e2d7adaef6f373
|
||||
F VERSION b7c9d1d11cb70ef8e90cfcf3c944aa58a9f801cc2ad487eebb0a110c16dfc2df
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -12,11 +12,12 @@ F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
|
||||
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 2c274948734e03c51790ff51468f91db8d570bcca864284d9c6d6e777264cd7e
|
||||
F autoconf/Makefile.am 465fb475ee5a4b8a63d26c889cb36a4edbff0325b6859eb29a13cdf5c91b005c
|
||||
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
|
||||
F autoconf/Makefile.msc 6a46d0659d6e4a25346102bcba40a7fb4b0b8b2dc4faabdf0187488c6dd580d6
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac 18fca06f884213be062dd5e07c5297079cc45893d9cd3f522ce426e715033e3d
|
||||
F autoconf/configure.ac 5f6cf281ae675685335ce7f43f8c2d59d3ac8ba4174a57b8e83097c5e10dcf4e
|
||||
F autoconf/tea/Makefile.in b438a7020446c8a8156e8d97c8914a04833da6fd
|
||||
F autoconf/tea/README 3e9a3c060f29a44344ab50aec506f4db903fb873
|
||||
F autoconf/tea/aclocal.m4 52c47aac44ce0ddb1f918b6993e8beb8eee88f43
|
||||
@@ -35,7 +36,7 @@ F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 80e2dcad8ab88aacc58b55eb0e395f79184b45fcfaa3f36fc20d2e71cfa0a7e4 x
|
||||
F configure.ac d4529ebb26ae046269334f1dac65f2b1d6927c2efe22b2ec24dce24dfe4f83dd
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html 278113807f49d12d04179a93fab92b5b917a08771152ca7949d34e928efa3941
|
||||
F doc/lemon.html ac63db056bce24b7368e29319cd1a7eb5f1798cc85922d96a80b6c3a4ff9f51b
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F ext/README.md fd5f78013b0a2bc6f0067afb19e6ad040e89a10179b4f6f03eee58fac5f169bd
|
||||
@@ -44,8 +45,8 @@ F ext/async/sqlite3async.c 0f3070cc3f5ede78f2b9361fb3b629ce200d7d74
|
||||
F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
||||
F ext/expert/README.md b321c2762bb93c18ea102d5a5f7753a4b8bac646cb392b3b437f633caf2020c3
|
||||
F ext/expert/expert.c d548d603a4cc9e61f446cc179c120c6713511c413f82a4a32b1e1e69d3f086a4
|
||||
F ext/expert/expert1.test fd21496d8e52c817a7741f467f42b0502c0ac7e07dcdd1d6e15a3e8154ed4e41
|
||||
F ext/expert/sqlite3expert.c 1dfa561e64dc0f89d56b96e6afda87468c34b43604c2df50c47e3f4362778fb2
|
||||
F ext/expert/expert1.test baa05800dc1c569faa7ce6232cead0fcedc07fea038b3a2489eaaf710831d546
|
||||
F ext/expert/sqlite3expert.c 89b7b59be610b929958db02416539a46ac088fd84f81623c4190aff62e92c3c4
|
||||
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
|
||||
F ext/expert/test_expert.c d56c194b769bdc90cf829a14c9ecbc1edca9c850b837a4d0b13be14095c32a72
|
||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||
@@ -78,11 +79,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||
F ext/fts3/fts3.c f1c58503bc81c3dab1a70b25e146878ae40fccc716fd7c9b817995b661bc896f
|
||||
F ext/fts3/fts3.c b577921c7e56ea27893da06691f15721801375ebd411a0e24ec5f6fec3c572c3
|
||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
|
||||
F ext/fts3/fts3Int.h 3378157f383540857a466420b8279626204434c3eb0dc948ad9bcd3991fc41f5
|
||||
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||
F ext/fts3/fts3_expr.c dfd571a24412779ac01f25c01d888c6ef7b2d0ef
|
||||
F ext/fts3/fts3_expr.c 3b1dbceddd8622599f3cc2626897667fe40487aaa1676707d6c37ec5a8422fc1
|
||||
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
|
||||
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
|
||||
F ext/fts3/fts3_icu.c deb46f7020d87ea7a14a433fb7a7f4bef42a9652
|
||||
@@ -187,7 +188,7 @@ F ext/fts5/test/fts5near.test 211477940142d733ac04fad97cb24095513ab2507073a99c27
|
||||
F ext/fts5/test/fts5onepass.test f9b7d9b2c334900c6542a869760290e2ab5382af8fbd618834bf1fcc3e7b84da
|
||||
F ext/fts5/test/fts5optimize.test 36a752d24c818792032e4ff502936fc9cc5ef938721696396fdc79214b2717f1
|
||||
F ext/fts5/test/fts5phrase.test 13e5d8e9083077b3d9c74315b3c92ec723cc6eb37c8155e0bfe1bba00559f07b
|
||||
F ext/fts5/test/fts5plan.test e30e8378441114ef6977a3dc24ecd203caa670d782124dfc9a6e9af09f7abc4d
|
||||
F ext/fts5/test/fts5plan.test 00dc4c974938b509db7cb3680407f068ee6e9cc824f492f68cb741a7b679fe41
|
||||
F ext/fts5/test/fts5porter.test 8d08010c28527db66bc3feebd2b8767504aaeb9b101a986342fa7833d49d0d15
|
||||
F ext/fts5/test/fts5porter2.test 0d251a673f02fa13ca7f011654873b3add20745f7402f108600a23e52d8c7457
|
||||
F ext/fts5/test/fts5prefix.test a0fa67b06650f2deaa7bf27745899d94e0fb547ad9ecbd08bfad98c04912c056
|
||||
@@ -204,7 +205,7 @@ F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947e
|
||||
F ext/fts5/test/fts5tok1.test ce6551e41ff56f30b69963577324624733bed0d1753589f06120d664d9cd45c9
|
||||
F ext/fts5/test/fts5tok2.test dcacb32d4a2a3f0dd3215d4a3987f78ae4be21a2
|
||||
F ext/fts5/test/fts5tokenizer.test 6aeb5e8061ffc0ff9a5299f27beaee3b2b4b8b336d4f107262bca338bea8f8e9
|
||||
F ext/fts5/test/fts5unicode.test 1e5570df758f7e0b27ff0e087ee96f559d5cc9ade80afa9421537a8a20a7cfbf
|
||||
F ext/fts5/test/fts5unicode.test 17056f4efe6b0a5d4f41fdf7a7dc9af2873004562eaa899d40633b93dc95f5a9
|
||||
F ext/fts5/test/fts5unicode2.test 9b3df486de05fb4bde4aa7ee8de2e6dae1df6eb90e3f2e242c9383b95d314e3e
|
||||
F ext/fts5/test/fts5unicode3.test c3caecbe8264629ffe653b43ca5790b9793eba4422f92203e5247558e5a534e7
|
||||
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
|
||||
@@ -271,16 +272,16 @@ F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a2
|
||||
F ext/misc/appendvfs.c 3777f22ec1057dc4e5fd89f2fbddcc7a29fbeef1ad038c736c54411bb1967af7
|
||||
F ext/misc/btreeinfo.c 78c8c57d325185ccc04b7679e5b020e34a4d9c87453e6b7ac943d0a26cee3256
|
||||
F ext/misc/carray.c ed96c218ea940b85c9a274c4d9c59fe9491c299147a38a8bba537687bd6c6005
|
||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||
F ext/misc/completion.c 0d0bd16378415b982e7119baddef52a0d2cc25860c238a9d2832b0cc6a84a16d
|
||||
F ext/misc/closure.c fe928228e8dfb2f00227311c203ccba9c2e5561f4f6de6da87e5b4a30cd8af15
|
||||
F ext/misc/completion.c e75b8886a2531f9a7ec02dab5f179bb37e6bd46b5da7665a6cbf2dfbe2daa483
|
||||
F ext/misc/compress.c dd4f8a6d0baccff3c694757db5b430f3bbd821d8686d1fc24df55cf9f035b189
|
||||
F ext/misc/csv.c 1a009b93650732e22334edc92459c4630b9fa703397cbb3c8ca279921a36ca11
|
||||
F ext/misc/dbdump.c 22018e00eb50e9ebf9067c92d4e7162dc5006a3efc4e0c19bc3829825a1043b0
|
||||
F ext/misc/csv.c 65297bcce8d5acd5aadef42acbe739aef5a2ef5e74c7b73361ca19f3e21de657
|
||||
F ext/misc/dbdump.c 69ef1be5b210538f77dfcc6fcb55b4b5f5e98b1e0bcfd67d818711e10761db4d
|
||||
F ext/misc/eval.c 6ea9b22a5fa0dd973b67ca4e53555be177bc0b7b263aadf1024429457c82c0e3
|
||||
F ext/misc/fileio.c 48c7751c78fc4cdd29d8c862fd2f3f98bbfefa2a3cf1ca1496df4bf02eb8cded
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c dbe086615b9546c156bf32b9378fc09383b58bd17513b866cfd24c1e15281984
|
||||
F ext/misc/json1.c 02f5f0d9c131df79f4ee168d2b426f0f0d273b7771fc0bb5293c4e7692d9a2ee
|
||||
F ext/misc/memvfs.c ab36f49e02ebcdf85a1e08dc4d8599ea8f343e073ac9e0bca18a98b7e1ec9567
|
||||
F ext/misc/mmapwarm.c 70b618f2d0bde43fae288ad0b7498a629f2b6f61b50a27e06fae3cd23c83af29
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
@@ -297,7 +298,7 @@ F ext/misc/showauth.c 732578f0fe4ce42d577e1c86dc89dd14a006ab52
|
||||
F ext/misc/spellfix.c 54d650f44f3a69a851814791bd4d304575cdbbf78d96d4f0801b44a8f31a58c5
|
||||
F ext/misc/sqlar.c 57d5bc45cd5492208e451f697404be88f8612527d64c9d42f96b325b64983d74
|
||||
F ext/misc/stmt.c 6f16443abb3551e3f5813bb13ba19a30e7032830015b0f92fe0c0453045c0a11
|
||||
F ext/misc/templatevtab.c 52b9363de0ae4a695728a52769a2e2dab8a0a2db77ca753ad9e1a0d0f32d1f89
|
||||
F ext/misc/templatevtab.c 8251b31011dd00fc38e739c78c234c930be42b3b274bbe0493b79cd40db02a9e
|
||||
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
|
||||
F ext/misc/unionvtab.c 0b3173f69b8899da640a13a345dc5ef1400199405f738abe6145b2454195b8ff
|
||||
F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
|
||||
@@ -307,8 +308,8 @@ F ext/misc/vtshim.c 1976e6dd68dd0d64508c91a6dfab8e75f8aaf6cd
|
||||
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
|
||||
F ext/misc/zipfile.c c4de8f0ad446ce4a49aae11ff7b771cd7af60d7136c0bcfb53da1475b9075e79
|
||||
F ext/misc/zorder.c b0ff58fa643afa1d846786d51ea8d5c4b6b35aa0254ab5a82617db92f3adda64
|
||||
F ext/rbu/rbu.c ea7d1b7eb44c123a2a619332e19fe5313500705c4a58aaa1887905c0d83ffc2e
|
||||
F ext/rbu/rbu1.test 43836fac8c7179a358eaf38a8a1ef3d6e6285842
|
||||
F ext/rbu/rbu.c 4ae41f01d78dfae2204a63bcf39d5eb3548d039b094c29eec9a8d6683a66a5d3
|
||||
F ext/rbu/rbu1.test 41123c64e8c88bd14eb7d3f8562f37fa87aaeb154b1eade2881de21d3504be55
|
||||
F ext/rbu/rbu10.test 1846519a438697f45e9dcb246908af81b551c29e1078d0304fae83f1fed7e9ee
|
||||
F ext/rbu/rbu11.test 9bc68c2d3dbeb1720153626e3bd0466dcc017702
|
||||
F ext/rbu/rbu12.test bde22ed0004dd5d1888c72a84ae407e574aeae16
|
||||
@@ -323,7 +324,7 @@ F ext/rbu/rbu9.test 0806d1772c9f4981774ff028de6656e4183082af
|
||||
F ext/rbu/rbuA.test 4e58e46e60d4064248614c43303d71f1b18cc804dd834ce6a913b3861828b28d
|
||||
F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2
|
||||
F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831
|
||||
F ext/rbu/rbu_common.tcl ebb8d81f44dc20e360cff1f34eb2ad0def33128805c5b36afcc44ab338509589
|
||||
F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5
|
||||
F ext/rbu/rbucollate.test 86d6fc9b8f59a27b7b5a6e20b5e29816d338a0dbdea8c54bfcc549a0d437f3ea
|
||||
F ext/rbu/rbucrash.test 61470d977a06a0abc2ec35b05d82a1d7d87d10f4ffabad14c1c231edc942ad66
|
||||
F ext/rbu/rbucrash2.test b2ecbdd7bb72c88bd217c65bd00dafa07f7f2d4d
|
||||
@@ -338,10 +339,11 @@ F ext/rbu/rbumulti.test 2cf153ab3d5861ff26517dc6cbaec430787a59f1d50e8771fe7a7529
|
||||
F ext/rbu/rbuprogress.test 1849d4e0e50616edf5ce75ce7db86622e656b5cf
|
||||
F ext/rbu/rburesume.test 8acb77f4a422ff55acfcfc9cc15a5cb210b1de83
|
||||
F ext/rbu/rbusave.test 0f43b6686084f426ddd040b878426452fd2c2f48
|
||||
F ext/rbu/rbusplit.test 69271c790732b28bd465551d80b0a9a3f074e189896ee8490ce56d22078c124d
|
||||
F ext/rbu/rbutemplimit.test cd553a9288d515d0b5f87d277e76fd18c4aa740b761e7880fab11ce986ea18d1
|
||||
F ext/rbu/rbuvacuum.test ff357e9b556ca7ad4673da0ff7f244def919ff858e0f9f350d3e30fdd83a62a8
|
||||
F ext/rbu/rbuvacuum2.test 2074ab14fe66e1c7e7210c62562650dcd215bbaa
|
||||
F ext/rbu/sqlite3rbu.c f6e9ca388b5d4680fbf266a4d10a21aec11d6baf48f6d06fd53f6b205fad959f
|
||||
F ext/rbu/sqlite3rbu.c f438fea899d15d13ff3e3133242b9e378c37b5a3d76add8c342c68bdd65c6819
|
||||
F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
|
||||
F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
|
||||
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
|
||||
@@ -354,24 +356,25 @@ F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc782
|
||||
F ext/repair/test/checkindex01.test 6945d0ffc0c1dc993b2ce88036b26e0f5d6fcc65da70fc9df27c2647bb358b0f
|
||||
F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c bc61010e978b5b8ae6dbb90274a2fbb5db5ff5e2880b5c6e8abd48eea77264db
|
||||
F ext/rtree/rtree.c cb6d4bd43c118354fe5b5213843da058259467ecdbac0c6f71ead0fd89acf4ec
|
||||
F ext/rtree/rtree.h 4a690463901cb5e6127cf05eb8e642f127012fd5003830dbc974eca5802d9412
|
||||
F ext/rtree/rtree1.test 47e2095bebea6813754fd7afa6a20e2b7b4ebcd5cb7dbcb6932b6c9f86bbf972
|
||||
F ext/rtree/rtree1.test 309afc04d4287542b2cd74f933296832cc681c7b014d9405cb329b62053a5349
|
||||
F ext/rtree/rtree2.test 5f25b01acd03470067a2d52783b2eb0a50bf836803d4342d20ca39e541220fe2
|
||||
F ext/rtree/rtree3.test 2cafe8265d1ff28f206fce88d114f208349df482
|
||||
F ext/rtree/rtree3.test 4ee5d7df86040efe3d8d84f141f2962a7745452200a7cba1db06f86d97050499
|
||||
F ext/rtree/rtree4.test 304de65d484540111b896827e4261815e5dca4ce28eeecd58be648cd73452c4b
|
||||
F ext/rtree/rtree5.test 49c9041d713d54560b315c2c7ef7207ee287eba1b20f8266968a06f2e55d3142
|
||||
F ext/rtree/rtree6.test 916a641d2beac01b9880871ff07612d56c1e466190a27c82ab36ffd58be03b9f
|
||||
F ext/rtree/rtree6.test 593e0d36510d5ac1d1fb39b018274ff17604fe8fdca8cf1f8e16559cea1477f4
|
||||
F ext/rtree/rtree7.test c8fb2e555b128dd0f0bdb520c61380014f497f8a23c40f2e820acc9f9e4fdce5
|
||||
F ext/rtree/rtree8.test 649f5a37ec656028a4a32674b9b1183104285a7625a09d2a8f52a1cef72c93f2
|
||||
F ext/rtree/rtree8.test 924926d7c64ac59fcca0809de472d9dd73c612f54daae1cf992bdd7dac90305b
|
||||
F ext/rtree/rtree9.test c646f12c8c1c68ef015c6c043d86a0c42488e2e68ed1bb1b0771a7ca246cbabf
|
||||
F ext/rtree/rtreeA.test 20623ca337ca3bd7e008cc9fb49e44dbe97f1a80b238e10a12bb4afcd0da3776
|
||||
F ext/rtree/rtreeB.test 4cec297f8e5c588654bbf3c6ed0903f10612be8a2878055dd25faf8c71758bc9
|
||||
F ext/rtree/rtreeC.test d9d06dda1aee68b4dc227dfcc899f335f8b621e9d1920ee3d4e5dab8ccd71db7
|
||||
F ext/rtree/rtreeC.test 128928549d22b65c381ab1366760d08703cd75e34f6a7a506ece38f9330b7282
|
||||
F ext/rtree/rtreeD.test fe46aa7f012e137bd58294409b16c0d43976c3bb92c8f710481e577c4a1100dc
|
||||
F ext/rtree/rtreeE.test e65d3fc625da1800b412fc8785817327d43ccfec5f5973912d8c9e471928caa9
|
||||
F ext/rtree/rtreeF.test 81ffa7ef51c4e4618d497a57328c265bf576990c7070633b623b23cd450ed331
|
||||
F ext/rtree/rtreeG.test 1b9ca6e3effb48f4161edaa463ddeaa8fca4b2526d084f9cbf5dbe4e0184939c
|
||||
F ext/rtree/rtreeH.test aa08cc4fa8005b4c67446c7110205055b4d6da90e760e6f44b82dfa4cdf8d87a
|
||||
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
|
||||
F ext/rtree/rtree_util.tcl db734b4c5e75fed6acc56d9701f2235345acfdec750b5fc7b587936f5f6bceed
|
||||
F ext/rtree/rtreecheck.test 4d29103d1e16fcbf90135d1c637b833688492b063b2971dfb5dc6ba76555cfee
|
||||
@@ -414,7 +417,7 @@ F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 068618fe288bf9d93091b808be73e26a93fb2db8435328cc5760f9dd35ba168b
|
||||
F main.mk 3f50dfe5cb4257c1aca96e417636ed51bc2561e71d31a21e9ccdf66feb912f43
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -428,35 +431,35 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c cf7a8af45cb0ace672f47a1b29ab24092a9e8cd8d945a9974e3b5d925f548594
|
||||
F src/analyze.c 71fbbeb7b25417592f54d869fe90c28b48e4cecb9926ef9b06d90fb0aec48941
|
||||
F src/attach.c bbdf97bb366d94d2bafff8ef611b3bee7b5f54d695531790d896a7a17e126317
|
||||
F src/auth.c 6277d63837357549fe14e723490d6dc1a38768d71c795c5eb5c0f8a99f918f73
|
||||
F src/attach.c 4a3138bd771d5426ae4344d8d5e900440af29fabc5ec2f39f69a45010dfbccd7
|
||||
F src/auth.c a38f3c63c974787ecf75e3213f8cac6568b9a7af7591fb0372ec0517dd16dca8
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
|
||||
F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
|
||||
F src/btree.c 9eb9531c65346bbfccf5325384b7db1849daf4db6601dcfe21ba5c5b20623b64
|
||||
F src/btree.h 0866c0a08255142ea0e754aabd211c843cab32045c978a592a43152405ed0c84
|
||||
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
|
||||
F src/btree.c 44405d03a05496e13b40b3a208bcf941c42c815da90d6ff4b04267a6985e5eb7
|
||||
F src/btree.h 448f15b98ea85dcf7e4eb76f731cadb89636c676ad25dfaac6de77cd66556598
|
||||
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
|
||||
F src/build.c 91d548027a54044851299e719d60d6a2b6eaf3e3274678098cb73a6ab8c0fa19
|
||||
F src/callback.c fe677cb5f5abb02f7a772a62a98c2f516426081df68856e8f2d5f950929b966a
|
||||
F src/build.c 5fc41458505331bfb0c175f40b9a13cb335f826bed3ae311aaae000c132d7b16
|
||||
F src/callback.c 36caff1e7eb7deb58572d59c41cee8f064a11d00297616995c5050ea0cfc1288
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c 849d4cebe008cfc6e4799b034a172b4eaf8856b100739632a852732ba66eee48
|
||||
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
|
||||
F src/dbpage.c 8db4c97f630e7d83f884ea75caf1ffd0988c160e9d530194d93721c80821e0f6
|
||||
F src/dbstat.c edabb82611143727511a45ca0859b8cd037851ebe756ae3db289859dd18b6f91
|
||||
F src/delete.c 333aca5587c690bbc460c9b2e6842e7080b1f7abac0e6ca4d3f82c2aea328def
|
||||
F src/expr.c 53df437b3a4a404f039645919b2d6a56a2f59b9883e858940cd2a8858a25cd3d
|
||||
F src/delete.c 4c8c7604277a2041647f96b78f4b9a47858e9217e4fb333d35e7b5ab32c5b57f
|
||||
F src/expr.c 16f90ae2af2a100bc430a89184afde54878d82f18267e8d00bc4f33e695a7c57
|
||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||
F src/fkey.c d617daf66b5515e2b42c1405b2b4984c30ca50fb705ab164271a9bf66c69e331
|
||||
F src/func.c 94f42cba2cc1c34aeaa441022ba0170ec3fec4bba54db4e0ded085c6dc0fdc51
|
||||
F src/fkey.c b1da9ef8dc834603bb0d28972378a7ce65897847f9a1e89ab800bbdf24c788ee
|
||||
F src/func.c e2e3c02621a528a472933fd4733a5da635676f1461be73293f6e9f62f18d4eaa
|
||||
F src/global.c 9bf034fd560bdd514715170ed8460bb7f823cec113f0569ef3f18a20c7ccd128
|
||||
F src/hash.c a12580e143f10301ed5166ea4964ae2853d3905a511d4e0c44497245c7ce1f7a
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 33a2c72b6182e8ddf697d604cc087c77ff5fc512a32b8b624641d41b390e249e
|
||||
F src/insert.c 76b1dc902e4c3930d9a17a40cd8ee2e94b1fd8cce766672caef164a6d5d4df1d
|
||||
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
|
||||
F src/loadext.c f6e4e416a736369f9e80eba609f0acda97148a8b0453784d670c78d3eed2f302
|
||||
F src/main.c 10e3897f5d78cef6bcbd1eedc8ccc3fe9e9783d07e052d9d70e57364ded19274
|
||||
F src/loadext.c 6aae5739198d96c51ae6eb97c4a5b1744c22ed7a5a565a5399a717780d48a36b
|
||||
F src/main.c 0402e234155e0aad75fe6cd204864f492495be8605a50b4b3d4d72895cced3ce
|
||||
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
|
||||
@@ -466,7 +469,7 @@ F src/mem5.c 9bf955937b07f8c32541c8a9991f33ce3173d944
|
||||
F src/memdb.c e94c478a757c4307fd170fe0a7650ef4cf722c59e5a95a8a7896ffedc1679139
|
||||
F src/memjournal.c 6f3d36a0a8f72f48f6c3c722f04301ac64f2515435fa42924293e46fc7994661
|
||||
F src/msvc.h 4942752b6a253116baaa8de75256c51a459a5e81
|
||||
F src/mutex.c b021263554c8a3995e9d53193b8194b96d1ed28e06c3b532dd7f7d29cf0c7d53
|
||||
F src/mutex.c bae36f8af32c22ad80bbf0ccebec63c252b6a2b86e4d3e42672ff287ebf4a604
|
||||
F src/mutex.h 779d588e3b7756ec3ecf7d78cde1d84aba414f85
|
||||
F src/mutex_noop.c 9d4309c075ba9cc7249e19412d3d62f7f94839c4
|
||||
F src/mutex_unix.c aaf9ebc3f89df28483c52208497a99a02cc3650011422fc9d4c57e4392f7fe58
|
||||
@@ -477,32 +480,32 @@ F src/os.h 48388821692e87da174ea198bf96b1b2d9d83be5dfc908f673ee21fafbe0d432
|
||||
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
|
||||
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
|
||||
F src/os_unix.c 2b53b0b8ddc580db096252c721729e5f5f2f355b4fc056f8f3fb328aeb3c9e8a
|
||||
F src/os_win.c eb03c6d52f893bcd7fdd4c6006674c13c1b5e49543fec98d605201af2997171c
|
||||
F src/os_win.c ac29c25cde4cfb4adacc59cdec4aa45698ca0e29164ea127859585ccd9faa354
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 1bb6a57fa0465296a4d6109a1a64610a0e7adde1f3acf3ef539a9d972908ce8f
|
||||
F src/pager.h c571b064df842ec8f2e90855dead9acf4cbe0d1b2c05afe0ef0d0145f7fd0388
|
||||
F src/parse.y 1095d04ac7bc6d2cc69167daf6969c1276970c5d14578e259561d2a5477312f3
|
||||
F src/parse.y 0b81472496809693a139067fea1fe3f14a7be8aa26c8f18bb327034d1252a06a
|
||||
F src/pcache.c 135ef0bc6fb2e3b7178d49ab5c9176254c8a691832c1bceb1156b2fbdd0869bd
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c bea56df3ae0637768c0da4fbbb8f2492f780980d95000034a105ff291bf7ca69
|
||||
F src/pragma.c c0d13c0e82a9197aef5533d63300c5b0c8a216ae1fd14ada64e1f12f398d7e82
|
||||
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c b086fea6a1952db88beca31fdd621201ee5e4ce3f02905248cc3035a8174aa89
|
||||
F src/printf.c d3b7844ddeb11fbbdd38dd84d09c9c1ac171d21fb038473c3aa97981201cc660
|
||||
F src/prepare.c 95a9dba7a5d032039a77775188cb3b6fb17f2fa1a0b7cd915b30b4b823383ffa
|
||||
F src/printf.c 7f6f3cba8e0c49c19e30a1ff4e9aeda6e06814dcbad4b664a69e1b6cb6e7e365
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 6415381a0e9d22c0e7cba33ca4a53f81474190862f5d4838190f5eb5b0b47bc9
|
||||
F src/resolve.c 14602f46800ba182ea6a490e0f304127d29ac1f724bdadcc639e25d3223fcf6e
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 04ae9b4a30992bf428ec27027972ea9e8b31c59e4cbead8adebda1512be2e450
|
||||
F src/shell.c.in 8ab4687da814ddc4adf6ea0fcd43ea1eb2784ee6915674dd690759241b7a24b3
|
||||
F src/sqlite.h.in aa9bd3ae4a077c7002059cb418271abe52214b0227b2a734bc44736b24cbcc40
|
||||
F src/select.c 3291892add3a8f01dc3754e40ef9e30ad22c78e3404a388ae58f0390a1fb29eb
|
||||
F src/shell.c.in c29cb307d6275131e6f9874e0fa73f87acf40a22c4a82faba2059a93b4d294d1
|
||||
F src/sqlite.h.in 63b07f76731f2b1e55c48fdb9f0508dcc6fbe3971010b8612ffd847c3c56d9a1
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 83a3c4ce93d650bedfd1aa558cb85a516bd6d094445ee989740827d0d944368d
|
||||
F src/sqliteInt.h 6f26888c81854b1cc8c9a285d75411636a7c6444227e1953a39b2c52323441d5
|
||||
F src/sqlite3ext.h 9887b27e69c01e79c2cbe74ef73bf01af5b5703d6a7f0a4371e386d7249cb1c7
|
||||
F src/sqliteInt.h d2bd297dba08f2390a91c31ff775e0964e9663df5b2910a569fe6f830b8b2beb
|
||||
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
|
||||
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
|
||||
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
|
||||
F src/tclsqlite.c 916a92de77ec5cbe27818ca194d8cf0c58aa7ad5b87527098f6aa5a6068800ce
|
||||
F src/test1.c b2df6d7ed8ecb53680f7040163ba92b50c471ed8104d128c88c8e969a107887f
|
||||
F src/test1.c 51aa5f3030217ca45eb62e90944838794d4faaae7a8f60e0330ae01f30bc997b
|
||||
F src/test2.c 3efb99ab7f1fc8d154933e02ae1378bac9637da5
|
||||
F src/test3.c b8434949dfb8aff8dfa082c8b592109e77844c2135ed3c492113839b6956255b
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
@@ -529,7 +532,7 @@ F src/test_intarray.c 988fc61cb0ff539f4172c0d95f15287c92516f64
|
||||
F src/test_intarray.h f3b7672f5d1056eac563c0d6ea8480a660b1475c
|
||||
F src/test_journal.c 619f2aa10e0d7a5f87c0f06825bc61dfce1c6b9c7f3ad990fb13de6c3b8874a3
|
||||
F src/test_loadext.c 337056bae59f80b9eb00ba82088b39d0f4fe6dfd
|
||||
F src/test_malloc.c 5201422e2403e66a7a9c2b7d8df806acd8d2a0429822adb7e932f324e7b5b3c6
|
||||
F src/test_malloc.c dec0aa821b230773aeb3dd11d652c1193f7cedb18a20b25659bc672288115242
|
||||
F src/test_md5.c 7268e1e8c399d4a5e181b64ac20e1e6f3bc4dd9fc87abac02db145a3d951fa8c
|
||||
F src/test_multiplex.c e054459f7633f3ff8ce1245da724f9a8be189e4e
|
||||
F src/test_multiplex.h 5436d03f2d0501d04f3ed50a75819e190495b635
|
||||
@@ -554,32 +557,32 @@ F src/test_windirent.c a895e2c068a06644eef91a7f0a32182445a893b9a0f33d0cdb4283dca
|
||||
F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a90484215
|
||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 5b0c661a85f783d35b9883830736eeb63be4aefc4f6b7d9cd081d48782c041e2
|
||||
F src/treeview.c 14d5d1254702ec96876aa52642cb31548612384134970409fae333b25b39d6bb
|
||||
F src/tokenize.c bbde32eac9eb1280f5292bcdfef66f5a57e43176cbf9347e0efab9f75e133f97
|
||||
F src/treeview.c 2c5c4bc0a443401db5fd621542150452ddf5055d38edd4eef868bc2b6bfb0260
|
||||
F src/trigger.c 4ace6d1d5ba9a89822deb287317f33c810440526eafe185c2d8a48c31df1e995
|
||||
F src/update.c ae56e307cf9009290845b79a5f930b7c71613dc9d3ff1d290cdc91c4bd0487d9
|
||||
F src/upsert.c 23b386d71adea0350ad829244fb3f9580eb0b95f119b3d6d56e7362e883605e4
|
||||
F src/update.c 46dc24c6158446aaab45caee09b6d99327cb479268b83ffeb5b701823da3b67b
|
||||
F src/upsert.c 47edd408cc73f8d3c00a140550d1ad180b407c146285947969dd09874802bf88
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
|
||||
F src/vacuum.c 762ee9bbf8733d87d8cd06f58d950e881982e416f8c767334a40ffd341b6bff5
|
||||
F src/vdbe.c 066a4e1de2ed83e253adfd2e97a684cf562eaa41d31ee7f3d3e4c8aea4485a55
|
||||
F src/vdbe.h 574ce9a0d57b026fc93ac379a339b8d391977f335ab4176a7e21ba902e9184bd
|
||||
F src/vdbeInt.h 95f7adfdc5c8f1353321f55a6c5ec00a90877e3b85af5159e393afb41ff54110
|
||||
F src/vdbeapi.c 29d2baf9c1233131ec467d7bed1b7c8a03c27579048d768c4b04acf427838858
|
||||
F src/vdbeaux.c 0fdf97855e523489b8a75483e872164418b46651d8bfd74c6f526b4cbaf3c41d
|
||||
F src/vacuum.c 37730af7540033135909ecaee3667dddec043293428d8718546d0d64ba4a5025
|
||||
F src/vdbe.c 71e5a72d89eabf7f88ef0ad4a429d3c3ee5d10de76af3818c47b275a6b3a9097
|
||||
F src/vdbe.h e3f43bcc27ff30b0f25a6104d0cb5657e1c4b5e1b5cd2dd2216d5bcc2156a746
|
||||
F src/vdbeInt.h 42d3e65ea0c664f6d9bc9a53de645c0baf8566ff0188409ff3b8d2abc327bc17
|
||||
F src/vdbeapi.c 765a0bbe01311626417de6cb743f7f25f9f98435c98a9df4bb0714d11014633d
|
||||
F src/vdbeaux.c b00d35805a2b326d1371ab7ce8f3a95c8af35b1431367ffe482fc2c735d69fb1
|
||||
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
|
||||
F src/vdbemem.c 0cbe9b9560e42b72983cf9e1bceba48f297e51142bfb6b57f3747cf60106b92d
|
||||
F src/vdbemem.c 803323406d8623a7619ea5d5f74016697eeaed19c02b98ce9c3013e77dbe1c38
|
||||
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
|
||||
F src/vdbetrace.c 48e11ebe040c6b41d146abed2602e3d00d621d7ebe4eb29b0a0f1617fd3c2f6c
|
||||
F src/vtab.c 0e4885495172e1bdf54b12cce23b395ac74ef5729031f15e1bc1e3e6b360ed1a
|
||||
F src/vdbetrace.c 79d6dbbc479267b255a7de8080eee6e729928a0ef93ed9b0bfa5618875b48392
|
||||
F src/vtab.c 10ea07dec111de6fb0a4fc87a7ffa4c65fdc088a19dbfaf7d6f2b128f2e8eb7b
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c aa9cffc7a2bad6b826a86c8562dd4978398720ed41cb8ee7aa9d054eb8b456a0
|
||||
F src/wal.h 8de5d2d3de0956d6f6cb48c83a4012d5f227b8fe940f3a349a4b7e85ebcb492a
|
||||
F src/walker.c da987a20d40145c0a03c07d8fefcb2ed363becc7680d0500d9c79915591f5b1f
|
||||
F src/where.c d6e5f2056e9a60251e79780fc598a5943e88a3c0fa0019d54922e59f99019287
|
||||
F src/whereInt.h 2610cb87dd95509995b63decc674c60f2757697a206cfe0c085ee53d9c43cfff
|
||||
F src/wherecode.c 982b7450c53fb272f61a1d20c93e960260ea4dfe8e2e9bacc190e2a041a1f1a4
|
||||
F src/whereexpr.c 53532be687e12f3cd314f1e204cd4fbdac7ad250e918a182b048121e16e828ae
|
||||
F src/where.c 60ec752fcbe9f9e0271ac60548d159a540a1ee47a4f9fedc85e88a3d0e392dd1
|
||||
F src/whereInt.h cbae2bcd37cfebdb7812a8b188cdb19634ced2b9346470d1c270556b0c33ea53
|
||||
F src/wherecode.c 728c7f70731430ccdac807a79969873e1af6968bf1c4745dff3f9dd35f636cc8
|
||||
F src/whereexpr.c e90b2e76dcabc81edff56633bf281bc01d93b71e0c81482dc06925ce39f5844a
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
|
||||
@@ -594,19 +597,19 @@ F test/alter4.test b6d7b86860111864f6cddb54af313f5862dda23b
|
||||
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test b3a9c67d00e1df7588a5b7be9a0292899f94fe8cac1f94a017277474ca2e59df
|
||||
F test/analyze3.test 8b3ef8ba6d1096b76c40e0925c0fe51e700d2b779cdda40914580de3f9b9d80f
|
||||
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
|
||||
F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
|
||||
F test/analyze4.test cdf88f3f72b0f0643a1ff6c730fc5af1e42464d47478d9fbac84c333f72c014e
|
||||
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
|
||||
F test/analyze6.test f1c552ce39cca4ec922a7e4e0e5d0203d6b3281f
|
||||
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
|
||||
F test/analyze8.test c05a461d0a6b05991106467d0c47480f2e709c82
|
||||
F test/analyze9.test dac0bdc7eab965b9ad639ca83564d98717aaf13ce5a776f23d9a3680238cecd8
|
||||
F test/analyzeA.test 3335697f6700c7052295cfd0067fc5b2aacddf9a
|
||||
F test/analyze6.test 7b2667b879976ac4b90d8df80d5456328684f1f6f6fdef9469d6e53401f2f469
|
||||
F test/analyze7.test a37f4d9cb699a8af068ae02df1bb08bf844df8e98a92a8126cbff89e226879d8
|
||||
F test/analyze8.test e32a970564271114786703750e6939cf81dea4b8580874e38e9213ee092f6936
|
||||
F test/analyze9.test 9fbf0e0101eef4f5dc149769aa14e10b76ee06e7c28598264b32173cd1999a54
|
||||
F test/analyzeA.test 22a892d67bd2223126335b99774cce56ba91122cfe82446d2927afc43ad667dc
|
||||
F test/analyzeB.test a4c1c3048f6d9e090eb76e83eecb18bcf6d31a70
|
||||
F test/analyzeC.test 555a6cc388b9818b6eda6df816f01ce0a75d3a93
|
||||
F test/analyzeD.test 42af58de25a6436502e43006e9e59e2d71bcb0cf
|
||||
F test/analyzeD.test e50cd0b3e6063216cc0c88a1776e8645dc0bd65a6bb275769cbee33b7fd8d90c
|
||||
F test/analyzeE.test 8684e8ac5722fb97c251887ad97e5d496a98af1d
|
||||
F test/analyzeF.test f423125b557f11ad71bb29765ef9c34b6dcf4ab7
|
||||
F test/analyzeF.test 9e1a0537949eb5483642b1140a5c39e5b4025939024b935398471fa552f4dabb
|
||||
F test/analyzer1.test 459fa02c445ddbf0101a3bad47b34290a35f2e49
|
||||
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
|
||||
F test/async2.test c0a9bd20816d7d6a2ceca7b8c03d3d69c28ffb8b
|
||||
@@ -624,12 +627,12 @@ F test/auth.test 3d6cd8f3978ba55b1202574e6ecd79c6e00914ca44b9bfd6c1fe6fb873fcac8
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test db21405b95257c24d29273b6b31d0efc59e1d337e3d5804ba2d1fd4897b1ae49
|
||||
F test/autoanalyze1.test b9cc3f32a990fa56669b668d237c6d53e983554ae80c0604992e18869a0b2dec
|
||||
F test/autoinc.test 6ae8fb69c9f656962464ae4e6667045d0dfc3b46
|
||||
F test/autoindex1.test 788d0894aa3aee1220036d20696e98733fb7ca02265cb1e801700177120c1aeb
|
||||
F test/autoinc.test 9d202b7dce6571e52b744138eff12610214501acd635abdd72d18736cd06fd22
|
||||
F test/autoindex1.test a09958fa756129af10b6582bcbf3cbdf11e305e027b393f393caef801159dee0
|
||||
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
F test/autoindex3.test 2dd997d6590438b53e4f715f9278aa91c9299cf3f81246a0915269c35beb790e
|
||||
F test/autoindex4.test 49d3cd791a9baa16fb461d7ea3de80d019a819cf
|
||||
F test/autoindex5.test 96f084a5e6024ea07cace5888df3223f3ea86990
|
||||
F test/autoindex5.test 5f0135dc3b266277b8c1904624439097d8e8020dd7197eda13fda23c35c21a05
|
||||
F test/autovacuum.test 0831cd34e14695d297187f7f6519265e3121c5b0a1720e548e86829e796129e9
|
||||
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
|
||||
F test/avtrans.test b7dc25459ecbd86c6fa9c606ee3068f59d81e225118617dcf2bbb6ded2ade89e
|
||||
@@ -643,15 +646,15 @@ F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
|
||||
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
|
||||
F test/bestindex1.test 0cf1bd2d7b97d3a3a8c10736125274f64765c4ee
|
||||
F test/bestindex2.test 4a06b8922ab2fd09434870da8d1cdf525aaf7060
|
||||
F test/bestindex3.test 578b6a52dab819e63f28e3640e04b32c85aed320
|
||||
F test/bestindex1.test 852170bddbb21daa121fabcc274640ff83d7d8705912e8b5fe7ed2c5a9a9224a
|
||||
F test/bestindex2.test 9a0ccd320b6525eec3a706aae6cdab7e1b7b5abca75027e39f39f755e76e5928
|
||||
F test/bestindex3.test 001788a114ad96d81d5154fe77c7f1e26e84b3a2b5635ca29e4f96f6decc534e
|
||||
F test/bestindex4.test 4cb5ff7dbaebadb87d366f51969271778423b455
|
||||
F test/bestindex5.test 412b42f8036b28d8b2f3534d89389ad946a4b1a65a12263f51936f7424296f1b
|
||||
F test/between.test 34d375fb5ce1ae283ffe82b6b233e9f38e84fc6c
|
||||
F test/bigfile.test aa74f4e5db51c8e54a1d9de9fa65d01d1eb20b59
|
||||
F test/bigfile2.test 1b489a3a39ae90c7f027b79110d6b4e1dbc71bfc
|
||||
F test/bigmmap.test abe819e6e1ac1db0c3bfe364ff58889d96e7896b2bbc8bdf1afc77cdeb7d7a9b
|
||||
F test/bigmmap.test 31dad31573638bd32de866cdefd11843f75685be4ba6aec1a47918f098f1899b
|
||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||
F test/bigsort.test 8299fa9298f4f1e02fc7d2712e8b77d6cd60e5a2
|
||||
F test/bind.test 1e136709b306f7ed3192d349c2930d89df6ab621654ad6f1a72381d3fe76f483
|
||||
@@ -683,7 +686,7 @@ F test/cast.test 5ceb920718d280b61163500a7d29e0e0a86458b1cbd92d96f962c9d970aa385
|
||||
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
|
||||
F test/check.test 33a698e8c63613449d85d624a38ef669bf20331daabebe3891c9405dd6df463a
|
||||
F test/close.test 799ea4599d2f5704b0a30f477d17c2c760d8523fa5d0c8be4a7df2a8cad787d8
|
||||
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
|
||||
F test/closure01.test 9905883f1b171a4638f98fc764879f154e214a306d3d8daf412a15e7f3a9b1e0
|
||||
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
|
||||
F test/collate1.test 08c18e7512a5a32c97938854263fa15362eeb846
|
||||
F test/collate2.test 9aaa410a00734e48bcb27f3872617d6f69b2a621
|
||||
@@ -722,9 +725,9 @@ F test/corruptH.test 79801d97ec5c2f9f3c87739aa1ec2eb786f96454
|
||||
F test/corruptI.test 075fe1d75aa1d84e2949be56b6264376c41502e4
|
||||
F test/corruptJ.test 4d5ccc4bf959464229a836d60142831ef76a5aa4
|
||||
F test/corruptK.test 91550557849244a9904f4e090052e3f2c1c3f1106840d58b00ffaa3a8c2d3fc0
|
||||
F test/cost.test 1eedbfd868f806f3fa08ff072b04cf270dcf61c8
|
||||
F test/cost.test b37db8a10d467a69e71a9f3d40bbb266c2f587742b37c6912f6e3f7185a0e216
|
||||
F test/count.test cb2e0f934c6eb33670044520748d2ecccd46259c
|
||||
F test/coveridxscan.test b629e896b14df2f000a99b8d170d80589c46562c
|
||||
F test/coveridxscan.test 5ec98719a2e2914e8908dc75f7247d9b54a26df04625f846ac7900d5483f7296
|
||||
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
|
||||
F test/crash2.test 5b14d4eb58b880e231361d3b609b216acda86651
|
||||
F test/crash3.test 8f5de9d32ab9ab95475a9efe7f47a940aa889418
|
||||
@@ -737,7 +740,7 @@ F test/crashM.test d95f59046fa749b0d0822edf18a717788c8f318d
|
||||
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
|
||||
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
|
||||
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
|
||||
F test/csv01.test 526fc6aefd052badd5a0283f86b4b395c3df76bfe98d96c801f494f5e2c7836c
|
||||
F test/csv01.test 6e1445b3207d574cff22fc41a8e549dfcf2466ee90546ada97d22a90fa89eb58
|
||||
F test/ctime.test 78749e6c9a5f0010d67985be80788f841e3cd2da18114e2ed6010399a7d807f3
|
||||
F test/cursorhint.test 7bc346788390475e77a345da2b92270d04d35856
|
||||
F test/cursorhint2.test 0078ae1ded4afcf5eb80d06e3a72b6e1c3f1a646aab26eeb583b0a9ec6f0d56e
|
||||
@@ -765,12 +768,12 @@ F test/e_blobclose.test 4b3c8c60c2171164d472059c73e9f3c1844bb66d
|
||||
F test/e_blobopen.test e95e1d40f995056f6f322cd5e1a1b83a27e1a145
|
||||
F test/e_blobwrite.test f87ff598b67af5b3ec002a8d83e804dc8d23808e88cf0080c176612fc9ffce14
|
||||
F test/e_changes.test fd66105385153dbf21fdb35eb8ef6c3e1eade579
|
||||
F test/e_createtable.test d4c6059d44dcd4b636de9aae322766062b471844
|
||||
F test/e_createtable.test e1c4512b9e15fe7bedbbfc0c6daac8a4af65f32dc3c48310b0135b5735857b26
|
||||
F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 21ce09c361227ddbc9819a5608ee2700c276bdd5
|
||||
F test/e_expr.test ca8896601ade1e27c6559614c7f32c63d44636fdfa720436a160f09b8bf66c89
|
||||
F test/e_fkey.test dcdc6ad26b1d4f07636208de4c1c22aae7c0597a685a6c10fe6da91f3191dd96
|
||||
F test/e_fkey.test 9778696ef9fceacebed8d482d02b47287981faaedf6f73db563ea8a7afb546da
|
||||
F test/e_fts3.test 8cf40550bb088a6aa187c818c00fabe26ef82900a4cd5c66b427ccafe28bedaa
|
||||
F test/e_insert.test f02f7f17852b2163732c6611d193f84fc67bc641fb4882c77a464076e5eba80e
|
||||
F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8
|
||||
@@ -790,7 +793,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
|
||||
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
|
||||
F test/enc3.test 6807f7a7740a00361ca8d0ccd66bc60c8dc5f2b6
|
||||
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
|
||||
F test/eqp.test 3fe051af50921284189d1970eb653f9fcf5117d2
|
||||
F test/eqp.test 4fd69d25f21d8679f5fce13e639975879d89abf6acce4bd9cede133b7482aba7
|
||||
F test/errmsg.test eae9f091eb39ce7e20305de45d8e5d115b68fa856fba4ea6757b6ca3705ff7f9
|
||||
F test/eval.test a64c9105d6ff163df7cf09d6ac29cdad5922078c
|
||||
F test/exclusive.test 1206b87e192497d78c7f35552e86a9d05421498da300fb1cce5ca5351ccde3c3
|
||||
@@ -868,7 +871,7 @@ F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test c416d50c4fdb6f32a15205b3d0a49eb74fcea92feb66b531a83c904770de5ff1
|
||||
F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1
|
||||
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
|
||||
F test/fts3aux1.test 24b8a69e342a6684e3929408b245cdf5de0d45f8094108fa0a57cd007228963d
|
||||
F test/fts3aux1.test 7a170e172afdbceb67f5baa05941fd4fbf56af42f61daa3d140f4b4bf4cb68f6
|
||||
F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
|
||||
F test/fts3b.test c15c4a9d04e210d0be67e54ce6a87b927168fbf9c1e3faec8c1a732c366fd491
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
@@ -884,15 +887,15 @@ F test/fts3defer2.test c540f5f5c2840f70c68fd9b597df817ec7170468
|
||||
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
|
||||
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
|
||||
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
|
||||
F test/fts3expr.test 9466627007804d855bf9df2a0cfb3dac23686fdc
|
||||
F test/fts3expr.test ebae205a7a89446c32583bcd492dcb817b9f6b31819bb4dde2583bb99c77e526
|
||||
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
||||
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
|
||||
F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3
|
||||
F test/fts3expr4.test cac5dd815fe6b5921741abdccdde3b7f50b86394de91e13308ee7986859c4a9f
|
||||
F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
|
||||
F test/fts3fault.test 9fb7d6266a38806de841f7244bac1b0fe3a1477184bbb10b172d19d2ca6ad692
|
||||
F test/fts3fault2.test 6a17a11d8034b1c4eca9f3091649273d56c49ff049e2173df8060f94341e9da0
|
||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||
F test/fts3join.test 69aeb460d0ea17527a2b1b8d24ce18f29c7f207a7261867a2618f639c8020459
|
||||
F test/fts3join.test 949b4f5ae3ae9cc2423cb865d711e32476bdb205ab2be923fdf48246e4a44166
|
||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||
F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a
|
||||
F test/fts3misc.test ba03a83b831555cfd18c6c862b24b70a53ce7497fe55077f7c4b7c9ce83c2eed
|
||||
@@ -900,7 +903,7 @@ F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
|
||||
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
||||
F test/fts3prefix2.test e1f0a822ca661dced7f12ce392e14eaf65609dce
|
||||
F test/fts3query.test f33eb71a1fe1084ea585eeb7ee76b390729f5170
|
||||
F test/fts3query.test ca5dffabdfe9aef2ebcc89e02ce515898f86f8c30a365283831c53e0e08e5821
|
||||
F test/fts3rank.test cd99bc83a3c923c8d52afd90d86979cf05fc41849f892faeac3988055ef37b99
|
||||
F test/fts3rnd.test 1320d8826a845e38a96e769562bf83d7a92a15d0
|
||||
F test/fts3shared.test 57e26a801f21027b7530da77db54286a6fe4997e
|
||||
@@ -938,13 +941,14 @@ F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
|
||||
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
|
||||
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
|
||||
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
|
||||
F test/fuzz_malloc.test 328f70aaca63adf29b4c6f06505ed0cf57ca7c26
|
||||
F test/fuzzcheck.c 5eb86c6ac96833ee622f45bf47e8045999c1b4b10d05e4eb809894a4b39f2f84
|
||||
F test/fuzz_malloc.test 5b257a7652d8ee90b22e9cf80d9dbea31a4f3e6fed1d33de57b24b1bdb211d79
|
||||
F test/fuzzcheck.c 3885207dc217c4dcdb2de4a3cb169a263afeef51ab9bd0ba8567289f0a19a470
|
||||
F test/fuzzdata1.db 7ee3227bad0e7ccdeb08a9e6822916777073c664
|
||||
F test/fuzzdata2.db f03a420d3b822cc82e4f894ca957618fbe9c4973
|
||||
F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
|
||||
F test/fuzzdata4.db 1882f0055fb63214d8407ddc7aca9b0b1c59af21
|
||||
F test/fuzzdata5.db 9f0cdcc5c6e83b90cf9ae343bd07f684d2da2de7
|
||||
F test/fuzzdata5.db 117d821cde02e30a687f6361a34b98e6e0b05062df523cfee163c58564403b68
|
||||
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
|
||||
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
|
||||
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
|
||||
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
|
||||
@@ -979,13 +983,13 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
|
||||
F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||
F test/index6.test b4fc812290067a578b98bb2667b676db89e202a7
|
||||
F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
|
||||
F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d
|
||||
F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98
|
||||
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
|
||||
F test/indexedby.test faa585e315e868f09bce0eb39c41d6134649b13d2801638294d3ae616edf1609
|
||||
F test/indexedby.test a52c8c6abfae4fbfb51d99440de4ca1840dbacc606b05e29328a2a8ba7cd914e
|
||||
F test/indexexpr1.test 635261197bcdc19b9b2c59bbfa7227d525c00e9587faddb2d293c44d287ce60e
|
||||
F test/indexexpr2.test 13247bac49143196556eb3f65e97ef301bd3e993f4511558b5db322ddc370ea6
|
||||
F test/indexexpr2.test 08551aa8956a91582979e17b6d369f321a5cb6ed6d3e952925a3e54e9e7de216
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -1008,10 +1012,10 @@ F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
|
||||
F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
|
||||
F test/istrue.test 62372ad3ddcc5d0eb8ff9097dcb0aad8961bf1b9cb45ba634f6e284695126f9a
|
||||
F test/join.test 2ad9d7fe10e0cc06bc7803c22e5533be11cdadbc592f5f95d789a873b57a5a66
|
||||
F test/join2.test f5ea0fd3b0a441c8e439706339dcd17cec63a896a755c04a30bfd442ecce1190
|
||||
F test/join2.test 10f7047e723ebd68b2f47189be8eed20451a6f665d8bf46f1774c640d1062417
|
||||
F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
|
||||
F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
|
||||
F test/join5.test c6bd62effc37a152bea735f9ef241b19bb967bd4593dc99b20e2fc55ae707e38
|
||||
F test/join5.test 5a2da0c3ea852a7063d3e72fc7d5a04a6de5ef6e6d85092582f69033f7459adc
|
||||
F test/join6.test cfe6503791ceb0cbb509966740286ec423cbf10b
|
||||
F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497
|
||||
F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4
|
||||
@@ -1019,7 +1023,7 @@ F test/journal3.test c9c29883f5bf535ae82ae21c472df6263806a22e467b6db7cd0d6d54530
|
||||
F test/jrnlmode.test a6693f2bed4541a21e703aaa37bb3e10de154130645952933b82b2dec0a8b539
|
||||
F test/jrnlmode2.test 8759a1d4657c064637f8b079592651530db738419e1d649c6df7048cd724363d
|
||||
F test/jrnlmode3.test 556b447a05be0e0963f4311e95ab1632b11c9eaa
|
||||
F test/json101.test 24e97954e3bd6404f3715888c7f8f835e36e19c7ae6513b5d9ab2d381498962d
|
||||
F test/json101.test b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
|
||||
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
|
||||
F test/json103.test c5f6b85e69de05f6b3195f9f9d5ce9cd179099a0
|
||||
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
|
||||
@@ -1064,7 +1068,7 @@ F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
|
||||
F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
|
||||
F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
|
||||
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
|
||||
F test/mallocK.test 27cb5566a6e5f2d76f9d4aa2eca45524401fd61e
|
||||
F test/mallocK.test 1f4b5efbf61715ab79b20b38739ff4b3d110ceb53f54e5db6da1f01c083707ab
|
||||
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
|
||||
F test/mallocM.test 78bbe9d3da84a5c679123cdb40d7b2010b18fc46e13897e4f253c6ba6fbff134
|
||||
F test/malloc_common.tcl aac62499b76be719fac31e7a3e54a7fd53272e7f
|
||||
@@ -1085,7 +1089,7 @@ F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
|
||||
F test/misc4.test 0d8be3466adf123a7791a66ba2bc8e8d229e87f3
|
||||
F test/misc5.test 60e1fc758a93cacd19eb2fafcd1d40d150a05047546c7a92389c98047d621901
|
||||
F test/misc6.test 953cc693924d88e6117aeba16f46f0bf5abede91
|
||||
F test/misc7.test 567e223b6497da2226a0340befaf2d663c91ad57a48aede21a35a984a2882d41
|
||||
F test/misc7.test 349855706310f0de6b91645d199f6874f518627fd057743fa4e3689b60d06efc
|
||||
F test/misc8.test 8fb0f31d7a8aed484d759773ab8ad12ec746a477f4a67394a4af0e677494c3ca
|
||||
F test/misuse.test 9e7f78402005e833af71dcab32d048003869eca5abcaccc985d4f8dc1d86bcc7
|
||||
F test/mjournal.test 9d86e697dcbc5da2c4e8caba9b176b5765fe65e80c88c278b8c09a917e436795
|
||||
@@ -1117,7 +1121,7 @@ F test/openv2.test 0d3040974bf402e19b7df4b783e447289d7ab394
|
||||
F test/optfuzz-db01.c a0c256905c8ac79f9a5de2f374a3d9f757bef0dca2a238dc7c10cc8a38031834
|
||||
F test/optfuzz-db01.txt 21f6bdeadc701cf11528276e2a55c70bfcb846ba42df327f979bd9e7b6ce7041
|
||||
F test/optfuzz.c 50e330304eb1992e15ddd11f3daaad9bcc0d9aaad09cb2bcc77f9515df2e88b1
|
||||
F test/orderby1.test 4d22a7c75f6a83fc1f188cc7bb5192285fdf2552
|
||||
F test/orderby1.test e4501f54721f804ca56922e253403ac6775f88e9f07569994ce99212b3ca5b10
|
||||
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
|
||||
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
|
||||
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
|
||||
@@ -1126,11 +1130,11 @@ F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
|
||||
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
|
||||
F test/orderby8.test 23ef1a5d72bd3adcc2f65561c654295d1b8047bd
|
||||
F test/orderby9.test 87fb9548debcc2cd141c5299002dd94672fa76a3
|
||||
F test/oserror.test b32dc34f2363ef18532e3a0a7358e3e7e321974f
|
||||
F test/oserror.test e7b3416be4b9d5dd2fe0b42dd394daaddbb6c83eeec1f0e47b120b53e0ad3ace
|
||||
F test/ossfuzz.c c4c4547e2c92ac52f10038b073a03248251a23c1c559728f63a18aeca0e79f03
|
||||
F test/ossshell.c f125c5bd16e537a2549aa579b328dd1c59905e7ab1338dfc210e755bb7b69f17
|
||||
F test/ovfl.test 199c482696defceacee8c8e0e0ef36da62726b2f
|
||||
F test/pager1.test f596d3bd53ce96e1d87d44d223d2ae6c8867dd782c425e5eb28b5721fa6aaa97
|
||||
F test/pager1.test a32ce299ed01ffb06e84a3af467ae1f3389786b316f40c4359f442c79144736b
|
||||
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
|
||||
F test/pager3.test 4e9a83d6ca0838d7c602c9eb93d1357562d9059c1e02ffb138a8271020838370
|
||||
F test/pager4.test a122e9e6925d5b23b31e3dfef8c6a44bbf19590e
|
||||
@@ -1169,17 +1173,18 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 5f15ab8056799e9a6e26a310d49236d2e774d6a30d0ec74601e18d4ce146b79c x
|
||||
F test/resetdb.test 2107b34a8c437183f48eb833905df43818160a55f4ac69bbaf54f356fb2b27bd
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa
|
||||
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
|
||||
F test/rollback2.test bc868d57899dc6972e2b4483faae0e03365a0556941474eec487ae21d8d38bb6
|
||||
F test/rollbackfault.test 0e646aeab8840c399cfbfa43daab46fd609cf04a
|
||||
F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc
|
||||
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
|
||||
F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d
|
||||
F test/rowvalue.test 32861d6a933ded868035f2ec79aeb993a2a46eb7a6d282ae13415a4c2e369463
|
||||
F test/rowvalue.test ef851a80f7e6de93b51caca9e4b6b7d2dcd540bbcca7d51860e80435b8b4c0de
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 3068f508753af69884b12125995f023da0dbb256
|
||||
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
|
||||
F test/rowvalue4.test cbd1cead27a797d11ec93301fd801c89e97eb1809b3d984b7f16a3876e362eac
|
||||
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
|
||||
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8
|
||||
@@ -1195,7 +1200,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd
|
||||
F test/savepoint6.test f41279c5e137139fa5c21485773332c7adb98cd7
|
||||
F test/savepoint7.test cde525ea3075283eb950cdcdefe23ead4f700daa
|
||||
F test/savepointfault.test f044eac64b59f09746c7020ee261734de82bf9b2
|
||||
F test/scanstatus.test 1ba0e2ee25dcd1d55ec770803b19832cffaecbf0b15d376807759ebeed3669b0
|
||||
F test/scanstatus.test d14842d0a2757ee059bcffa365746453d60952ba1077980c9a348a9fefbd232a
|
||||
F test/schema.test 8f7999be894260f151adf15c2c7540f1c6d6a481
|
||||
F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5
|
||||
F test/schema3.test 1bc1008e1f8cb5654b248c55f27249366eb7ed38
|
||||
@@ -1213,10 +1218,10 @@ F test/select6.test 39eac4a5c03650b2b473c532882273283ee8b7a0
|
||||
F test/select7.test f659f231489349e8c5734e610803d7654207318f
|
||||
F test/select8.test 8c8f5ae43894c891efc5755ed905467d1d67ad5d
|
||||
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
|
||||
F test/selectA.test 101e722370ac6e84978c2958b8931c78b10a1709
|
||||
F test/selectA.test b8a590f6493cad5b0bb4dfe1709bf7dcda0b6c40bb4caf32d1e36a89eebc8fc5
|
||||
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
|
||||
F test/selectC.test e25243f8ca503e06f252eb0218976d07cfeceac3
|
||||
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
|
||||
F test/selectD.test cfa9f27dbdbeaf2d021d26c79b6c790d8f26e5506d50117c7696d3e136d6d9e7
|
||||
F test/selectE.test a8730ca330fcf40ace158f134f4fe0eb00c7edbf
|
||||
F test/selectF.test 21c94e6438f76537b72532fa9fd4710cdd455fc3
|
||||
F test/selectG.test 089f7d3d7e6db91566f00b036cb353107a2cca6220eb1cb264085a836dae8840
|
||||
@@ -1236,7 +1241,7 @@ F test/sharedA.test 49d87ec54ab640fbbc3786ee3c01de94aaa482a3a9f834ad3fe92770eb69
|
||||
F test/sharedB.test 16cc7178e20965d75278f410943109b77b2e645e
|
||||
F test/shared_err.test 32634e404a3317eeb94abc7a099c556a346fdb8fb3858dbe222a4cbb8926a939
|
||||
F test/sharedlock.test 5ede3c37439067c43b0198f580fd374ebf15d304
|
||||
F test/shell1.test e2f7d375ae80eb16590af23d6c40cd0140b6d1f92642c1b71eb94630a144ee08
|
||||
F test/shell1.test 50154b0c4779df435b9e60ca60104b05f1cc217eab1aa383131359329e73d939
|
||||
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
|
||||
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
|
||||
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
|
||||
@@ -1249,15 +1254,15 @@ F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test 8ab5d2c7c5cd3fe7f172d366e6e74e887cb33cb4
|
||||
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan2.test ef143c6e4a5ba4f19c1d1e3f517811f7942bdf2142736cc568feb34e0b5fb763
|
||||
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
F test/skipscan6.test 5866039d03a56f5bd0b3d172a012074a1d90a15b
|
||||
F test/skipscan6.test 0b4cd1b4ac9f84d91454df513c99a4932fa07e8f27b8049bea605068b3e34ac7
|
||||
F test/snapshot.test 85735bd997a4f6d710140c28fd860519a299649f
|
||||
F test/snapshot2.test 925e42427e923262db63c9d7155183f889e3e99feaedec4075f659e51608344f
|
||||
F test/snapshot3.test 9719443594a04778861bd20d12596c5f880af177d6cd62f111da3198cafc6096
|
||||
F test/snapshot_fault.test 52c5e97ebd218846a8ae2da4d147d3e77d71f963
|
||||
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
|
||||
F test/soak.test 18944cf21b94a7fe0df02016a6ee1e9632bc4e8d095a0cb49d95e15d5cca2d5c
|
||||
F test/softheap1.test 843cd84db9891b2d01b9ab64cef3e9020f98d087
|
||||
F test/sort.test c2adc635c2564241fefec0b3a68391ef6868fd3b
|
||||
F test/sort2.test cc23b7c19d684657559e8a55b02f7fcee03851d0
|
||||
@@ -1274,7 +1279,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 377a0c48e5a92e0b11c1c5ebb1bc9d83a7312c922bc0cb05970ef5d6a96d1f0c
|
||||
F test/speedtest1.c 20cc4028b0e88392b5a635c2ea5d5e777d569bf7258aead37f8be7a886c38344
|
||||
F test/speedtest1.c cc7e6b4a7c9f3e3d1a497ae3f75236a832a2ce0f6a9b017f95d996c821605bfb
|
||||
F test/spellfix.test 951a6405d49d1a23d6b78027d3877b4a33eeb8221dcab5704b499755bb4f552e
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1314,7 +1319,7 @@ F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
|
||||
F test/temptable2.test d2940417496e2b9548e01d09990763fbe88c316504033256d51493e1f1a5ce6a
|
||||
F test/temptable3.test d11a0974e52b347e45ee54ef1923c91ed91e4637
|
||||
F test/temptrigger.test 38f0ca479b1822d3117069e014daabcaacefffcc
|
||||
F test/tester.tcl 94901a4625d9a2229666dd5c44120ddf7f0fb639470710ef74a4cefc7b039e07
|
||||
F test/tester.tcl aa7558f20fcf7dd9151325f849d9103bd450235093bc078073bf0f080991e3c4
|
||||
F test/thread001.test b61a29dd87cf669f5f6ac96124a7c97d71b0c80d9012746072055877055cf9ef
|
||||
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
|
||||
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
|
||||
@@ -1335,7 +1340,7 @@ F test/tkt-2d1a5c67d.test be1326f3061caec85085f4c9ee4490561ca037c0
|
||||
F test/tkt-2ea2425d34.test 1cf13e6f75d149b3209a0cb32927a82d3d79fb28
|
||||
F test/tkt-31338dca7e.test 6fb8807851964da0d24e942f2e19c7c705b9fb58
|
||||
F test/tkt-313723c356.test 4b306ad45c736cedf2f5221f6155b92143244b6d
|
||||
F test/tkt-385a5b56b9.test c0a06ada41d7f06b1686da0e718553f853771d1e
|
||||
F test/tkt-385a5b56b9.test 5204a7cba0e28c99df0acbf95af5e1af4d32965a7a14de6eccebf949607618b1
|
||||
F test/tkt-38cb5df375.test f3cc8671f1eb604d4ae9cf886ed4366bec656678
|
||||
F test/tkt-3998683a16.test 6d1d04d551ed1704eb3396ca87bb9ccc8c5c1eb7
|
||||
F test/tkt-3a77c9714e.test b08bca26de1140bdf004a37716582a43d7bd8be8
|
||||
@@ -1350,7 +1355,7 @@ F test/tkt-5e10420e8d.test 904d1687b3c06d43e5b3555bbcf6802e7c0ffd84
|
||||
F test/tkt-5ee23731f.test 9db6e1d7209dc0794948b260d6f82b2b1de83a9f
|
||||
F test/tkt-6bfb98dfc0.test 24780633627b5cfc0635a5500c2389ebfb563336
|
||||
F test/tkt-752e1646fc.test ea78d88d14fe9866bdd991c634483334639e13bf
|
||||
F test/tkt-78e04e52ea.test 1b2e6bf4f1d9887b216b6da774e5f25915ec8118
|
||||
F test/tkt-78e04e52ea.test 1b5be1bac961833a9fd70fe50738cb4064822c61f82c54f7d488435ec806ea62
|
||||
F test/tkt-7a31705a7e6.test 9e9c057b6a9497c8f7ba7b16871029414ccf6550e7345d9085d6d71c9a56bb6f
|
||||
F test/tkt-7bbfb7d442.test 7b2cd79c7a17ae6750e75ec1a7846712a69c9d18
|
||||
F test/tkt-80ba201079.test 105a721e6aad0ae3c5946d7615d1e4d03f6145b8
|
||||
@@ -1368,7 +1373,7 @@ F test/tkt-a8a0d2996a.test 76662ff0622c90e7ce7bbcb4d9e1129acddf877d17c3489f2da7f
|
||||
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
|
||||
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
|
||||
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
|
||||
F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4
|
||||
F test/tkt-b75a9ca6b0.test 1bc0381538fd21f96a10dbabc10ffc51b5b2e5f412d34bae571273ca784003d7
|
||||
F test/tkt-ba7cbfaedc.test b4c0deccc12aeb55cfdb57935b16b5d67c5a9877
|
||||
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
|
||||
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
|
||||
@@ -1433,7 +1438,7 @@ F test/tkt3346.test 6f67c3ed7db94dfc5df4f5f0b63809a1f611e01a
|
||||
F test/tkt3357.test 77c37c6482b526fe89941ce951c22d011f5922ed
|
||||
F test/tkt3419.test 1bbf36d7ea03b638c15804251287c2391f5c1f6b
|
||||
F test/tkt3424.test 61f831bd2b071bd128fa5d00fbda57e656ca5812
|
||||
F test/tkt3442.test 53840ec5325bb94544792aad4c20476f81dc26b1
|
||||
F test/tkt3442.test a1fc47c669e651d16494de3ff349bcb53281456f2ca02c8bc14220b6044bbfe8
|
||||
F test/tkt3457.test 5651e2cbb94645b677ec663160b9e192b87b7d365aecdfb24e19f749575a6fc2
|
||||
F test/tkt3461.test 228ea328a5a21e8663f80ee3d212a6ad92549a19
|
||||
F test/tkt3493.test 1686cbde85f8721fc1bdc0ee72f2ef2f63139218
|
||||
@@ -1469,7 +1474,7 @@ F test/tkt3992.test f3e7d548ac26f763b47bc0f750da3d03c81071da
|
||||
F test/tkt3997.test a335fa41ca3985660a139df7b734a26ef53284bd
|
||||
F test/tkt4018.test 18dbc6617f7a4b90e938d1bd6d26ad18daafaf08
|
||||
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
|
||||
F test/tpch01.test 7c4eb8cdd79c568f46d344b3e789c9fdb8a766d112871352704861f3fca32a2a
|
||||
F test/trace.test a659a9862957f4789e37a92b3bf6d2caf5c86b02cdeefc41e850ae53acf6992a
|
||||
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
|
||||
F test/trace3.test 1dff966888773ff1bfea01c080caf15417892b3f998408fe920c4791f7337144
|
||||
@@ -1477,7 +1482,7 @@ F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
F test/transitive1.test 293300f46916569f08875cdb2fe2134be2c27677
|
||||
F test/trigger1.test ea9624cc1dae05645469df6119fa815f9e6f1e8c
|
||||
F test/trigger1.test 17e4b43e656c4b354df2357634a6ba887990f510c43629f4feca30e3338d2a61
|
||||
F test/trigger2.test 5cd7d69a7ba1143ee045e4ae2963ff32ae4c87a6
|
||||
F test/trigger3.test aa640bb2bbb03edd5ff69c055117ea088f121945
|
||||
F test/trigger4.test 74700b76ebf3947b2f7a92405141eb2cf2a5d359
|
||||
@@ -1506,13 +1511,14 @@ F test/unionvtabfault.test 26b6854d5aef9005cd630513025690bff1b7378ae9c97b81e2a3c
|
||||
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
|
||||
F test/unique2.test 3674e9f2a3f1fbbfd4772ac74b7a97090d0f77d2
|
||||
F test/unixexcl.test d936ba2b06794018e136418addd59a2354eeae97
|
||||
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
|
||||
F test/unordered.test ffeea7747d5ba962a8009a20b7e53d68cbae05b063604c68702c5998eb50c981
|
||||
F test/update.test 1148de8d913e9817717990603aadeca07aab9ddbb10a30f167cbfd8d3a3ccb60
|
||||
F test/update2.test 5e67667e1c54017d964e626db765cf8bedcf87483c184f4c575bdb8c1dd2313e
|
||||
F test/upsert1.test 934315888a04b4e119ebb6abf558d92bf01d9f94fc8ff0bbc1c7c6015005340f
|
||||
F test/upsert1.test d587db593f131e112a98a05685c418e0eacc28df5905403e4ca04cd74c39a3fc
|
||||
F test/upsert2.test 9c3cdbb1a890227f6504ce4b0e3de68f4cdfa16bb21d8641208a9239896c5a09
|
||||
F test/upsert3.test 88d7d590a1948a9cb6eac1b54b0642f67a9f35a1fc0f19b200e97d5d39e3179c
|
||||
F test/upsert4.test c70b9dd9ae9952d8942ae2558dcecdeb1128097b1d03a22d8ae42660112ffc73
|
||||
F test/upsert4.test 25d2a1da92f149331ae0c51ca6e3eee78189577585eab92de149900d62994fa5
|
||||
F test/upsertfault.test f21ca47740841fdb4d61acfa7b17646d773e67724fe8c185b71c018db8a94b35
|
||||
F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
|
||||
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
|
||||
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
|
||||
@@ -1579,41 +1585,41 @@ F test/walrofault.test c70cb6e308c443867701856cce92ad8288cd99488fa52afab77cca6cf
|
||||
F test/walshared.test 0befc811dcf0b287efae21612304d15576e35417
|
||||
F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f
|
||||
F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747
|
||||
F test/where.test f0c325563acde44f2c4ea6ba348e9e29f7121757
|
||||
F test/where.test f19ea3fa31c425b04af42c8b192a5b595ee84498df8d27dcd79ec043b25fbbfb
|
||||
F test/where2.test 478d2170637b9211f593120648858593bf2445a1
|
||||
F test/where3.test 54cdeb02157acc979de41530b804ae7b09552bf1
|
||||
F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c
|
||||
F test/where4.test 4a371bfcc607f41d233701bdec33ac2972908ba8
|
||||
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
|
||||
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
|
||||
F test/where7.test f520bcec2c3d12dc4615623b06b2aec7c2d67e94
|
||||
F test/where7.test e579da972eb3372edc9de850efc221848c763f9e4feafc8426d84a4453b92b23
|
||||
F test/where8.test 461ca40265ed996a6305da99bb024b0e41602bb586acf544c08f95922358e49f
|
||||
F test/where9.test 729c3ba9b47e8f9f1aab96bae7dad2a524f1d1a2
|
||||
F test/where9.test ad2ddb339d10d324763c3da60502b8631f15a2397b869192fbd4e82f40e167d3
|
||||
F test/whereA.test 6c6a420ca7d313242f9b1bd471dc80e4d0f8323700ba9c78df0bb843d4daa3b4
|
||||
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
|
||||
F test/whereC.test cae295158703cb3fc23bf1a108a9ab730efff0f6
|
||||
F test/whereD.test 711d4df58d6d4fb9b3f5ce040b818564198be002
|
||||
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
|
||||
F test/whereF.test 3d9412b1199d3e2bed34fcb76b4c48d0bf4df95d27e3f8dd27b6f8b4716d0d89
|
||||
F test/whereG.test dde4c52a97385a55be6a7cd46be8373f0cf35501
|
||||
F test/whereG.test 0158783235a6dd82fc0e37652b8522b186b9510594ac0a4bff0c4101b4396a52
|
||||
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
|
||||
F test/whereI.test eab5b226bbc344ac70d7dc09b963a064860ae6d7
|
||||
F test/whereJ.test 55a3221706a7ab706293f17cc8f96da563bf0767
|
||||
F test/whereI.test b7769ee8dbefd987fb266715fee887f05f9ff180016b06fca7fa402df739193b
|
||||
F test/whereJ.test 88287550f6ee604422403b053455b1ad894eeaa5c35d348532dfa1439286cb9a
|
||||
F test/whereK.test f8e3cf26a8513ecc7f514f54df9f0572c046c42b
|
||||
F test/wherefault.test 1374c3aa198388925246475f84ad4cd5f9528864
|
||||
F test/wherelfault.test 9012e4ef5259058b771606616bd007af5d154e64cc25fa9fd4170f6411db44e3
|
||||
F test/wherelimit.test 1dee70c9cc147330156d75e23de88f771e624998b03ae316cb64e1d249f129d8
|
||||
F test/wherelimit.test 592081800806d297dd7449b1030c863d2883d6d42901837ccd2e5a9bd962edb0
|
||||
F test/wherelimit2.test be78ba3aa1831c6358fd7d5b9809bfd520f0c2a7d63a295e8f182e140ff137c3
|
||||
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
|
||||
F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2aeee74
|
||||
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
|
||||
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
|
||||
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
|
||||
F test/with1.test ca08e291249a810a2ec9b72ceef5575e07d5925b360fcf6652ae6fe06ac4dced
|
||||
F test/with1.test 58475190cd8caaeebea8cfeb2a264ec97a0c492b8ffe9ad20cefbb23df462f96
|
||||
F test/with2.test e0030e2f0267a910d6c0e4f46f2dfe941c1cc0d4f659ba69b3597728e7e8f1ab
|
||||
F test/with3.test e71604a0e53cba82bc04c703987cb1d6751ec0b6
|
||||
F test/with3.test 5e8ce2c585170bbbc0544e2a01a4941fa0be173ba5265e5c92eb588cd99a232d
|
||||
F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f198205
|
||||
F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64
|
||||
F test/without_rowid1.test 1cb47a1a5ba5b2946f18703fabf9fb2a237b0a8180538793ecbaed834d0df765
|
||||
F test/without_rowid1.test 533add9100255e4cc430d371b3ecfb79f11f956b86c3a1b9d34413bf8e482d8f
|
||||
F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99
|
||||
F test/without_rowid3.test 2724c787a51a5dce09d078453a758117b4b728f1
|
||||
F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a
|
||||
@@ -1643,8 +1649,8 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
|
||||
F tool/lemon.c 3b5fb488c6b27e7cc4e3191cc1014af6d6250786dcae02991fb0df0d598fc5df
|
||||
F tool/lempar.c 468a155e8729cfbccfe1d85bf60d064f1dab76167a51149ec5c7928a2de63953
|
||||
F tool/lemon.c 33892e2a243865f73e6c6e7cecce3c6eb4bb95db4a3d9d86d146c8064feb92fd
|
||||
F tool/lempar.c bf7db78e7213f1d51516710483eab506fd52bf632c7abfb3e2e9b885c90c03e1
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
|
||||
@@ -1652,10 +1658,10 @@ F tool/max-limits.c cbb635fbb37ae4d05f240bfb5b5270bb63c54439
|
||||
F tool/mkautoconfamal.sh 422fc365358a2e92876ffc62971a0ff28ed472fc8bcf9de0df921c736fdeca5e
|
||||
F tool/mkccode.tcl 86463e68ce9c15d3041610fedd285ce32a5cf7a58fc88b3202b8b76837650dbe x
|
||||
F tool/mkctimec.tcl dd183b73ae1c28249669741c250525f0407e579a70482371668fd5f130d9feb3
|
||||
F tool/mkkeywordhash.c 98d7ce6f8ed32f23d6b30fbde6d9ed466d4ae38a9f8add20a36bebd3df56171c
|
||||
F tool/mkkeywordhash.c 20f366ad3794e1db42e333a6f35fa41a024f2e3528579c9d58eb13eaa3ab4913
|
||||
F tool/mkmsvcmin.tcl cad0c7b54d7dd92bc87d59f36d4cc4f070eb2e625f14159dc2f5c4204e6a13ea
|
||||
F tool/mkopcodec.tcl d1b6362bd3aa80d5520d4d6f3765badf01f6c43c
|
||||
F tool/mkopcodeh.tcl 4ee2a30ccbd900dc4d5cdb61bdab87cd2166cd2affcc78c9cc0b8d22a65b2eee
|
||||
F tool/mkopcodeh.tcl 17d1ccc05a926e19e3a9679ea3e4d1aaa15ba753e2fa7363e6e81c80e0ef8b86
|
||||
F tool/mkopts.tcl 680f785fdb09729fd9ac50632413da4eadbdf9071535e3f26d03795828ab07fa
|
||||
F tool/mkpragmatab.tcl 2144bc8550a6471a029db262a132d2df4b9e0db61b90398bf64f5b7b3f8d92cd
|
||||
F tool/mkshellc.tcl 1f45770aea226ac093a9c72f718efbb88a2a2833409ec2e1c4cecae4202626f5
|
||||
@@ -1682,14 +1688,14 @@ F tool/showstat4.c 0682ebea7abf4d3657f53c4a243f2e7eab48eab344ed36a94bb75dcd19a5c
|
||||
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 4bfd19aad7eb3ce0372ef0255f58035e0bba4ff5e9acfd763a10c6fb365c8dec
|
||||
F tool/speed-check.sh 4ff9b095cf1a7643f0264e7fb7d23f0b12b7cce587a9de315877c378e90eeaf4
|
||||
F tool/speed-check.sh 27c7fe178d5b2f7c90a04a127907acda0bfe637fa85b13c43e03e5ed39b008b6
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl 3efcd4240b738f6bb2b5af0aea7e1e0ef9bc1c61654f645076cec883030b710c
|
||||
F tool/sqldiff.c 30879bbc8de686df4624e86adce2d8981f500904c1cfb55b5d1eea2ffd9341eb
|
||||
F tool/sqldiff.c 579d7e4e42c30a963781654c87d2868823120b55d59e16ca77b0edbab0218713
|
||||
F tool/sqlite3_analyzer.c.in 7eeaae8b0d7577662acaabbb11107af0659d1b41bc1dfdd4d91422de27127968
|
||||
F tool/sqltclsh.c.in 1bcc2e9da58fadf17b0bf6a50e68c1159e602ce057210b655d50bad5aaaef898
|
||||
F tool/sqltclsh.tcl 862f4cf1418df5e1315b5db3b5ebe88969e2a784525af5fbf9596592f14ed848
|
||||
@@ -1724,7 +1730,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P d1906689abdb685f78aa97bca4bf301204d12846016d27bc86dcc9ce2b024d24
|
||||
R 18734526551b7a3f2bbebfc4bb6f5573
|
||||
P e336cf00486bdc0ec04ecded2b7c874d73a87e6aba3544e3678bedfb9a4af3b6
|
||||
R 8f6289962dafd62afd0dcc62419aace8
|
||||
T *branch * align8-fix
|
||||
T *sym-align8-fix *
|
||||
T -sym-trunk *
|
||||
U drh
|
||||
Z 95143f322f298a42bef8b7fc14836f21
|
||||
Z b4fcb02096c47b5fe0c3d849fd18fe13
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
131ed95e1452a5b0d92341c48a5d3915b328ccfce2cf605f702428ae7ee3e21b
|
||||
1b807b51cdf455b4f54216b73fd22bbc90f94e24222401e045f88cfd27f487e3
|
||||
+14
-1
@@ -158,7 +158,7 @@ static void attachFunc(
|
||||
sqlite3_free( zPath );
|
||||
db->nDb++;
|
||||
}
|
||||
db->skipBtreeMutex = 0;
|
||||
db->noSharedCache = 0;
|
||||
if( rc==SQLITE_CONSTRAINT ){
|
||||
rc = SQLITE_ERROR;
|
||||
zErrDyn = sqlite3MPrintf(db, "database is already attached");
|
||||
@@ -230,6 +230,7 @@ static void attachFunc(
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3BtreeEnterAll(db);
|
||||
db->init.iDb = 0;
|
||||
db->mDbFlags &= ~(DBFLAG_SchemaKnownOk);
|
||||
rc = sqlite3Init(db, &zErrDyn);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
assert( zErrDyn==0 || rc!=SQLITE_OK );
|
||||
@@ -604,6 +605,18 @@ int sqlite3FixTriggerStep(
|
||||
if( sqlite3FixExprList(pFix, pStep->pExprList) ){
|
||||
return 1;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_UPSERT
|
||||
if( pStep->pUpsert ){
|
||||
Upsert *pUp = pStep->pUpsert;
|
||||
if( sqlite3FixExprList(pFix, pUp->pUpsertTarget)
|
||||
|| sqlite3FixExpr(pFix, pUp->pUpsertTargetWhere)
|
||||
|| sqlite3FixExprList(pFix, pUp->pUpsertSet)
|
||||
|| sqlite3FixExpr(pFix, pUp->pUpsertWhere)
|
||||
){
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pStep = pStep->pNext;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -150,6 +150,7 @@ void sqlite3AuthRead(
|
||||
int iDb; /* The index of the database the expression refers to */
|
||||
int iCol; /* Index of column in table */
|
||||
|
||||
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
|
||||
if( db->xAuth==0 ) return;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pSchema);
|
||||
if( iDb<0 ){
|
||||
@@ -158,7 +159,6 @@ void sqlite3AuthRead(
|
||||
return;
|
||||
}
|
||||
|
||||
assert( pExpr->op==TK_COLUMN || pExpr->op==TK_TRIGGER );
|
||||
if( pExpr->op==TK_TRIGGER ){
|
||||
pTab = pParse->pTriggerTab;
|
||||
}else{
|
||||
|
||||
+3
-3
@@ -195,10 +195,10 @@ static void SQLITE_NOINLINE btreeEnterAll(sqlite3 *db){
|
||||
skipOk = 0;
|
||||
}
|
||||
}
|
||||
db->skipBtreeMutex = skipOk;
|
||||
db->noSharedCache = skipOk;
|
||||
}
|
||||
void sqlite3BtreeEnterAll(sqlite3 *db){
|
||||
if( db->skipBtreeMutex==0 ) btreeEnterAll(db);
|
||||
if( db->noSharedCache==0 ) btreeEnterAll(db);
|
||||
}
|
||||
static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
|
||||
int i;
|
||||
@@ -210,7 +210,7 @@ static void SQLITE_NOINLINE btreeLeaveAll(sqlite3 *db){
|
||||
}
|
||||
}
|
||||
void sqlite3BtreeLeaveAll(sqlite3 *db){
|
||||
if( db->skipBtreeMutex==0 ) btreeLeaveAll(db);
|
||||
if( db->noSharedCache==0 ) btreeLeaveAll(db);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
|
||||
+182
-30
@@ -864,7 +864,11 @@ static int btreeRestoreCursorPosition(BtCursor *pCur){
|
||||
** back to where it ought to be if this routine returns true.
|
||||
*/
|
||||
int sqlite3BtreeCursorHasMoved(BtCursor *pCur){
|
||||
return pCur->eState!=CURSOR_VALID;
|
||||
assert( EIGHT_BYTE_ALIGNMENT(pCur)
|
||||
|| pCur==sqlite3BtreeFakeValidCursor() );
|
||||
assert( offsetof(BtCursor, eState)==0 );
|
||||
assert( sizeof(pCur->eState)==1 );
|
||||
return CURSOR_VALID != *(u8*)pCur;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2972,6 +2976,10 @@ static void setDefaultSyncFlag(BtShared *pBt, u8 safety_level){
|
||||
# define setDefaultSyncFlag(pBt,safety_level)
|
||||
#endif
|
||||
|
||||
/* Forward declaration */
|
||||
static int newDatabase(BtShared*);
|
||||
|
||||
|
||||
/*
|
||||
** Get a reference to pPage1 of the database file. This will
|
||||
** also acquire a readlock on that file.
|
||||
@@ -3003,6 +3011,9 @@ static int lockBtree(BtShared *pBt){
|
||||
if( nPage==0 || memcmp(24+(u8*)pPage1->aData, 92+(u8*)pPage1->aData,4)!=0 ){
|
||||
nPage = nPageFile;
|
||||
}
|
||||
if( (pBt->db->flags & SQLITE_ResetDatabase)!=0 ){
|
||||
nPage = 0;
|
||||
}
|
||||
if( nPage>0 ){
|
||||
u32 pageSize;
|
||||
u32 usableSize;
|
||||
@@ -6219,7 +6230,9 @@ static int clearCell(
|
||||
if( pInfo->nLocal==pInfo->nPayload ){
|
||||
return SQLITE_OK; /* No overflow pages. Return without doing anything */
|
||||
}
|
||||
if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){
|
||||
testcase( pCell + pInfo->nSize == pPage->aDataEnd );
|
||||
testcase( pCell + (pInfo->nSize-1) == pPage->aDataEnd );
|
||||
if( pCell + pInfo->nSize > pPage->aDataEnd ){
|
||||
/* Cell extends past end of page */
|
||||
return SQLITE_CORRUPT_PAGE(pPage);
|
||||
}
|
||||
@@ -8145,6 +8158,94 @@ static int balance(BtCursor *pCur){
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Overwrite content from pX into pDest. Only do the write if the
|
||||
** content is different from what is already there.
|
||||
*/
|
||||
static int btreeOverwriteContent(
|
||||
MemPage *pPage, /* MemPage on which writing will occur */
|
||||
u8 *pDest, /* Pointer to the place to start writing */
|
||||
const BtreePayload *pX, /* Source of data to write */
|
||||
int iOffset, /* Offset of first byte to write */
|
||||
int iAmt /* Number of bytes to be written */
|
||||
){
|
||||
int nData = pX->nData - iOffset;
|
||||
if( nData<=0 ){
|
||||
/* Overwritting with zeros */
|
||||
int i;
|
||||
for(i=0; i<iAmt && pDest[i]==0; i++){}
|
||||
if( i<iAmt ){
|
||||
int rc = sqlite3PagerWrite(pPage->pDbPage);
|
||||
if( rc ) return rc;
|
||||
memset(pDest + i, 0, iAmt - i);
|
||||
}
|
||||
}else{
|
||||
if( nData<iAmt ){
|
||||
/* Mixed read data and zeros at the end. Make a recursive call
|
||||
** to write the zeros then fall through to write the real data */
|
||||
int rc = btreeOverwriteContent(pPage, pDest+nData, pX, iOffset+nData,
|
||||
iAmt-nData);
|
||||
if( rc ) return rc;
|
||||
iAmt = nData;
|
||||
}
|
||||
if( memcmp(pDest, ((u8*)pX->pData) + iOffset, iAmt)!=0 ){
|
||||
int rc = sqlite3PagerWrite(pPage->pDbPage);
|
||||
if( rc ) return rc;
|
||||
memcpy(pDest, ((u8*)pX->pData) + iOffset, iAmt);
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Overwrite the cell that cursor pCur is pointing to with fresh content
|
||||
** contained in pX.
|
||||
*/
|
||||
static int btreeOverwriteCell(BtCursor *pCur, const BtreePayload *pX){
|
||||
int iOffset; /* Next byte of pX->pData to write */
|
||||
int nTotal = pX->nData + pX->nZero; /* Total bytes of to write */
|
||||
int rc; /* Return code */
|
||||
MemPage *pPage = pCur->pPage; /* Page being written */
|
||||
BtShared *pBt; /* Btree */
|
||||
Pgno ovflPgno; /* Next overflow page to write */
|
||||
u32 ovflPageSize; /* Size to write on overflow page */
|
||||
|
||||
if( pCur->info.pPayload + pCur->info.nLocal > pPage->aDataEnd ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
/* Overwrite the local portion first */
|
||||
rc = btreeOverwriteContent(pPage, pCur->info.pPayload, pX,
|
||||
0, pCur->info.nLocal);
|
||||
if( rc ) return rc;
|
||||
if( pCur->info.nLocal==nTotal ) return SQLITE_OK;
|
||||
|
||||
/* Now overwrite the overflow pages */
|
||||
iOffset = pCur->info.nLocal;
|
||||
assert( nTotal>=0 );
|
||||
assert( iOffset>=0 );
|
||||
ovflPgno = get4byte(pCur->info.pPayload + iOffset);
|
||||
pBt = pPage->pBt;
|
||||
ovflPageSize = pBt->usableSize - 4;
|
||||
do{
|
||||
rc = btreeGetPage(pBt, ovflPgno, &pPage, 0);
|
||||
if( rc ) return rc;
|
||||
if( sqlite3PagerPageRefcount(pPage->pDbPage)!=1 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}else{
|
||||
if( iOffset+ovflPageSize<(u32)nTotal ){
|
||||
ovflPgno = get4byte(pPage->aData);
|
||||
}else{
|
||||
ovflPageSize = nTotal - iOffset;
|
||||
}
|
||||
rc = btreeOverwriteContent(pPage, pPage->aData+4, pX,
|
||||
iOffset, ovflPageSize);
|
||||
}
|
||||
sqlite3PagerUnref(pPage->pDbPage);
|
||||
if( rc ) return rc;
|
||||
iOffset += ovflPageSize;
|
||||
}while( iOffset<nTotal );
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Insert a new record into the BTree. The content of the new record
|
||||
@@ -8235,35 +8336,86 @@ int sqlite3BtreeInsert(
|
||||
invalidateIncrblobCursors(p, pCur->pgnoRoot, pX->nKey, 0);
|
||||
|
||||
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
|
||||
** to a row with the same key as the new entry being inserted. */
|
||||
assert( (flags & BTREE_SAVEPOSITION)==0 ||
|
||||
((pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey) );
|
||||
** to a row with the same key as the new entry being inserted.
|
||||
*/
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( flags & BTREE_SAVEPOSITION ){
|
||||
assert( pCur->curFlags & BTCF_ValidNKey );
|
||||
assert( pX->nKey==pCur->info.nKey );
|
||||
assert( pCur->info.nSize!=0 );
|
||||
assert( loc==0 );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* If the cursor is currently on the last row and we are appending a
|
||||
** new row onto the end, set the "loc" to avoid an unnecessary
|
||||
** btreeMoveto() call */
|
||||
/* On the other hand, BTREE_SAVEPOSITION==0 does not imply
|
||||
** that the cursor is not pointing to a row to be overwritten.
|
||||
** So do a complete check.
|
||||
*/
|
||||
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && pX->nKey==pCur->info.nKey ){
|
||||
loc = 0;
|
||||
/* The cursor is pointing to the entry that is to be
|
||||
** overwritten */
|
||||
assert( pX->nData>=0 && pX->nZero>=0 );
|
||||
if( pCur->info.nSize!=0
|
||||
&& pCur->info.nPayload==(u32)pX->nData+pX->nZero
|
||||
){
|
||||
/* New entry is the same size as the old. Do an overwrite */
|
||||
return btreeOverwriteCell(pCur, pX);
|
||||
}
|
||||
assert( loc==0 );
|
||||
}else if( loc==0 ){
|
||||
/* The cursor is *not* pointing to the cell to be overwritten, nor
|
||||
** to an adjacent cell. Move the cursor so that it is pointing either
|
||||
** to the cell to be overwritten or an adjacent cell.
|
||||
*/
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, 0, pX->nKey, flags!=0, &loc);
|
||||
if( rc ) return rc;
|
||||
}
|
||||
}else if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
|
||||
if( pX->nMem ){
|
||||
UnpackedRecord r;
|
||||
r.pKeyInfo = pCur->pKeyInfo;
|
||||
r.aMem = pX->aMem;
|
||||
r.nField = pX->nMem;
|
||||
r.default_rc = 0;
|
||||
r.errCode = 0;
|
||||
r.r1 = 0;
|
||||
r.r2 = 0;
|
||||
r.eqSeen = 0;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
|
||||
}else{
|
||||
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
|
||||
}else{
|
||||
/* This is an index or a WITHOUT ROWID table */
|
||||
|
||||
/* If BTREE_SAVEPOSITION is set, the cursor must already be pointing
|
||||
** to a row with the same key as the new entry being inserted.
|
||||
*/
|
||||
assert( (flags & BTREE_SAVEPOSITION)==0 || loc==0 );
|
||||
|
||||
/* If the cursor is not already pointing either to the cell to be
|
||||
** overwritten, or if a new cell is being inserted, if the cursor is
|
||||
** not pointing to an immediately adjacent cell, then move the cursor
|
||||
** so that it does.
|
||||
*/
|
||||
if( loc==0 && (flags & BTREE_SAVEPOSITION)==0 ){
|
||||
if( pX->nMem ){
|
||||
UnpackedRecord r;
|
||||
r.pKeyInfo = pCur->pKeyInfo;
|
||||
r.aMem = pX->aMem;
|
||||
r.nField = pX->nMem;
|
||||
r.default_rc = 0;
|
||||
r.errCode = 0;
|
||||
r.r1 = 0;
|
||||
r.r2 = 0;
|
||||
r.eqSeen = 0;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pCur, &r, 0, flags!=0, &loc);
|
||||
}else{
|
||||
rc = btreeMoveto(pCur, pX->pKey, pX->nKey, flags!=0, &loc);
|
||||
}
|
||||
if( rc ) return rc;
|
||||
}
|
||||
if( rc ) return rc;
|
||||
|
||||
/* If the cursor is currently pointing to an entry to be overwritten
|
||||
** and the new content is the same as as the old, then use the
|
||||
** overwrite optimization.
|
||||
*/
|
||||
if( loc==0 ){
|
||||
getCellInfo(pCur);
|
||||
if( pCur->info.nKey==pX->nKey ){
|
||||
BtreePayload x2;
|
||||
x2.pData = pX->pKey;
|
||||
x2.nData = pX->nKey;
|
||||
x2.nZero = 0;
|
||||
return btreeOverwriteCell(pCur, &x2);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) );
|
||||
|
||||
@@ -9102,14 +9254,14 @@ static void checkAppendMsg(
|
||||
pCheck->nErr++;
|
||||
va_start(ap, zFormat);
|
||||
if( pCheck->errMsg.nChar ){
|
||||
sqlite3StrAccumAppend(&pCheck->errMsg, "\n", 1);
|
||||
sqlite3_str_append(&pCheck->errMsg, "\n", 1);
|
||||
}
|
||||
if( pCheck->zPfx ){
|
||||
sqlite3XPrintf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
|
||||
sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2);
|
||||
}
|
||||
sqlite3VXPrintf(&pCheck->errMsg, zFormat, ap);
|
||||
sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap);
|
||||
va_end(ap);
|
||||
if( pCheck->errMsg.accError==STRACCUM_NOMEM ){
|
||||
if( pCheck->errMsg.accError==SQLITE_NOMEM ){
|
||||
pCheck->mallocFailed = 1;
|
||||
}
|
||||
}
|
||||
@@ -9693,11 +9845,11 @@ integrity_ck_cleanup:
|
||||
sqlite3PageFree(sCheck.heap);
|
||||
sqlite3_free(sCheck.aPgRef);
|
||||
if( sCheck.mallocFailed ){
|
||||
sqlite3StrAccumReset(&sCheck.errMsg);
|
||||
sqlite3_str_reset(&sCheck.errMsg);
|
||||
sCheck.nErr++;
|
||||
}
|
||||
*pnErr = sCheck.nErr;
|
||||
if( sCheck.nErr==0 ) sqlite3StrAccumReset(&sCheck.errMsg);
|
||||
if( sCheck.nErr==0 ) sqlite3_str_reset(&sCheck.errMsg);
|
||||
/* Make sure this analysis did not leave any unref() pages. */
|
||||
assert( nRef==sqlite3PagerRefcount(pBt->pPager) );
|
||||
sqlite3BtreeLeave(p);
|
||||
|
||||
+18
-3
@@ -259,13 +259,28 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags);
|
||||
** entry in either an index or table btree.
|
||||
**
|
||||
** Index btrees (used for indexes and also WITHOUT ROWID tables) contain
|
||||
** an arbitrary key and no data. These btrees have pKey,nKey set to their
|
||||
** key and pData,nData,nZero set to zero.
|
||||
** an arbitrary key and no data. These btrees have pKey,nKey set to the
|
||||
** key and the pData,nData,nZero fields are uninitialized. The aMem,nMem
|
||||
** fields give an array of Mem objects that are a decomposition of the key.
|
||||
** The nMem field might be zero, indicating that no decomposition is available.
|
||||
**
|
||||
** Table btrees (used for rowid tables) contain an integer rowid used as
|
||||
** the key and passed in the nKey field. The pKey field is zero.
|
||||
** pData,nData hold the content of the new entry. nZero extra zero bytes
|
||||
** are appended to the end of the content when constructing the entry.
|
||||
** The aMem,nMem fields are uninitialized for table btrees.
|
||||
**
|
||||
** Field usage summary:
|
||||
**
|
||||
** Table BTrees Index Btrees
|
||||
**
|
||||
** pKey always NULL encoded key
|
||||
** nKey the ROWID length of pKey
|
||||
** pData data not used
|
||||
** aMem not used decomposed key value
|
||||
** nMem not used entries in aMem
|
||||
** nData length of pData not used
|
||||
** nZero extra zeros after pData not used
|
||||
**
|
||||
** This object is used to pass information into sqlite3BtreeInsert(). The
|
||||
** same information used to be passed as five separate parameters. But placing
|
||||
@@ -276,7 +291,7 @@ int sqlite3BtreeDelete(BtCursor*, u8 flags);
|
||||
struct BtreePayload {
|
||||
const void *pKey; /* Key content for indexes. NULL for tables */
|
||||
sqlite3_int64 nKey; /* Size of pKey for indexes. PRIMARY KEY for tabs */
|
||||
const void *pData; /* Data for tables. NULL for indexes */
|
||||
const void *pData; /* Data for tables. */
|
||||
sqlite3_value *aMem; /* First of nMem value in the unpacked pKey */
|
||||
u16 nMem; /* Number of aMem[] value. Might be zero */
|
||||
int nData; /* Size of pData. 0 if none. */
|
||||
|
||||
+24
-14
@@ -343,24 +343,27 @@ Table *sqlite3LocateTable(
|
||||
const char *zDbase /* Name of the database. Might be NULL */
|
||||
){
|
||||
Table *p;
|
||||
sqlite3 *db = pParse->db;
|
||||
|
||||
/* Read the database schema. If an error occurs, leave an error message
|
||||
** and code in pParse and return NULL. */
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
if( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0
|
||||
&& SQLITE_OK!=sqlite3ReadSchema(pParse)
|
||||
){
|
||||
return 0;
|
||||
}
|
||||
|
||||
p = sqlite3FindTable(pParse->db, zName, zDbase);
|
||||
p = sqlite3FindTable(db, zName, zDbase);
|
||||
if( p==0 ){
|
||||
const char *zMsg = flags & LOCATE_VIEW ? "no such view" : "no such table";
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( sqlite3FindDbName(pParse->db, zDbase)<1 ){
|
||||
if( sqlite3FindDbName(db, zDbase)<1 ){
|
||||
/* If zName is the not the name of a table in the schema created using
|
||||
** CREATE, then check to see if it is the name of an virtual table that
|
||||
** can be an eponymous virtual table. */
|
||||
Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
|
||||
Module *pMod = (Module*)sqlite3HashFind(&db->aModule, zName);
|
||||
if( pMod==0 && sqlite3_strnicmp(zName, "pragma_", 7)==0 ){
|
||||
pMod = sqlite3PragmaVtabRegister(pParse->db, zName);
|
||||
pMod = sqlite3PragmaVtabRegister(db, zName);
|
||||
}
|
||||
if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
|
||||
return pMod->pEpoTab;
|
||||
@@ -525,6 +528,7 @@ void sqlite3ResetOneSchema(sqlite3 *db, int iDb){
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
DbSetProperty(db, iDb, DB_ResetWanted);
|
||||
DbSetProperty(db, 1, DB_ResetWanted);
|
||||
db->mDbFlags &= ~DBFLAG_SchemaKnownOk;
|
||||
}
|
||||
|
||||
if( db->nSchemaLock==0 ){
|
||||
@@ -550,7 +554,7 @@ void sqlite3ResetAllSchemasOfConnection(sqlite3 *db){
|
||||
sqlite3SchemaClear(pDb->pSchema);
|
||||
}
|
||||
}
|
||||
db->mDbFlags &= ~DBFLAG_SchemaChange;
|
||||
db->mDbFlags &= ~(DBFLAG_SchemaChange|DBFLAG_SchemaKnownOk);
|
||||
sqlite3VtabUnlockList(db);
|
||||
sqlite3BtreeLeaveAll(db);
|
||||
sqlite3CollapseDatabaseArray(db);
|
||||
@@ -2839,6 +2843,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0); VdbeCoverage(v);
|
||||
regRecord = sqlite3GetTempReg(pParse);
|
||||
sqlite3MultiWrite(pParse);
|
||||
|
||||
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
|
||||
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
|
||||
@@ -2852,12 +2857,13 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
|
||||
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_SorterSort, iSorter, 0); VdbeCoverage(v);
|
||||
if( IsUniqueIndex(pIndex) ){
|
||||
int j2 = sqlite3VdbeCurrentAddr(v) + 3;
|
||||
sqlite3VdbeGoto(v, j2);
|
||||
int j2 = sqlite3VdbeGoto(v, 1);
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeVerifyAbortable(v, OE_Abort);
|
||||
sqlite3VdbeAddOp4Int(v, OP_SorterCompare, iSorter, j2, regRecord,
|
||||
pIndex->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3UniqueConstraint(pParse, OE_Abort, pIndex);
|
||||
sqlite3VdbeJumpHere(v, j2);
|
||||
}else{
|
||||
addr2 = sqlite3VdbeCurrentAddr(v);
|
||||
}
|
||||
@@ -3020,7 +3026,11 @@ void sqlite3CreateIndex(
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
&& sqlite3UserAuthTable(pTab->zName)==0
|
||||
#endif
|
||||
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0 ){
|
||||
#ifdef SQLITE_ALLOW_SQLITE_MASTER_INDEX
|
||||
&& sqlite3StrICmp(&pTab->zName[7],"master")!=0
|
||||
#endif
|
||||
&& sqlite3StrNICmp(&pTab->zName[7],"altertab_",9)!=0
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName);
|
||||
goto exit_create_index;
|
||||
}
|
||||
@@ -4199,16 +4209,16 @@ void sqlite3UniqueConstraint(
|
||||
|
||||
sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
|
||||
if( pIdx->aColExpr ){
|
||||
sqlite3XPrintf(&errMsg, "index '%q'", pIdx->zName);
|
||||
sqlite3_str_appendf(&errMsg, "index '%q'", pIdx->zName);
|
||||
}else{
|
||||
for(j=0; j<pIdx->nKeyCol; j++){
|
||||
char *zCol;
|
||||
assert( pIdx->aiColumn[j]>=0 );
|
||||
zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
|
||||
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
|
||||
sqlite3StrAccumAppendAll(&errMsg, pTab->zName);
|
||||
sqlite3StrAccumAppend(&errMsg, ".", 1);
|
||||
sqlite3StrAccumAppendAll(&errMsg, zCol);
|
||||
if( j ) sqlite3_str_append(&errMsg, ", ", 2);
|
||||
sqlite3_str_appendall(&errMsg, pTab->zName);
|
||||
sqlite3_str_append(&errMsg, ".", 1);
|
||||
sqlite3_str_appendall(&errMsg, zCol);
|
||||
}
|
||||
}
|
||||
zErr = sqlite3StrAccumFinish(&errMsg);
|
||||
|
||||
@@ -406,10 +406,12 @@ FuncDef *sqlite3FindFunction(
|
||||
if( createFlag && bestScore<FUNC_PERFECT_MATCH &&
|
||||
(pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){
|
||||
FuncDef *pOther;
|
||||
u8 *z;
|
||||
pBest->zName = (const char*)&pBest[1];
|
||||
pBest->nArg = (u16)nArg;
|
||||
pBest->funcFlags = enc;
|
||||
memcpy((char*)&pBest[1], zName, nName+1);
|
||||
for(z=(u8*)pBest->zName; *z; z++) *z = sqlite3UpperToLower[*z];
|
||||
pOther = (FuncDef*)sqlite3HashInsert(&db->aFunc, pBest->zName, pBest);
|
||||
if( pOther==pBest ){
|
||||
sqlite3DbFree(db, pBest);
|
||||
|
||||
+9
-5
@@ -343,7 +343,7 @@ void sqlite3DeleteFrom(
|
||||
goto delete_from_cleanup;
|
||||
}
|
||||
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
sqlite3BeginWriteOperation(pParse, bComplex, iDb);
|
||||
|
||||
/* If we are trying to delete from a view, realize that view into
|
||||
** an ephemeral table.
|
||||
@@ -447,6 +447,7 @@ void sqlite3DeleteFrom(
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
assert( IsVirtual(pTab)==0 || eOnePass!=ONEPASS_MULTI );
|
||||
assert( IsVirtual(pTab) || bComplex || eOnePass!=ONEPASS_OFF );
|
||||
if( eOnePass!=ONEPASS_SINGLE ) sqlite3MultiWrite(pParse);
|
||||
|
||||
/* Keep track of the number of rows to be deleted */
|
||||
if( memCnt ){
|
||||
@@ -552,13 +553,16 @@ void sqlite3DeleteFrom(
|
||||
if( IsVirtual(pTab) ){
|
||||
const char *pVTab = (const char *)sqlite3GetVTable(db, pTab);
|
||||
sqlite3VtabMakeWritable(pParse, pTab);
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
|
||||
sqlite3MayAbort(pParse);
|
||||
if( eOnePass==ONEPASS_SINGLE && sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
if( eOnePass==ONEPASS_SINGLE ){
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iTabCur);
|
||||
if( sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp4(v, OP_VUpdate, 0, 1, iKey, pVTab, P4_VTAB);
|
||||
sqlite3VdbeChangeP5(v, OE_Abort);
|
||||
}else
|
||||
#endif
|
||||
{
|
||||
|
||||
+14
-22
@@ -2410,11 +2410,8 @@ int sqlite3FindInIndex(
|
||||
if( colUsed==(MASKBIT(nExpr)-1) ){
|
||||
/* If we reach this point, that means the index pIdx is usable */
|
||||
int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0,
|
||||
sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName),
|
||||
P4_DYNAMIC);
|
||||
#endif
|
||||
ExplainQueryPlan((pParse, 0,
|
||||
"USING INDEX %s FOR IN-OPERATOR",pIdx->zName));
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
@@ -2609,17 +2606,6 @@ int sqlite3CodeSubselect(
|
||||
jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
if( pParse->explain==2 ){
|
||||
char *zMsg = sqlite3MPrintf(pParse->db, "EXECUTE %s%s SUBQUERY %d",
|
||||
jmpIfDynamic>=0?"":"CORRELATED ",
|
||||
pExpr->op==TK_IN?"LIST":"SCALAR",
|
||||
pParse->iNextSelectId
|
||||
);
|
||||
sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
|
||||
}
|
||||
#endif
|
||||
|
||||
switch( pExpr->op ){
|
||||
case TK_IN: {
|
||||
int addr; /* Address of OP_OpenEphemeral instruction */
|
||||
@@ -2657,6 +2643,9 @@ int sqlite3CodeSubselect(
|
||||
Select *pSelect = pExpr->x.pSelect;
|
||||
ExprList *pEList = pSelect->pEList;
|
||||
|
||||
ExplainQueryPlan((pParse, 1, "%sLIST SUBQUERY",
|
||||
jmpIfDynamic>=0?"":"CORRELATED "
|
||||
));
|
||||
assert( !isRowid );
|
||||
/* If the LHS and RHS of the IN operator do not match, that
|
||||
** error will have been caught long before we reach this point. */
|
||||
@@ -2698,7 +2687,6 @@ int sqlite3CodeSubselect(
|
||||
ExprList *pList = pExpr->x.pList;
|
||||
struct ExprList_item *pItem;
|
||||
int r1, r2, r3;
|
||||
|
||||
affinity = sqlite3ExprAffinity(pLeft);
|
||||
if( !affinity ){
|
||||
affinity = SQLITE_AFF_BLOB;
|
||||
@@ -2779,6 +2767,8 @@ int sqlite3CodeSubselect(
|
||||
assert( ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
|
||||
pSel = pExpr->x.pSelect;
|
||||
ExplainQueryPlan((pParse, 1, "%sSCALAR SUBQUERY",
|
||||
jmpIfDynamic>=0?"":"CORRELATED "));
|
||||
nReg = pExpr->op==TK_SELECT ? pSel->pEList->nExpr : 1;
|
||||
sqlite3SelectDestInit(&dest, 0, pParse->nMem+1);
|
||||
pParse->nMem += nReg;
|
||||
@@ -3541,6 +3531,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr_code_doover:
|
||||
if( pExpr==0 ){
|
||||
op = TK_NULL;
|
||||
}else{
|
||||
@@ -4001,7 +3992,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
case TK_SPAN:
|
||||
case TK_COLLATE:
|
||||
case TK_UPLUS: {
|
||||
return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||
pExpr = pExpr->pLeft;
|
||||
goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. OSSFuzz. */
|
||||
}
|
||||
|
||||
case TK_TRIGGER: {
|
||||
@@ -4039,10 +4031,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( p1>=0 && p1<(pTab->nCol*2+2) );
|
||||
|
||||
sqlite3VdbeAddOp2(v, OP_Param, p1, target);
|
||||
VdbeComment((v, "%s.%s -> $%d",
|
||||
VdbeComment((v, "r[%d]=%s.%s", target,
|
||||
(pExpr->iTable ? "new" : "old"),
|
||||
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName),
|
||||
target
|
||||
(pExpr->iColumn<0 ? "rowid" : pExpr->pTab->aCol[pExpr->iColumn].zName)
|
||||
));
|
||||
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
@@ -4920,7 +4911,8 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
|
||||
if( sqlite3ExprCompare(pParse, pA->pLeft, pB->pLeft, iTab) ) return 2;
|
||||
if( sqlite3ExprCompare(pParse, pA->pRight, pB->pRight, iTab) ) return 2;
|
||||
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
|
||||
if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
|
||||
assert( (combinedFlags & EP_Reduced)==0 );
|
||||
if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
|
||||
if( pA->iColumn!=pB->iColumn ) return 2;
|
||||
if( pA->iTable!=pB->iTable
|
||||
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
|
||||
|
||||
@@ -331,6 +331,12 @@ static void fkLookupParent(
|
||||
int iCur = pParse->nTab - 1; /* Cursor number to use */
|
||||
int iOk = sqlite3VdbeMakeLabel(v); /* jump here if parent key found */
|
||||
|
||||
sqlite3VdbeVerifyAbortable(v,
|
||||
(!pFKey->isDeferred
|
||||
&& !(pParse->db->flags & SQLITE_DeferFKs)
|
||||
&& !pParse->pToplevel
|
||||
&& !pParse->isMultiWrite) ? OE_Abort : OE_Ignore);
|
||||
|
||||
/* If nIncr is less than zero, then check at runtime if there are any
|
||||
** outstanding constraints to resolve. If there are not, there is no need
|
||||
** to check if deleting this row resolves any outstanding violations.
|
||||
@@ -738,6 +744,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
|
||||
** constraints are violated.
|
||||
*/
|
||||
if( (db->flags & SQLITE_DeferFKs)==0 ){
|
||||
sqlite3VdbeVerifyAbortable(v, OE_Abort);
|
||||
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
|
||||
VdbeCoverage(v);
|
||||
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
|
||||
|
||||
+5
-5
@@ -251,7 +251,7 @@ static void printfFunc(
|
||||
x.apArg = argv+1;
|
||||
sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
str.printfFlags = SQLITE_PRINTF_SQLFUNC;
|
||||
sqlite3XPrintf(&str, zFormat, &x);
|
||||
sqlite3_str_appendf(&str, zFormat, &x);
|
||||
n = str.nChar;
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
|
||||
SQLITE_DYNAMIC);
|
||||
@@ -1654,20 +1654,20 @@ static void groupConcatStep(
|
||||
zSep = ",";
|
||||
nSep = 1;
|
||||
}
|
||||
if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
|
||||
if( zSep ) sqlite3_str_append(pAccum, zSep, nSep);
|
||||
}
|
||||
zVal = (char*)sqlite3_value_text(argv[0]);
|
||||
nVal = sqlite3_value_bytes(argv[0]);
|
||||
if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
|
||||
if( zVal ) sqlite3_str_append(pAccum, zVal, nVal);
|
||||
}
|
||||
}
|
||||
static void groupConcatFinalize(sqlite3_context *context){
|
||||
StrAccum *pAccum;
|
||||
pAccum = sqlite3_aggregate_context(context, 0);
|
||||
if( pAccum ){
|
||||
if( pAccum->accError==STRACCUM_TOOBIG ){
|
||||
if( pAccum->accError==SQLITE_TOOBIG ){
|
||||
sqlite3_result_error_toobig(context);
|
||||
}else if( pAccum->accError==STRACCUM_NOMEM ){
|
||||
}else if( pAccum->accError==SQLITE_NOMEM ){
|
||||
sqlite3_result_error_nomem(context);
|
||||
}else{
|
||||
sqlite3_result_text(context, sqlite3StrAccumFinish(pAccum), -1,
|
||||
|
||||
+22
-1
@@ -226,11 +226,26 @@ static int autoIncBegin(
|
||||
Table *pTab /* The table we are writing to */
|
||||
){
|
||||
int memId = 0; /* Register holding maximum rowid */
|
||||
assert( pParse->db->aDb[iDb].pSchema!=0 );
|
||||
if( (pTab->tabFlags & TF_Autoincrement)!=0
|
||||
&& (pParse->db->mDbFlags & DBFLAG_Vacuum)==0
|
||||
){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
AutoincInfo *pInfo;
|
||||
Table *pSeqTab = pParse->db->aDb[iDb].pSchema->pSeqTab;
|
||||
|
||||
/* Verify that the sqlite_sequence table exists and is an ordinary
|
||||
** rowid table with exactly two columns.
|
||||
** Ticket d8dc2b3a58cd5dc2918a1d4acb 2018-05-23 */
|
||||
if( pSeqTab==0
|
||||
|| !HasRowid(pSeqTab)
|
||||
|| IsVirtual(pSeqTab)
|
||||
|| pSeqTab->nCol!=2
|
||||
){
|
||||
pParse->nErr++;
|
||||
pParse->rc = SQLITE_CORRUPT_SEQUENCE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
pInfo = pToplevel->pAinc;
|
||||
while( pInfo && pInfo->pTab!=pTab ){ pInfo = pInfo->pNext; }
|
||||
@@ -1405,6 +1420,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
Expr *pExpr = pCheck->a[i].pExpr;
|
||||
if( aiChng && checkConstraintUnchanged(pExpr, aiChng, pkChng) ) continue;
|
||||
allOk = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3ExprIfTrue(pParse, pExpr, allOk, SQLITE_JUMPIFNULL);
|
||||
if( onError==OE_Ignore ){
|
||||
sqlite3VdbeGoto(v, ignoreDest);
|
||||
@@ -1514,6 +1530,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
/* Check to see if the new rowid already exists in the table. Skip
|
||||
** the following conflict logic if it does not. */
|
||||
VdbeNoopComment((v, "uniqueness check for ROWID"));
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iDataCur, addrRowidOk, regNewData);
|
||||
VdbeCoverage(v);
|
||||
|
||||
@@ -1726,6 +1743,7 @@ void sqlite3GenerateConstraintChecks(
|
||||
|
||||
/* Check to see if the new index entry will be unique */
|
||||
sqlite3ExprCachePush(pParse);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
sqlite3VdbeAddOp4Int(v, OP_NoConflict, iThisCur, addrUniqueOk,
|
||||
regIdx, pIdx->nKeyCol); VdbeCoverage(v);
|
||||
|
||||
@@ -1812,10 +1830,12 @@ void sqlite3GenerateConstraintChecks(
|
||||
default: {
|
||||
Trigger *pTrigger = 0;
|
||||
assert( onError==OE_Replace );
|
||||
sqlite3MultiWrite(pParse);
|
||||
if( db->flags&SQLITE_RecTriggers ){
|
||||
pTrigger = sqlite3TriggersExist(pParse, pTab, TK_DELETE, 0, 0);
|
||||
}
|
||||
if( pTrigger || sqlite3FkRequired(pParse, pTab, 0, 0) ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
}
|
||||
sqlite3GenerateRowDelete(pParse, pTab, pTrigger, iDataCur, iIdxCur,
|
||||
regR, nPkField, 0, OE_Replace,
|
||||
(pIdx==pPk ? ONEPASS_SINGLE : ONEPASS_OFF), iThisCur);
|
||||
@@ -2335,6 +2355,7 @@ static int xferOptimization(
|
||||
emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
|
||||
if( pDest->iPKey>=0 ){
|
||||
addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
|
||||
sqlite3VdbeVerifyAbortable(v, onError);
|
||||
addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
|
||||
VdbeCoverage(v);
|
||||
sqlite3RowidConstraint(pParse, onError, pDest);
|
||||
|
||||
+17
-4
@@ -434,7 +434,22 @@ static const sqlite3_api_routines sqlite3Apis = {
|
||||
/* Version 3.22.0 and later */
|
||||
sqlite3_vtab_nochange,
|
||||
sqlite3_value_nochange,
|
||||
sqlite3_vtab_collation
|
||||
sqlite3_vtab_collation,
|
||||
/* Version 3.24.0 and later */
|
||||
sqlite3_keyword_count,
|
||||
sqlite3_keyword_name,
|
||||
sqlite3_keyword_check,
|
||||
sqlite3_str_new,
|
||||
sqlite3_str_finish,
|
||||
sqlite3_str_appendf,
|
||||
sqlite3_str_vappendf,
|
||||
sqlite3_str_append,
|
||||
sqlite3_str_appendall,
|
||||
sqlite3_str_appendchar,
|
||||
sqlite3_str_reset,
|
||||
sqlite3_str_errcode,
|
||||
sqlite3_str_length,
|
||||
sqlite3_str_value
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -500,10 +515,8 @@ static int sqlite3LoadExtension(
|
||||
#if SQLITE_OS_UNIX || SQLITE_OS_WIN
|
||||
for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){
|
||||
char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]);
|
||||
int bExists = 0;
|
||||
if( zAltFile==0 ) return SQLITE_NOMEM_BKPT;
|
||||
sqlite3OsAccess(pVfs, zAltFile, SQLITE_ACCESS_EXISTS, &bExists);
|
||||
if( bExists ) handle = sqlite3OsDlOpen(pVfs, zAltFile);
|
||||
handle = sqlite3OsDlOpen(pVfs, zAltFile);
|
||||
sqlite3_free(zAltFile);
|
||||
}
|
||||
#endif
|
||||
|
||||
+35
-27
@@ -834,6 +834,7 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
|
||||
{ SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE, SQLITE_NoCkptOnClose },
|
||||
{ SQLITE_DBCONFIG_ENABLE_QPSG, SQLITE_EnableQPSG },
|
||||
{ SQLITE_DBCONFIG_TRIGGER_EQP, SQLITE_TriggerEQP },
|
||||
{ SQLITE_DBCONFIG_RESET_DATABASE, SQLITE_ResetDatabase },
|
||||
};
|
||||
unsigned int i;
|
||||
rc = SQLITE_ERROR; /* IMP: R-42790-23372 */
|
||||
@@ -1807,11 +1808,13 @@ int sqlite3_create_function_v2(
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( xDestroy ){
|
||||
pArg = (FuncDestructor *)sqlite3DbMallocZero(db, sizeof(FuncDestructor));
|
||||
pArg = (FuncDestructor *)sqlite3Malloc(sizeof(FuncDestructor));
|
||||
if( !pArg ){
|
||||
sqlite3OomFault(db);
|
||||
xDestroy(p);
|
||||
goto out;
|
||||
}
|
||||
pArg->nRef = 0;
|
||||
pArg->xDestroy = xDestroy;
|
||||
pArg->pUserData = p;
|
||||
}
|
||||
@@ -1819,7 +1822,7 @@ int sqlite3_create_function_v2(
|
||||
if( pArg && pArg->nRef==0 ){
|
||||
assert( rc!=SQLITE_OK );
|
||||
xDestroy(p);
|
||||
sqlite3DbFree(db, pArg);
|
||||
sqlite3_free(pArg);
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -1857,6 +1860,28 @@ int sqlite3_create_function16(
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** The following is the implementation of an SQL function that always
|
||||
** fails with an error message stating that the function is used in the
|
||||
** wrong context. The sqlite3_overload_function() API might construct
|
||||
** SQL function that use this routine so that the functions will exist
|
||||
** for name resolution but are actually overloaded by the xFindFunction
|
||||
** method of virtual tables.
|
||||
*/
|
||||
static void sqlite3InvalidFunction(
|
||||
sqlite3_context *context, /* The function calling context */
|
||||
int NotUsed, /* Number of arguments to the function */
|
||||
sqlite3_value **NotUsed2 /* Value of each argument */
|
||||
){
|
||||
const char *zName = (const char*)sqlite3_user_data(context);
|
||||
char *zErr;
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
zErr = sqlite3_mprintf(
|
||||
"unable to use function %s in the requested context", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Declare that a function has been overloaded by a virtual table.
|
||||
**
|
||||
@@ -1874,7 +1899,8 @@ int sqlite3_overload_function(
|
||||
const char *zName,
|
||||
int nArg
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int rc;
|
||||
char *zCopy;
|
||||
|
||||
#ifdef SQLITE_ENABLE_API_ARMOR
|
||||
if( !sqlite3SafetyCheckOk(db) || zName==0 || nArg<-2 ){
|
||||
@@ -1882,13 +1908,13 @@ int sqlite3_overload_function(
|
||||
}
|
||||
#endif
|
||||
sqlite3_mutex_enter(db->mutex);
|
||||
if( sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)==0 ){
|
||||
rc = sqlite3CreateFunc(db, zName, nArg, SQLITE_UTF8,
|
||||
0, sqlite3InvalidFunction, 0, 0, 0);
|
||||
}
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
rc = sqlite3FindFunction(db, zName, nArg, SQLITE_UTF8, 0)!=0;
|
||||
sqlite3_mutex_leave(db->mutex);
|
||||
return rc;
|
||||
if( rc ) return SQLITE_OK;
|
||||
zCopy = sqlite3_mprintf(zName);
|
||||
if( zCopy==0 ) return SQLITE_NOMEM;
|
||||
return sqlite3_create_function_v2(db, zName, nArg, SQLITE_UTF8,
|
||||
zCopy, sqlite3InvalidFunction, 0, 0, sqlite3_free);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
@@ -3861,24 +3887,6 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_N_KEYWORD
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord)
|
||||
**
|
||||
** If zWord is a keyword recognized by the parser, then return the
|
||||
** number of keywords. Or if zWord is not a keyword, return 0.
|
||||
**
|
||||
** This test feature is only available in the amalgamation since
|
||||
** the SQLITE_N_KEYWORD macro is not defined in this file if SQLite
|
||||
** is built using separate source files.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_ISKEYWORD: {
|
||||
const char *zWord = va_arg(ap, const char*);
|
||||
int n = sqlite3Strlen30(zWord);
|
||||
rc = (sqlite3KeywordCode((u8*)zWord, n)!=TK_ID) ? SQLITE_N_KEYWORD : 0;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, int onoff);
|
||||
**
|
||||
** If parameter onoff is non-zero, configure the wrappers so that all
|
||||
|
||||
@@ -358,4 +358,3 @@ int sqlite3_mutex_notheld(sqlite3_mutex *p){
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SQLITE_MUTEX_OMIT) */
|
||||
|
||||
|
||||
+43
-26
@@ -315,22 +315,6 @@ struct winVfsAppData {
|
||||
# define SQLITE_WIN32_DBG_BUF_SIZE ((int)(4096-sizeof(DWORD)))
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The value used with sqlite3_win32_set_directory() to specify that
|
||||
* the data directory should be changed.
|
||||
*/
|
||||
#ifndef SQLITE_WIN32_DATA_DIRECTORY_TYPE
|
||||
# define SQLITE_WIN32_DATA_DIRECTORY_TYPE (1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The value used with sqlite3_win32_set_directory() to specify that
|
||||
* the temporary directory should be changed.
|
||||
*/
|
||||
#ifndef SQLITE_WIN32_TEMP_DIRECTORY_TYPE
|
||||
# define SQLITE_WIN32_TEMP_DIRECTORY_TYPE (2)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If compiled with SQLITE_WIN32_MALLOC on Windows, we will use the
|
||||
* various Win32 API heap functions instead of our own.
|
||||
@@ -1927,13 +1911,13 @@ char *sqlite3_win32_utf8_to_mbcs_v2(const char *zText, int useAnsi){
|
||||
}
|
||||
|
||||
/*
|
||||
** This function sets the data directory or the temporary directory based on
|
||||
** the provided arguments. The type argument must be 1 in order to set the
|
||||
** data directory or 2 in order to set the temporary directory. The zValue
|
||||
** argument is the name of the directory to use. The return value will be
|
||||
** SQLITE_OK if successful.
|
||||
** This function is the same as sqlite3_win32_set_directory (below); however,
|
||||
** it accepts a UTF-8 string.
|
||||
*/
|
||||
int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
|
||||
int sqlite3_win32_set_directory8(
|
||||
unsigned long type, /* Identifier for directory being set or reset */
|
||||
const char *zValue /* New value for directory being set or reset */
|
||||
){
|
||||
char **ppDirectory = 0;
|
||||
#ifndef SQLITE_OMIT_AUTOINIT
|
||||
int rc = sqlite3_initialize();
|
||||
@@ -1949,20 +1933,53 @@ int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
|
||||
);
|
||||
assert( !ppDirectory || sqlite3MemdebugHasType(*ppDirectory, MEMTYPE_HEAP) );
|
||||
if( ppDirectory ){
|
||||
char *zValueUtf8 = 0;
|
||||
char *zCopy = 0;
|
||||
if( zValue && zValue[0] ){
|
||||
zValueUtf8 = winUnicodeToUtf8(zValue);
|
||||
if ( zValueUtf8==0 ){
|
||||
zCopy = sqlite3_mprintf("%s", zValue);
|
||||
if ( zCopy==0 ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
}
|
||||
sqlite3_free(*ppDirectory);
|
||||
*ppDirectory = zValueUtf8;
|
||||
*ppDirectory = zCopy;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is the same as sqlite3_win32_set_directory (below); however,
|
||||
** it accepts a UTF-16 string.
|
||||
*/
|
||||
int sqlite3_win32_set_directory16(
|
||||
unsigned long type, /* Identifier for directory being set or reset */
|
||||
const void *zValue /* New value for directory being set or reset */
|
||||
){
|
||||
int rc;
|
||||
char *zUtf8 = 0;
|
||||
if( zValue ){
|
||||
zUtf8 = sqlite3_win32_unicode_to_utf8(zValue);
|
||||
if( zUtf8==0 ) return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
rc = sqlite3_win32_set_directory8(type, zUtf8);
|
||||
if( zUtf8 ) sqlite3_free(zUtf8);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function sets the data directory or the temporary directory based on
|
||||
** the provided arguments. The type argument must be 1 in order to set the
|
||||
** data directory or 2 in order to set the temporary directory. The zValue
|
||||
** argument is the name of the directory to use. The return value will be
|
||||
** SQLITE_OK if successful.
|
||||
*/
|
||||
int sqlite3_win32_set_directory(
|
||||
unsigned long type, /* Identifier for directory being set or reset */
|
||||
void *zValue /* New value for directory being set or reset */
|
||||
){
|
||||
return sqlite3_win32_set_directory16(type, zValue);
|
||||
}
|
||||
|
||||
/*
|
||||
** The return value of winGetLastErrorMsg
|
||||
** is zero if the error message fits in the buffer, or non-zero
|
||||
|
||||
+5
-2
@@ -24,8 +24,9 @@
|
||||
%token_type {Token}
|
||||
%default_type {Token}
|
||||
|
||||
// The generated parser function takes a 4th argument as follows:
|
||||
%extra_argument {Parse *pParse}
|
||||
// An extra argument to the constructor for the parser, which is available
|
||||
// to all actions.
|
||||
%extra_context {Parse *pParse}
|
||||
|
||||
// This code runs whenever there is a syntax error
|
||||
//
|
||||
@@ -466,6 +467,7 @@ cmd ::= select(X). {
|
||||
}
|
||||
}
|
||||
|
||||
%ifndef SQLITE_OMIT_CTE
|
||||
select(A) ::= WITH wqlist(W) selectnowith(X). {
|
||||
Select *p = X;
|
||||
if( p ){
|
||||
@@ -486,6 +488,7 @@ select(A) ::= WITH RECURSIVE wqlist(W) selectnowith(X). {
|
||||
}
|
||||
A = p;
|
||||
}
|
||||
%endif /* SQLITE_OMIT_CTE */
|
||||
select(A) ::= selectnowith(X). {
|
||||
Select *p = X;
|
||||
if( p ){
|
||||
|
||||
+10
-10
@@ -2216,26 +2216,26 @@ static int pragmaVtabConnect(
|
||||
UNUSED_PARAMETER(argc);
|
||||
UNUSED_PARAMETER(argv);
|
||||
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
||||
sqlite3StrAccumAppendAll(&acc, "CREATE TABLE x");
|
||||
sqlite3_str_appendall(&acc, "CREATE TABLE x");
|
||||
for(i=0, j=pPragma->iPragCName; i<pPragma->nPragCName; i++, j++){
|
||||
sqlite3XPrintf(&acc, "%c\"%s\"", cSep, pragCName[j]);
|
||||
sqlite3_str_appendf(&acc, "%c\"%s\"", cSep, pragCName[j]);
|
||||
cSep = ',';
|
||||
}
|
||||
if( i==0 ){
|
||||
sqlite3XPrintf(&acc, "(\"%s\"", pPragma->zName);
|
||||
sqlite3_str_appendf(&acc, "(\"%s\"", pPragma->zName);
|
||||
cSep = ',';
|
||||
i++;
|
||||
}
|
||||
j = 0;
|
||||
if( pPragma->mPragFlg & PragFlg_Result1 ){
|
||||
sqlite3StrAccumAppendAll(&acc, ",arg HIDDEN");
|
||||
sqlite3_str_appendall(&acc, ",arg HIDDEN");
|
||||
j++;
|
||||
}
|
||||
if( pPragma->mPragFlg & (PragFlg_SchemaOpt|PragFlg_SchemaReq) ){
|
||||
sqlite3StrAccumAppendAll(&acc, ",schema HIDDEN");
|
||||
sqlite3_str_appendall(&acc, ",schema HIDDEN");
|
||||
j++;
|
||||
}
|
||||
sqlite3StrAccumAppend(&acc, ")", 1);
|
||||
sqlite3_str_append(&acc, ")", 1);
|
||||
sqlite3StrAccumFinish(&acc);
|
||||
assert( strlen(zBuf) < sizeof(zBuf)-1 );
|
||||
rc = sqlite3_declare_vtab(db, zBuf);
|
||||
@@ -2387,13 +2387,13 @@ static int pragmaVtabFilter(
|
||||
}
|
||||
}
|
||||
sqlite3StrAccumInit(&acc, 0, 0, 0, pTab->db->aLimit[SQLITE_LIMIT_SQL_LENGTH]);
|
||||
sqlite3StrAccumAppendAll(&acc, "PRAGMA ");
|
||||
sqlite3_str_appendall(&acc, "PRAGMA ");
|
||||
if( pCsr->azArg[1] ){
|
||||
sqlite3XPrintf(&acc, "%Q.", pCsr->azArg[1]);
|
||||
sqlite3_str_appendf(&acc, "%Q.", pCsr->azArg[1]);
|
||||
}
|
||||
sqlite3StrAccumAppendAll(&acc, pTab->pName->zName);
|
||||
sqlite3_str_appendall(&acc, pTab->pName->zName);
|
||||
if( pCsr->azArg[0] ){
|
||||
sqlite3XPrintf(&acc, "=%Q", pCsr->azArg[0]);
|
||||
sqlite3_str_appendf(&acc, "=%Q", pCsr->azArg[0]);
|
||||
}
|
||||
zSql = sqlite3StrAccumFinish(&acc);
|
||||
if( zSql==0 ) return SQLITE_NOMEM;
|
||||
|
||||
+12
-5
@@ -145,6 +145,7 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
const char *zMasterName;
|
||||
int openedTransaction = 0;
|
||||
|
||||
assert( (db->mDbFlags & DBFLAG_SchemaKnownOk)==0 );
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pSchema );
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
@@ -215,6 +216,9 @@ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){
|
||||
for(i=0; i<ArraySize(meta); i++){
|
||||
sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]);
|
||||
}
|
||||
if( (db->flags & SQLITE_ResetDatabase)!=0 ){
|
||||
memset(meta, 0, sizeof(meta));
|
||||
}
|
||||
pDb->pSchema->schema_cookie = meta[BTREE_SCHEMA_VERSION-1];
|
||||
|
||||
/* If opening a non-empty database, check the text encoding. For the
|
||||
@@ -374,6 +378,7 @@ int sqlite3Init(sqlite3 *db, char **pzErrMsg){
|
||||
}
|
||||
/* All other schemas after the main schema. The "temp" schema must be last */
|
||||
for(i=db->nDb-1; i>0; i--){
|
||||
assert( i==1 || sqlite3BtreeHoldsMutex(db->aDb[i].pBt) );
|
||||
if( !DbHasProperty(db, i, DB_SchemaLoaded) ){
|
||||
rc = sqlite3InitOne(db, i, pzErrMsg);
|
||||
if( rc ) return rc;
|
||||
@@ -395,10 +400,12 @@ int sqlite3ReadSchema(Parse *pParse){
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
if( !db->init.busy ){
|
||||
rc = sqlite3Init(db, &pParse->zErrMsg);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
pParse->rc = rc;
|
||||
pParse->nErr++;
|
||||
if( rc!=SQLITE_OK ){
|
||||
pParse->rc = rc;
|
||||
pParse->nErr++;
|
||||
}else if( db->noSharedCache ){
|
||||
db->mDbFlags |= DBFLAG_SchemaKnownOk;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@@ -609,7 +616,7 @@ static int sqlite3Prepare(
|
||||
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
|
||||
static const char * const azColName[] = {
|
||||
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
|
||||
"selectid", "order", "from", "detail"
|
||||
"id", "parent", "notused", "detail"
|
||||
};
|
||||
int iFirst, mx;
|
||||
if( sParse.explain==2 ){
|
||||
|
||||
+97
-43
@@ -134,7 +134,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
|
||||
** Set the StrAccum object to an error mode.
|
||||
*/
|
||||
static void setStrAccumError(StrAccum *p, u8 eError){
|
||||
assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG );
|
||||
assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG );
|
||||
p->accError = eError;
|
||||
p->nAlloc = 0;
|
||||
}
|
||||
@@ -168,8 +168,8 @@ static char *getTextArg(PrintfArguments *p){
|
||||
/*
|
||||
** Render a string given by "fmt" into the StrAccum object.
|
||||
*/
|
||||
void sqlite3VXPrintf(
|
||||
StrAccum *pAccum, /* Accumulate results here */
|
||||
void sqlite3_str_vappendf(
|
||||
sqlite3_str *pAccum, /* Accumulate results here */
|
||||
const char *fmt, /* Format string */
|
||||
va_list ap /* arguments */
|
||||
){
|
||||
@@ -226,11 +226,11 @@ void sqlite3VXPrintf(
|
||||
#else
|
||||
do{ fmt++; }while( *fmt && *fmt != '%' );
|
||||
#endif
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, (int)(fmt - bufpt));
|
||||
sqlite3_str_append(pAccum, bufpt, (int)(fmt - bufpt));
|
||||
if( *fmt==0 ) break;
|
||||
}
|
||||
if( (c=(*++fmt))==0 ){
|
||||
sqlite3StrAccumAppend(pAccum, "%", 1);
|
||||
sqlite3_str_append(pAccum, "%", 1);
|
||||
break;
|
||||
}
|
||||
/* Find out what flags are present */
|
||||
@@ -408,7 +408,7 @@ void sqlite3VXPrintf(
|
||||
u64 n = (u64)precision + 10 + precision/3;
|
||||
zOut = zExtra = sqlite3Malloc( n );
|
||||
if( zOut==0 ){
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
setStrAccumError(pAccum, SQLITE_NOMEM);
|
||||
return;
|
||||
}
|
||||
nOut = (int)n;
|
||||
@@ -533,7 +533,7 @@ void sqlite3VXPrintf(
|
||||
bufpt = zExtra
|
||||
= sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
|
||||
if( bufpt==0 ){
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
setStrAccumError(pAccum, SQLITE_NOMEM);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -665,11 +665,11 @@ void sqlite3VXPrintf(
|
||||
if( precision>1 ){
|
||||
width -= precision-1;
|
||||
if( width>1 && !flag_leftjustify ){
|
||||
sqlite3AppendChar(pAccum, width-1, ' ');
|
||||
sqlite3_str_appendchar(pAccum, width-1, ' ');
|
||||
width = 0;
|
||||
}
|
||||
while( precision-- > 1 ){
|
||||
sqlite3StrAccumAppend(pAccum, buf, length);
|
||||
sqlite3_str_append(pAccum, buf, length);
|
||||
}
|
||||
}
|
||||
bufpt = buf;
|
||||
@@ -755,7 +755,7 @@ void sqlite3VXPrintf(
|
||||
if( n>etBUFSIZE ){
|
||||
bufpt = zExtra = sqlite3Malloc( n );
|
||||
if( bufpt==0 ){
|
||||
setStrAccumError(pAccum, STRACCUM_NOMEM);
|
||||
setStrAccumError(pAccum, SQLITE_NOMEM);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
@@ -779,7 +779,7 @@ void sqlite3VXPrintf(
|
||||
pToken = va_arg(ap, Token*);
|
||||
assert( bArgList==0 );
|
||||
if( pToken && pToken->n ){
|
||||
sqlite3StrAccumAppend(pAccum, (const char*)pToken->z, pToken->n);
|
||||
sqlite3_str_append(pAccum, (const char*)pToken->z, pToken->n);
|
||||
}
|
||||
length = width = 0;
|
||||
break;
|
||||
@@ -795,10 +795,10 @@ void sqlite3VXPrintf(
|
||||
assert( bArgList==0 );
|
||||
assert( k>=0 && k<pSrc->nSrc );
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3StrAccumAppendAll(pAccum, pItem->zDatabase);
|
||||
sqlite3StrAccumAppend(pAccum, ".", 1);
|
||||
sqlite3_str_appendall(pAccum, pItem->zDatabase);
|
||||
sqlite3_str_append(pAccum, ".", 1);
|
||||
}
|
||||
sqlite3StrAccumAppendAll(pAccum, pItem->zName);
|
||||
sqlite3_str_appendall(pAccum, pItem->zName);
|
||||
length = width = 0;
|
||||
break;
|
||||
}
|
||||
@@ -817,11 +817,11 @@ void sqlite3VXPrintf(
|
||||
*/
|
||||
width -= length;
|
||||
if( width>0 ){
|
||||
if( !flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, length);
|
||||
if( flag_leftjustify ) sqlite3AppendChar(pAccum, width, ' ');
|
||||
if( !flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
|
||||
sqlite3_str_append(pAccum, bufpt, length);
|
||||
if( flag_leftjustify ) sqlite3_str_appendchar(pAccum, width, ' ');
|
||||
}else{
|
||||
sqlite3StrAccumAppend(pAccum, bufpt, length);
|
||||
sqlite3_str_append(pAccum, bufpt, length);
|
||||
}
|
||||
|
||||
if( zExtra ){
|
||||
@@ -842,13 +842,13 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
char *zNew;
|
||||
assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
|
||||
if( p->accError ){
|
||||
testcase(p->accError==STRACCUM_TOOBIG);
|
||||
testcase(p->accError==STRACCUM_NOMEM);
|
||||
testcase(p->accError==SQLITE_TOOBIG);
|
||||
testcase(p->accError==SQLITE_NOMEM);
|
||||
return 0;
|
||||
}
|
||||
if( p->mxAlloc==0 ){
|
||||
N = p->nAlloc - p->nChar - 1;
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
setStrAccumError(p, SQLITE_TOOBIG);
|
||||
return N;
|
||||
}else{
|
||||
char *zOld = isMalloced(p) ? p->zText : 0;
|
||||
@@ -860,8 +860,8 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
szNew += p->nChar;
|
||||
}
|
||||
if( szNew > p->mxAlloc ){
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_TOOBIG);
|
||||
sqlite3_str_reset(p);
|
||||
setStrAccumError(p, SQLITE_TOOBIG);
|
||||
return 0;
|
||||
}else{
|
||||
p->nAlloc = (int)szNew;
|
||||
@@ -878,8 +878,8 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
p->nAlloc = sqlite3DbMallocSize(p->db, zNew);
|
||||
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
||||
}else{
|
||||
sqlite3StrAccumReset(p);
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
sqlite3_str_reset(p);
|
||||
setStrAccumError(p, SQLITE_NOMEM);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -889,7 +889,7 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
|
||||
/*
|
||||
** Append N copies of character c to the given string buffer.
|
||||
*/
|
||||
void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
void sqlite3_str_appendchar(sqlite3_str *p, int N, char c){
|
||||
testcase( p->nChar + (i64)N > 0x7fffffff );
|
||||
if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
|
||||
return;
|
||||
@@ -901,9 +901,9 @@ void sqlite3AppendChar(StrAccum *p, int N, char c){
|
||||
** The StrAccum "p" is not large enough to accept N new bytes of z[].
|
||||
** So enlarge if first, then do the append.
|
||||
**
|
||||
** This is a helper routine to sqlite3StrAccumAppend() that does special-case
|
||||
** This is a helper routine to sqlite3_str_append() that does special-case
|
||||
** work (enlarging the buffer) using tail recursion, so that the
|
||||
** sqlite3StrAccumAppend() routine can use fast calling semantics.
|
||||
** sqlite3_str_append() routine can use fast calling semantics.
|
||||
*/
|
||||
static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
N = sqlite3StrAccumEnlarge(p, N);
|
||||
@@ -917,7 +917,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
|
||||
** Append N bytes of text from z to the StrAccum object. Increase the
|
||||
** size of the memory allocation for StrAccum if necessary.
|
||||
*/
|
||||
void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
void sqlite3_str_append(sqlite3_str *p, const char *z, int N){
|
||||
assert( z!=0 || N==0 );
|
||||
assert( p->zText!=0 || p->nChar==0 || p->accError );
|
||||
assert( N>=0 );
|
||||
@@ -934,8 +934,8 @@ void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
|
||||
/*
|
||||
** Append the complete text of zero-terminated string z[] to the p string.
|
||||
*/
|
||||
void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
|
||||
sqlite3StrAccumAppend(p, z, sqlite3Strlen30(z));
|
||||
void sqlite3_str_appendall(sqlite3_str *p, const char *z){
|
||||
sqlite3_str_append(p, z, sqlite3Strlen30(z));
|
||||
}
|
||||
|
||||
|
||||
@@ -952,7 +952,7 @@ static SQLITE_NOINLINE char *strAccumFinishRealloc(StrAccum *p){
|
||||
memcpy(zText, p->zText, p->nChar+1);
|
||||
p->printfFlags |= SQLITE_PRINTF_MALLOCED;
|
||||
}else{
|
||||
setStrAccumError(p, STRACCUM_NOMEM);
|
||||
setStrAccumError(p, SQLITE_NOMEM);
|
||||
}
|
||||
p->zText = zText;
|
||||
return zText;
|
||||
@@ -967,14 +967,56 @@ char *sqlite3StrAccumFinish(StrAccum *p){
|
||||
return p->zText;
|
||||
}
|
||||
|
||||
/*
|
||||
** This singleton is an sqlite3_str object that is returned if
|
||||
** sqlite3_malloc() fails to provide space for a real one. This
|
||||
** sqlite3_str object accepts no new text and always returns
|
||||
** an SQLITE_NOMEM error.
|
||||
*/
|
||||
static sqlite3_str sqlite3OomStr = {
|
||||
0, 0, 0, 0, 0, SQLITE_NOMEM, 0
|
||||
};
|
||||
|
||||
/* Finalize a string created using sqlite3_str_new().
|
||||
*/
|
||||
char *sqlite3_str_finish(sqlite3_str *p){
|
||||
char *z;
|
||||
if( p!=0 && p!=&sqlite3OomStr ){
|
||||
z = sqlite3StrAccumFinish(p);
|
||||
sqlite3_free(p);
|
||||
}else{
|
||||
z = 0;
|
||||
}
|
||||
return z;
|
||||
}
|
||||
|
||||
/* Return any error code associated with p */
|
||||
int sqlite3_str_errcode(sqlite3_str *p){
|
||||
return p ? p->accError : SQLITE_NOMEM;
|
||||
}
|
||||
|
||||
/* Return the current length of p in bytes */
|
||||
int sqlite3_str_length(sqlite3_str *p){
|
||||
return p ? p->nChar : 0;
|
||||
}
|
||||
|
||||
/* Return the current value for p */
|
||||
char *sqlite3_str_value(sqlite3_str *p){
|
||||
if( p==0 || p->nChar==0 ) return 0;
|
||||
p->zText[p->nChar] = 0;
|
||||
return p->zText;
|
||||
}
|
||||
|
||||
/*
|
||||
** Reset an StrAccum string. Reclaim all malloced memory.
|
||||
*/
|
||||
void sqlite3StrAccumReset(StrAccum *p){
|
||||
void sqlite3_str_reset(StrAccum *p){
|
||||
if( isMalloced(p) ){
|
||||
sqlite3DbFree(p->db, p->zText);
|
||||
p->printfFlags &= ~SQLITE_PRINTF_MALLOCED;
|
||||
}
|
||||
p->nAlloc = 0;
|
||||
p->nChar = 0;
|
||||
p->zText = 0;
|
||||
}
|
||||
|
||||
@@ -1002,6 +1044,18 @@ void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
|
||||
p->printfFlags = 0;
|
||||
}
|
||||
|
||||
/* Allocate and initialize a new dynamic string object */
|
||||
sqlite3_str *sqlite3_str_new(sqlite3 *db){
|
||||
sqlite3_str *p = sqlite3_malloc64(sizeof(*p));
|
||||
if( p ){
|
||||
sqlite3StrAccumInit(p, 0, 0, 0,
|
||||
db ? db->aLimit[SQLITE_LIMIT_LENGTH] : SQLITE_MAX_LENGTH);
|
||||
}else{
|
||||
p = &sqlite3OomStr;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
/*
|
||||
** Print into memory obtained from sqliteMalloc(). Use the internal
|
||||
** %-conversion extensions.
|
||||
@@ -1014,9 +1068,9 @@ char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list ap){
|
||||
sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
|
||||
db->aLimit[SQLITE_LIMIT_LENGTH]);
|
||||
acc.printfFlags = SQLITE_PRINTF_INTERNAL;
|
||||
sqlite3VXPrintf(&acc, zFormat, ap);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
z = sqlite3StrAccumFinish(&acc);
|
||||
if( acc.accError==STRACCUM_NOMEM ){
|
||||
if( acc.accError==SQLITE_NOMEM ){
|
||||
sqlite3OomFault(db);
|
||||
}
|
||||
return z;
|
||||
@@ -1054,7 +1108,7 @@ char *sqlite3_vmprintf(const char *zFormat, va_list ap){
|
||||
if( sqlite3_initialize() ) return 0;
|
||||
#endif
|
||||
sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
|
||||
sqlite3VXPrintf(&acc, zFormat, ap);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
z = sqlite3StrAccumFinish(&acc);
|
||||
return z;
|
||||
}
|
||||
@@ -1099,7 +1153,7 @@ char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
|
||||
}
|
||||
#endif
|
||||
sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
|
||||
sqlite3VXPrintf(&acc, zFormat, ap);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
zBuf[acc.nChar] = 0;
|
||||
return zBuf;
|
||||
}
|
||||
@@ -1121,7 +1175,7 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
|
||||
** allocate memory because it might be called while the memory allocator
|
||||
** mutex is held.
|
||||
**
|
||||
** sqlite3VXPrintf() might ask for *temporary* memory allocations for
|
||||
** sqlite3_str_vappendf() might ask for *temporary* memory allocations for
|
||||
** certain format characters (%q) or for very large precisions or widths.
|
||||
** Care must be taken that any sqlite3_log() calls that occur while the
|
||||
** memory mutex is held do not use these mechanisms.
|
||||
@@ -1131,7 +1185,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
|
||||
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
|
||||
|
||||
sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
|
||||
sqlite3VXPrintf(&acc, zFormat, ap);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
|
||||
sqlite3StrAccumFinish(&acc));
|
||||
}
|
||||
@@ -1160,7 +1214,7 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
|
||||
char zBuf[500];
|
||||
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
||||
va_start(ap,zFormat);
|
||||
sqlite3VXPrintf(&acc, zFormat, ap);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
va_end(ap);
|
||||
sqlite3StrAccumFinish(&acc);
|
||||
#ifdef SQLITE_OS_TRACE_PROC
|
||||
@@ -1177,12 +1231,12 @@ void sqlite3DebugPrintf(const char *zFormat, ...){
|
||||
|
||||
|
||||
/*
|
||||
** variable-argument wrapper around sqlite3VXPrintf(). The bFlags argument
|
||||
** variable-argument wrapper around sqlite3_str_vappendf(). The bFlags argument
|
||||
** can contain the bit SQLITE_PRINTF_INTERNAL enable internal formats.
|
||||
*/
|
||||
void sqlite3XPrintf(StrAccum *p, const char *zFormat, ...){
|
||||
void sqlite3_str_appendf(StrAccum *p, const char *zFormat, ...){
|
||||
va_list ap;
|
||||
va_start(ap,zFormat);
|
||||
sqlite3VXPrintf(p, zFormat, ap);
|
||||
sqlite3_str_vappendf(p, zFormat, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
+24
-21
@@ -75,29 +75,31 @@ static void resolveAlias(
|
||||
assert( pOrig!=0 );
|
||||
db = pParse->db;
|
||||
pDup = sqlite3ExprDup(db, pOrig, 0);
|
||||
if( pDup==0 ) return;
|
||||
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
|
||||
if( pExpr->op==TK_COLLATE ){
|
||||
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
|
||||
}
|
||||
ExprSetProperty(pDup, EP_Alias);
|
||||
if( pDup!=0 ){
|
||||
if( zType[0]!='G' ) incrAggFunctionDepth(pDup, nSubquery);
|
||||
if( pExpr->op==TK_COLLATE ){
|
||||
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
|
||||
}
|
||||
ExprSetProperty(pDup, EP_Alias);
|
||||
|
||||
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
||||
** prevents ExprDelete() from deleting the Expr structure itself,
|
||||
** allowing it to be repopulated by the memcpy() on the following line.
|
||||
** The pExpr->u.zToken might point into memory that will be freed by the
|
||||
** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
|
||||
** make a copy of the token before doing the sqlite3DbFree().
|
||||
*/
|
||||
ExprSetProperty(pExpr, EP_Static);
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
memcpy(pExpr, pDup, sizeof(*pExpr));
|
||||
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
|
||||
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
||||
pExpr->flags |= EP_MemToken;
|
||||
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
|
||||
** prevents ExprDelete() from deleting the Expr structure itself,
|
||||
** allowing it to be repopulated by the memcpy() on the following line.
|
||||
** The pExpr->u.zToken might point into memory that will be freed by the
|
||||
** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to
|
||||
** make a copy of the token before doing the sqlite3DbFree().
|
||||
*/
|
||||
ExprSetProperty(pExpr, EP_Static);
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
memcpy(pExpr, pDup, sizeof(*pExpr));
|
||||
if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){
|
||||
assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 );
|
||||
pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken);
|
||||
pExpr->flags |= EP_MemToken;
|
||||
}
|
||||
sqlite3DbFree(db, pDup);
|
||||
}
|
||||
sqlite3DbFree(db, pDup);
|
||||
ExprSetProperty(pExpr, EP_Alias);
|
||||
}
|
||||
|
||||
|
||||
@@ -349,6 +351,7 @@ static int lookupName(
|
||||
testcase( iCol==(-1) );
|
||||
pExpr->iTable = pNC->uNC.pUpsert->regData + iCol;
|
||||
eNewExprOp = TK_REGISTER;
|
||||
ExprSetProperty(pExpr, EP_Alias);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_UPSERT */
|
||||
{
|
||||
|
||||
+391
-324
File diff suppressed because it is too large
Load Diff
+327
-180
File diff suppressed because it is too large
Load Diff
+246
-6
@@ -504,6 +504,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_IOERR_COMMIT_ATOMIC (SQLITE_IOERR | (30<<8))
|
||||
#define SQLITE_IOERR_ROLLBACK_ATOMIC (SQLITE_IOERR | (31<<8))
|
||||
#define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8))
|
||||
#define SQLITE_LOCKED_VTAB (SQLITE_LOCKED | (2<<8))
|
||||
#define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8))
|
||||
#define SQLITE_BUSY_SNAPSHOT (SQLITE_BUSY | (2<<8))
|
||||
#define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8))
|
||||
@@ -511,6 +512,7 @@ int sqlite3_exec(
|
||||
#define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8))
|
||||
#define SQLITE_CANTOPEN_CONVPATH (SQLITE_CANTOPEN | (4<<8))
|
||||
#define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8))
|
||||
#define SQLITE_CORRUPT_SEQUENCE (SQLITE_CORRUPT | (2<<8))
|
||||
#define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8))
|
||||
#define SQLITE_READONLY_CANTLOCK (SQLITE_READONLY | (2<<8))
|
||||
#define SQLITE_READONLY_ROLLBACK (SQLITE_READONLY | (3<<8))
|
||||
@@ -2112,6 +2114,21 @@ struct sqlite3_mem_methods {
|
||||
** 0 or 1 to indicate whether output-for-triggers has been disabled - 0 if
|
||||
** it is not disabled, 1 if it is.
|
||||
** </dd>
|
||||
**
|
||||
** <dt>SQLITE_DBCONFIG_RESET_DATABASE</dt>
|
||||
** <dd> Set the SQLITE_DBCONFIG_RESET_DATABASE flag and then run
|
||||
** [VACUUM] in order to reset a database back to an empty database
|
||||
** with no schema and no content. The following process works even for
|
||||
** a badly corrupted database file:
|
||||
** <ol>
|
||||
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0);
|
||||
** <li> [sqlite3_exec](db, "[VACUUM]", 0, 0, 0);
|
||||
** <li> sqlite3_db_config(db, SQLITE_DBCONFIG_RESET_DATABASE, 0, 0);
|
||||
** </ol>
|
||||
** Because resetting a database is destructive and irreversible, the
|
||||
** process requires the use of this obscure API and multiple steps to help
|
||||
** ensure that it does not happen by accident.
|
||||
** </dd>
|
||||
** </dl>
|
||||
*/
|
||||
#define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */
|
||||
@@ -2123,7 +2140,8 @@ struct sqlite3_mem_methods {
|
||||
#define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */
|
||||
#define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */
|
||||
#define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1008 /* Largest DBCONFIG */
|
||||
#define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */
|
||||
#define SQLITE_DBCONFIG_MAX 1009 /* Largest DBCONFIG */
|
||||
|
||||
/*
|
||||
** CAPI3REF: Enable Or Disable Extended Result Codes
|
||||
@@ -5509,6 +5527,41 @@ SQLITE_EXTERN char *sqlite3_temp_directory;
|
||||
*/
|
||||
SQLITE_EXTERN char *sqlite3_data_directory;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Win32 Specific Interface
|
||||
**
|
||||
** These interfaces are available only on Windows. The
|
||||
** [sqlite3_win32_set_directory] interface is used to set the value associated
|
||||
** with the [sqlite3_temp_directory] or [sqlite3_data_directory] variable, to
|
||||
** zValue, depending on the value of the type parameter. The zValue parameter
|
||||
** should be NULL to cause the previous value to be freed via [sqlite3_free];
|
||||
** a non-NULL value will be copied into memory obtained from [sqlite3_malloc]
|
||||
** prior to being used. The [sqlite3_win32_set_directory] interface returns
|
||||
** [SQLITE_OK] to indicate success, [SQLITE_ERROR] if the type is unsupported,
|
||||
** or [SQLITE_NOMEM] if memory could not be allocated. The value of the
|
||||
** [sqlite3_data_directory] variable is intended to act as a replacement for
|
||||
** the current directory on the sub-platforms of Win32 where that concept is
|
||||
** not present, e.g. WinRT and UWP. The [sqlite3_win32_set_directory8] and
|
||||
** [sqlite3_win32_set_directory16] interfaces behave exactly the same as the
|
||||
** sqlite3_win32_set_directory interface except the string parameter must be
|
||||
** UTF-8 or UTF-16, respectively.
|
||||
*/
|
||||
int sqlite3_win32_set_directory(
|
||||
unsigned long type, /* Identifier for directory being set or reset */
|
||||
void *zValue /* New value for directory being set or reset */
|
||||
);
|
||||
int sqlite3_win32_set_directory8(unsigned long type, const char *zValue);
|
||||
int sqlite3_win32_set_directory16(unsigned long type, const void *zValue);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Win32 Directory Types
|
||||
**
|
||||
** These macros are only available on Windows. They define the allowed values
|
||||
** for the type argument to the [sqlite3_win32_set_directory] interface.
|
||||
*/
|
||||
#define SQLITE_WIN32_DATA_DIRECTORY_TYPE 1
|
||||
#define SQLITE_WIN32_TEMP_DIRECTORY_TYPE 2
|
||||
|
||||
/*
|
||||
** CAPI3REF: Test For Auto-Commit Mode
|
||||
** KEYWORDS: {autocommit mode}
|
||||
@@ -6241,6 +6294,10 @@ struct sqlite3_index_info {
|
||||
|
||||
/*
|
||||
** CAPI3REF: Virtual Table Scan Flags
|
||||
**
|
||||
** Virtual table implementations are allowed to set the
|
||||
** [sqlite3_index_info].idxFlags field to some combination of
|
||||
** these bits.
|
||||
*/
|
||||
#define SQLITE_INDEX_SCAN_UNIQUE 1 /* Scan visits at most 1 row */
|
||||
|
||||
@@ -7016,7 +7073,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_ALWAYS 13
|
||||
#define SQLITE_TESTCTRL_RESERVE 14
|
||||
#define SQLITE_TESTCTRL_OPTIMIZATIONS 15
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16
|
||||
#define SQLITE_TESTCTRL_ISKEYWORD 16 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
||||
@@ -7030,6 +7087,189 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_PARSER_COVERAGE 26
|
||||
#define SQLITE_TESTCTRL_LAST 26 /* Largest TESTCTRL */
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQL Keyword Checking
|
||||
**
|
||||
** These routines provide access to the set of SQL language keywords
|
||||
** recognized by SQLite. Applications can uses these routines to determine
|
||||
** whether or not a specific identifier needs to be escaped (for example,
|
||||
** by enclosing in double-quotes) so as not to confuse the parser.
|
||||
**
|
||||
** The sqlite3_keyword_count() interface returns the number of distinct
|
||||
** keywords understood by SQLite.
|
||||
**
|
||||
** The sqlite3_keyword_name(N,Z,L) interface finds the N-th keyword and
|
||||
** makes *Z point to that keyword expressed as UTF8 and writes the number
|
||||
** of bytes in the keyword into *L. The string that *Z points to is not
|
||||
** zero-terminated. The sqlite3_keyword_name(N,Z,L) routine returns
|
||||
** SQLITE_OK if N is within bounds and SQLITE_ERROR if not. If either Z
|
||||
** or L are NULL or invalid pointers then calls to
|
||||
** sqlite3_keyword_name(N,Z,L) result in undefined behavior.
|
||||
**
|
||||
** The sqlite3_keyword_check(Z,L) interface checks to see whether or not
|
||||
** the L-byte UTF8 identifier that Z points to is a keyword, returning non-zero
|
||||
** if it is and zero if not.
|
||||
**
|
||||
** The parser used by SQLite is forgiving. It is often possible to use
|
||||
** a keyword as an identifier as long as such use does not result in a
|
||||
** parsing ambiguity. For example, the statement
|
||||
** "CREATE TABLE BEGIN(REPLACE,PRAGMA,END);" is accepted by SQLite, and
|
||||
** creates a new table named "BEGIN" with three columns named
|
||||
** "REPLACE", "PRAGMA", and "END". Nevertheless, best practice is to avoid
|
||||
** using keywords as identifiers. Common techniques used to avoid keyword
|
||||
** name collisions include:
|
||||
** <ul>
|
||||
** <li> Put all identifier names inside double-quotes. This is the official
|
||||
** SQL way to escape identifier names.
|
||||
** <li> Put identifier names inside [...]. This is not standard SQL,
|
||||
** but it is what SQL Server does and so lots of programmers use this
|
||||
** technique.
|
||||
** <li> Begin every identifier with the letter "Z" as no SQL keywords start
|
||||
** with "Z".
|
||||
** <li> Include a digit somewhere in every identifier name.
|
||||
** </ul>
|
||||
**
|
||||
** Note that the number of keywords understood by SQLite can depend on
|
||||
** compile-time options. For example, "VACUUM" is not a keyword if
|
||||
** SQLite is compiled with the [-DSQLITE_OMIT_VACUUM] option. Also,
|
||||
** new keywords may be added to future releases of SQLite.
|
||||
*/
|
||||
int sqlite3_keyword_count(void);
|
||||
int sqlite3_keyword_name(int,const char**,int*);
|
||||
int sqlite3_keyword_check(const char*,int);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Dynamic String Object
|
||||
** KEYWORDS: {dynamic string}
|
||||
**
|
||||
** An instance of the sqlite3_str object contains a dynamically-sized
|
||||
** string under construction.
|
||||
**
|
||||
** The lifecycle of an sqlite3_str object is as follows:
|
||||
** <ol>
|
||||
** <li> ^The sqlite3_str object is created using [sqlite3_str_new()].
|
||||
** <li> ^Text is appended to the sqlite3_str object using various
|
||||
** methods, such as [sqlite3_str_appendf()].
|
||||
** <li> ^The sqlite3_str object is destroyed and the string it created
|
||||
** is returned using the [sqlite3_str_finish()] interface.
|
||||
** </ol>
|
||||
*/
|
||||
typedef struct sqlite3_str sqlite3_str;
|
||||
|
||||
/*
|
||||
** CAPI3REF: Create A New Dynamic String Object
|
||||
** CONSTRUCTOR: sqlite3_str
|
||||
**
|
||||
** ^The [sqlite3_str_new(D)] interface allocates and initializes
|
||||
** a new [sqlite3_str] object. To avoid memory leaks, the object returned by
|
||||
** [sqlite3_str_new()] must be freed by a subsequent call to
|
||||
** [sqlite3_str_finish(X)].
|
||||
**
|
||||
** ^The [sqlite3_str_new(D)] interface always returns a pointer to a
|
||||
** valid [sqlite3_str] object, though in the event of an out-of-memory
|
||||
** error the returned object might be a special singleton that will
|
||||
** silently reject new text, always return SQLITE_NOMEM from
|
||||
** [sqlite3_str_errcode()], always return 0 for
|
||||
** [sqlite3_str_length()], and always return NULL from
|
||||
** [sqlite3_str_finish(X)]. It is always safe to use the value
|
||||
** returned by [sqlite3_str_new(D)] as the sqlite3_str parameter
|
||||
** to any of the other [sqlite3_str] methods.
|
||||
**
|
||||
** The D parameter to [sqlite3_str_new(D)] may be NULL. If the
|
||||
** D parameter in [sqlite3_str_new(D)] is not NULL, then the maximum
|
||||
** length of the string contained in the [sqlite3_str] object will be
|
||||
** the value set for [sqlite3_limit](D,[SQLITE_LIMIT_LENGTH]) instead
|
||||
** of [SQLITE_MAX_LENGTH].
|
||||
*/
|
||||
sqlite3_str *sqlite3_str_new(sqlite3*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Finalize A Dynamic String
|
||||
** DESTRUCTOR: sqlite3_str
|
||||
**
|
||||
** ^The [sqlite3_str_finish(X)] interface destroys the sqlite3_str object X
|
||||
** and returns a pointer to a memory buffer obtained from [sqlite3_malloc64()]
|
||||
** that contains the constructed string. The calling application should
|
||||
** pass the returned value to [sqlite3_free()] to avoid a memory leak.
|
||||
** ^The [sqlite3_str_finish(X)] interface may return a NULL pointer if any
|
||||
** errors were encountered during construction of the string. ^The
|
||||
** [sqlite3_str_finish(X)] interface will also return a NULL pointer if the
|
||||
** string in [sqlite3_str] object X is zero bytes long.
|
||||
*/
|
||||
char *sqlite3_str_finish(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Add Content To A Dynamic String
|
||||
** METHOD: sqlite3_str
|
||||
**
|
||||
** These interfaces add content to an sqlite3_str object previously obtained
|
||||
** from [sqlite3_str_new()].
|
||||
**
|
||||
** ^The [sqlite3_str_appendf(X,F,...)] and
|
||||
** [sqlite3_str_vappendf(X,F,V)] interfaces uses the [built-in printf]
|
||||
** functionality of SQLite to append formatted text onto the end of
|
||||
** [sqlite3_str] object X.
|
||||
**
|
||||
** ^The [sqlite3_str_append(X,S,N)] method appends exactly N bytes from string S
|
||||
** onto the end of the [sqlite3_str] object X. N must be non-negative.
|
||||
** S must contain at least N non-zero bytes of content. To append a
|
||||
** zero-terminated string in its entirety, use the [sqlite3_str_appendall()]
|
||||
** method instead.
|
||||
**
|
||||
** ^The [sqlite3_str_appendall(X,S)] method appends the complete content of
|
||||
** zero-terminated string S onto the end of [sqlite3_str] object X.
|
||||
**
|
||||
** ^The [sqlite3_str_appendchar(X,N,C)] method appends N copies of the
|
||||
** single-byte character C onto the end of [sqlite3_str] object X.
|
||||
** ^This method can be used, for example, to add whitespace indentation.
|
||||
**
|
||||
** ^The [sqlite3_str_reset(X)] method resets the string under construction
|
||||
** inside [sqlite3_str] object X back to zero bytes in length.
|
||||
**
|
||||
** These methods do not return a result code. ^If an error occurs, that fact
|
||||
** is recorded in the [sqlite3_str] object and can be recovered by a
|
||||
** subsequent call to [sqlite3_str_errcode(X)].
|
||||
*/
|
||||
void sqlite3_str_appendf(sqlite3_str*, const char *zFormat, ...);
|
||||
void sqlite3_str_vappendf(sqlite3_str*, const char *zFormat, va_list);
|
||||
void sqlite3_str_append(sqlite3_str*, const char *zIn, int N);
|
||||
void sqlite3_str_appendall(sqlite3_str*, const char *zIn);
|
||||
void sqlite3_str_appendchar(sqlite3_str*, int N, char C);
|
||||
void sqlite3_str_reset(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: Status Of A Dynamic String
|
||||
** METHOD: sqlite3_str
|
||||
**
|
||||
** These interfaces return the current status of an [sqlite3_str] object.
|
||||
**
|
||||
** ^If any prior errors have occurred while constructing the dynamic string
|
||||
** in sqlite3_str X, then the [sqlite3_str_errcode(X)] method will return
|
||||
** an appropriate error code. ^The [sqlite3_str_errcode(X)] method returns
|
||||
** [SQLITE_NOMEM] following any out-of-memory error, or
|
||||
** [SQLITE_TOOBIG] if the size of the dynamic string exceeds
|
||||
** [SQLITE_MAX_LENGTH], or [SQLITE_OK] if there have been no errors.
|
||||
**
|
||||
** ^The [sqlite3_str_length(X)] method returns the current length, in bytes,
|
||||
** of the dynamic string under construction in [sqlite3_str] object X.
|
||||
** ^The length returned by [sqlite3_str_length(X)] does not include the
|
||||
** zero-termination byte.
|
||||
**
|
||||
** ^The [sqlite3_str_value(X)] method returns a pointer to the current
|
||||
** content of the dynamic string under construction in X. The value
|
||||
** returned by [sqlite3_str_value(X)] is managed by the sqlite3_str object X
|
||||
** and might be freed or altered by any subsequent method on the same
|
||||
** [sqlite3_str] object. Applications must not used the pointer returned
|
||||
** [sqlite3_str_value(X)] after any subsequent method call on the same
|
||||
** object. ^Applications may change the content of the string returned
|
||||
** by [sqlite3_str_value(X)] as long as they do not write into any bytes
|
||||
** outside the range of 0 to [sqlite3_str_length(X)] and do not read or
|
||||
** write any byte after any subsequent sqlite3_str method call.
|
||||
*/
|
||||
int sqlite3_str_errcode(sqlite3_str*);
|
||||
int sqlite3_str_length(sqlite3_str*);
|
||||
char *sqlite3_str_value(sqlite3_str*);
|
||||
|
||||
/*
|
||||
** CAPI3REF: SQLite Runtime Status
|
||||
**
|
||||
@@ -8299,11 +8539,11 @@ int sqlite3_vtab_on_conflict(sqlite3 *);
|
||||
** method of a [virtual table], then it returns true if and only if the
|
||||
** column is being fetched as part of an UPDATE operation during which the
|
||||
** column value will not change. Applications might use this to substitute
|
||||
** a lighter-weight value to return that the corresponding [xUpdate] method
|
||||
** understands as a "no-change" value.
|
||||
** a return value that is less expensive to compute and that the corresponding
|
||||
** [xUpdate] method understands as a "no-change" value.
|
||||
**
|
||||
** If the [xColumn] method calls sqlite3_vtab_nochange() and finds that
|
||||
** the column is not changed by the UPDATE statement, they the xColumn
|
||||
** the column is not changed by the UPDATE statement, then the xColumn
|
||||
** method can optionally return without setting a result, without calling
|
||||
** any of the [sqlite3_result_int|sqlite3_result_xxxxx() interfaces].
|
||||
** In that case, [sqlite3_value_nochange(X)] will return true for the
|
||||
@@ -8798,7 +9038,7 @@ SQLITE_EXPERIMENTAL int sqlite3_snapshot_recover(sqlite3 *db, const char *zDb);
|
||||
** been a prior call to [sqlite3_deserialize(D,S,...)] with the same
|
||||
** values of D and S.
|
||||
** The size of the database is written into *P even if the
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contigious copy
|
||||
** SQLITE_SERIALIZE_NOCOPY bit is set but no contiguous copy
|
||||
** of the database exists.
|
||||
**
|
||||
** A call to sqlite3_serialize(D,S,P,F) might return NULL even if the
|
||||
|
||||
@@ -295,6 +295,21 @@ struct sqlite3_api_routines {
|
||||
int (*vtab_nochange)(sqlite3_context*);
|
||||
int (*value_nochange)(sqlite3_value*);
|
||||
const char *(*vtab_collation)(sqlite3_index_info*,int);
|
||||
/* Version 3.24.0 and later */
|
||||
int (*keyword_count)(void);
|
||||
int (*keyword_name)(int,const char**,int*);
|
||||
int (*keyword_check)(const char*,int);
|
||||
sqlite3_str *(*str_new)(sqlite3*);
|
||||
char *(*str_finish)(sqlite3_str*);
|
||||
void (*str_appendf)(sqlite3_str*, const char *zFormat, ...);
|
||||
void (*str_vappendf)(sqlite3_str*, const char *zFormat, va_list);
|
||||
void (*str_append)(sqlite3_str*, const char *zIn, int N);
|
||||
void (*str_appendall)(sqlite3_str*, const char *zIn);
|
||||
void (*str_appendchar)(sqlite3_str*, int N, char C);
|
||||
void (*str_reset)(sqlite3_str*);
|
||||
int (*str_errcode)(sqlite3_str*);
|
||||
int (*str_length)(sqlite3_str*);
|
||||
char *(*str_value)(sqlite3_str*);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -565,6 +580,21 @@ typedef int (*sqlite3_loadext_entry)(
|
||||
#define sqlite3_vtab_nochange sqlite3_api->vtab_nochange
|
||||
#define sqlite3_value_nochange sqlite3_api->value_nochange
|
||||
#define sqlite3_vtab_collation sqlite3_api->vtab_collation
|
||||
/* Version 3.24.0 and later */
|
||||
#define sqlite3_keyword_count sqlite3_api->keyword_count
|
||||
#define sqlite3_keyword_name sqlite3_api->keyword_name
|
||||
#define sqlite3_keyword_check sqlite3_api->keyword_check
|
||||
#define sqlite3_str_new sqlite3_api->str_new
|
||||
#define sqlite3_str_finish sqlite3_api->str_finish
|
||||
#define sqlite3_str_appendf sqlite3_api->str_appendf
|
||||
#define sqlite3_str_vappendf sqlite3_api->str_vappendf
|
||||
#define sqlite3_str_append sqlite3_api->str_append
|
||||
#define sqlite3_str_appendall sqlite3_api->str_appendall
|
||||
#define sqlite3_str_appendchar sqlite3_api->str_appendchar
|
||||
#define sqlite3_str_reset sqlite3_api->str_reset
|
||||
#define sqlite3_str_errcode sqlite3_api->str_errcode
|
||||
#define sqlite3_str_length sqlite3_api->str_length
|
||||
#define sqlite3_str_value sqlite3_api->str_value
|
||||
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)
|
||||
|
||||
+14
-28
@@ -1093,7 +1093,7 @@ typedef struct Select Select;
|
||||
typedef struct SQLiteThread SQLiteThread;
|
||||
typedef struct SelectDest SelectDest;
|
||||
typedef struct SrcList SrcList;
|
||||
typedef struct StrAccum StrAccum;
|
||||
typedef struct sqlite3_str StrAccum; /* Internal alias for sqlite3_str */
|
||||
typedef struct Table Table;
|
||||
typedef struct TableLock TableLock;
|
||||
typedef struct Token Token;
|
||||
@@ -1362,7 +1362,7 @@ struct sqlite3 {
|
||||
u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */
|
||||
u8 isTransactionSavepoint; /* True if the outermost savepoint is a TS */
|
||||
u8 mTrace; /* zero or more SQLITE_TRACE flags */
|
||||
u8 skipBtreeMutex; /* True if no shared-cache backends */
|
||||
u8 noSharedCache; /* True if no shared-cache backends */
|
||||
u8 nSqlExec; /* Number of pending OP_SqlExec opcodes */
|
||||
int nextPagesize; /* Pagesize after VACUUM if >0 */
|
||||
u32 magic; /* Magic number for detect library misuse */
|
||||
@@ -1506,6 +1506,7 @@ struct sqlite3 {
|
||||
#define SQLITE_Fts3Tokenizer 0x00400000 /* Enable fts3_tokenizer(2) */
|
||||
#define SQLITE_EnableQPSG 0x00800000 /* Query Planner Stability Guarantee*/
|
||||
#define SQLITE_TriggerEQP 0x01000000 /* Show trigger EXPLAIN QUERY PLAN */
|
||||
#define SQLITE_ResetDatabase 0x02000000 /* Reset the database */
|
||||
|
||||
/* Flags used only if debugging */
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -1522,6 +1523,7 @@ struct sqlite3 {
|
||||
#define DBFLAG_SchemaChange 0x0001 /* Uncommitted Hash table changes */
|
||||
#define DBFLAG_PreferBuiltin 0x0002 /* Preference to built-in funcs */
|
||||
#define DBFLAG_Vacuum 0x0004 /* Currently in a VACUUM */
|
||||
#define DBFLAG_SchemaKnownOk 0x0008 /* Schema is known to be valid */
|
||||
|
||||
/*
|
||||
** Bits of the sqlite3.dbOptFlags field that are used by the
|
||||
@@ -2607,9 +2609,6 @@ struct SrcList {
|
||||
unsigned viaCoroutine :1; /* Implemented as a co-routine */
|
||||
unsigned isRecursive :1; /* True for recursive reference in WITH */
|
||||
} fg;
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */
|
||||
#endif
|
||||
int iCursor; /* The VDBE cursor number used to access this table */
|
||||
Expr *pOn; /* The ON clause of a join */
|
||||
IdList *pUsing; /* The USING clause of a join */
|
||||
@@ -2740,13 +2739,13 @@ struct NameContext {
|
||||
struct Upsert {
|
||||
ExprList *pUpsertTarget; /* Optional description of conflicting index */
|
||||
Expr *pUpsertTargetWhere; /* WHERE clause for partial index targets */
|
||||
Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
|
||||
ExprList *pUpsertSet; /* The SET clause from an ON CONFLICT UPDATE */
|
||||
Expr *pUpsertWhere; /* WHERE clause for the ON CONFLICT UPDATE */
|
||||
/* The fields above comprise the parse tree for the upsert clause.
|
||||
** The fields below are used to transfer information from the INSERT
|
||||
** processing down into the UPDATE processing while generating code.
|
||||
** Upsert owns the memory allocated above, but not the memory below. */
|
||||
Index *pUpsertIdx; /* Constraint that pUpsertTarget identifies */
|
||||
SrcList *pUpsertSrc; /* Table to be updated */
|
||||
int regData; /* First register holding array of VALUES */
|
||||
int iDataCur; /* Index of the data cursor */
|
||||
@@ -2757,11 +2756,8 @@ struct Upsert {
|
||||
** An instance of the following structure contains all information
|
||||
** needed to generate code for a single SELECT statement.
|
||||
**
|
||||
** nLimit is set to -1 if there is no LIMIT clause. nOffset is set to 0.
|
||||
** If there is a LIMIT clause, the parser sets nLimit to the value of the
|
||||
** limit and nOffset to the value of the offset (or 0 if there is not
|
||||
** offset). But later on, nLimit and nOffset become the memory locations
|
||||
** in the VDBE that record the limit and offset counters.
|
||||
** See the header comment on the computeLimitRegisters() routine for a
|
||||
** detailed description of the meaning of the iLimit and iOffset fields.
|
||||
**
|
||||
** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
|
||||
** These addresses must be stored so that we can go back and fill in
|
||||
@@ -2821,8 +2817,7 @@ struct Select {
|
||||
#define SF_MaybeConvert 0x08000 /* Need convertCompoundSelectToSubquery() */
|
||||
#define SF_Converted 0x10000 /* By convertCompoundSelectToSubquery() */
|
||||
#define SF_IncludeHidden 0x20000 /* Include hidden columns in output */
|
||||
#define SF_ComplexResult 0x40000 /* Result set contains subquery or function */
|
||||
|
||||
#define SF_ComplexResult 0x40000 /* Result contains subquery or function */
|
||||
|
||||
/*
|
||||
** The results of a SELECT can be distributed in several ways, as defined
|
||||
@@ -3092,8 +3087,7 @@ struct Parse {
|
||||
#endif
|
||||
int nHeight; /* Expression tree height of current sub-select */
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
int iSelectId; /* ID of current select for EXPLAIN output */
|
||||
int iNextSelectId; /* Next available select ID for EXPLAIN output */
|
||||
int addrExplain; /* Address of current OP_Explain opcode */
|
||||
#endif
|
||||
VList *pVList; /* Mapping between variable names and numbers */
|
||||
Vdbe *pReprepare; /* VM being reprepared (sqlite3Reprepare()) */
|
||||
@@ -3279,17 +3273,15 @@ struct DbFixer {
|
||||
** An objected used to accumulate the text of a string where we
|
||||
** do not necessarily know how big the string will be in the end.
|
||||
*/
|
||||
struct StrAccum {
|
||||
struct sqlite3_str {
|
||||
sqlite3 *db; /* Optional database for lookaside. Can be NULL */
|
||||
char *zText; /* The string collected so far */
|
||||
u32 nAlloc; /* Amount of space allocated in zText */
|
||||
u32 mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
|
||||
u32 nChar; /* Length of the string so far */
|
||||
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
|
||||
u8 accError; /* SQLITE_NOMEM or SQLITE_TOOBIG */
|
||||
u8 printfFlags; /* SQLITE_PRINTF flags below */
|
||||
};
|
||||
#define STRACCUM_NOMEM 1
|
||||
#define STRACCUM_TOOBIG 2
|
||||
#define SQLITE_PRINTF_INTERNAL 0x01 /* Internal-use-only converters allowed */
|
||||
#define SQLITE_PRINTF_SQLFUNC 0x02 /* SQL function arguments to VXPrintf */
|
||||
#define SQLITE_PRINTF_MALLOCED 0x04 /* True if xText is allocated space */
|
||||
@@ -3658,8 +3650,6 @@ struct PrintfArguments {
|
||||
sqlite3_value **apArg; /* The argument values */
|
||||
};
|
||||
|
||||
void sqlite3VXPrintf(StrAccum*, const char*, va_list);
|
||||
void sqlite3XPrintf(StrAccum*, const char*, ...);
|
||||
char *sqlite3MPrintf(sqlite3*,const char*, ...);
|
||||
char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
|
||||
#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
|
||||
@@ -4176,17 +4166,14 @@ int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
|
||||
void (*)(sqlite3_context*,int,sqlite3_value **), void (*)(sqlite3_context*),
|
||||
FuncDestructor *pDestructor
|
||||
);
|
||||
void sqlite3NoopDestructor(void*);
|
||||
void sqlite3OomFault(sqlite3*);
|
||||
void sqlite3OomClear(sqlite3*);
|
||||
int sqlite3ApiExit(sqlite3 *db, int);
|
||||
int sqlite3OpenTempDatabase(Parse *);
|
||||
|
||||
void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
|
||||
void sqlite3StrAccumAppend(StrAccum*,const char*,int);
|
||||
void sqlite3StrAccumAppendAll(StrAccum*,const char*);
|
||||
void sqlite3AppendChar(StrAccum*,int,char);
|
||||
char *sqlite3StrAccumFinish(StrAccum*);
|
||||
void sqlite3StrAccumReset(StrAccum*);
|
||||
void sqlite3SelectDestInit(SelectDest*,int,int);
|
||||
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);
|
||||
|
||||
@@ -4213,10 +4200,10 @@ char sqlite3IndexColumnAffinity(sqlite3*, Index*, int);
|
||||
** The interface to the LEMON-generated parser
|
||||
*/
|
||||
#ifndef SQLITE_AMALGAMATION
|
||||
void *sqlite3ParserAlloc(void*(*)(u64));
|
||||
void *sqlite3ParserAlloc(void*(*)(u64), Parse*);
|
||||
void sqlite3ParserFree(void*, void(*)(void*));
|
||||
#endif
|
||||
void sqlite3Parser(void*, int, Token, Parse*);
|
||||
void sqlite3Parser(void*, int, Token);
|
||||
#ifdef YYTRACKMAXSTACKDEPTH
|
||||
int sqlite3ParserStackPeak(void*);
|
||||
#endif
|
||||
@@ -4282,7 +4269,6 @@ int sqlite3VtabCallConnect(Parse*, Table*);
|
||||
int sqlite3VtabCallDestroy(sqlite3*, int, const char *);
|
||||
int sqlite3VtabBegin(sqlite3 *, VTable *);
|
||||
FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*);
|
||||
void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
|
||||
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
|
||||
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
|
||||
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
|
||||
|
||||
@@ -7418,6 +7418,8 @@ static int SQLITE_TCLAPI test_sqlite3_db_config(
|
||||
{ "LOAD_EXTENSION", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION },
|
||||
{ "NO_CKPT_ON_CLOSE",SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE },
|
||||
{ "QPSG", SQLITE_DBCONFIG_ENABLE_QPSG },
|
||||
{ "TRIGGER_EQP", SQLITE_DBCONFIG_TRIGGER_EQP },
|
||||
{ "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE },
|
||||
};
|
||||
int i;
|
||||
int v;
|
||||
|
||||
@@ -32,6 +32,8 @@ static struct MemFault {
|
||||
int nRepeat; /* Number of times to repeat the failure */
|
||||
int nBenign; /* Number of benign failures seen since last config */
|
||||
int nFail; /* Number of failures seen since last config */
|
||||
int nOkBefore; /* Successful allocations prior to the first fault */
|
||||
int nOkAfter; /* Successful allocations after a fault */
|
||||
u8 enable; /* True if enabled */
|
||||
int isInstalled; /* True if the fault simulation layer is installed */
|
||||
int isBenignMode; /* True if malloc failures are considered benign */
|
||||
@@ -47,18 +49,32 @@ static void sqlite3Fault(void){
|
||||
cnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
** This routine exists as a place to set a breakpoint that will
|
||||
** fire the first time any malloc() fails on a single test case.
|
||||
** The sqlite3Fault() routine above runs on every malloc() failure.
|
||||
** This routine only runs on the first such failure.
|
||||
*/
|
||||
static void sqlite3FirstFault(void){
|
||||
static int cnt2 = 0;
|
||||
cnt2++;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check to see if a fault should be simulated. Return true to simulate
|
||||
** the fault. Return false if the fault should not be simulated.
|
||||
*/
|
||||
static int faultsimStep(void){
|
||||
if( likely(!memfault.enable) ){
|
||||
memfault.nOkAfter++;
|
||||
return 0;
|
||||
}
|
||||
if( memfault.iCountdown>0 ){
|
||||
memfault.iCountdown--;
|
||||
memfault.nOkBefore++;
|
||||
return 0;
|
||||
}
|
||||
if( memfault.nFail==0 ) sqlite3FirstFault();
|
||||
sqlite3Fault();
|
||||
memfault.nFail++;
|
||||
if( memfault.isBenignMode>0 ){
|
||||
@@ -133,6 +149,8 @@ static void faultsimConfig(int nDelay, int nRepeat){
|
||||
memfault.nRepeat = nRepeat;
|
||||
memfault.nBenign = 0;
|
||||
memfault.nFail = 0;
|
||||
memfault.nOkBefore = 0;
|
||||
memfault.nOkAfter = 0;
|
||||
memfault.enable = nDelay>=0;
|
||||
|
||||
/* Sometimes, when running multi-threaded tests, the isBenignMode
|
||||
|
||||
+3
-3
@@ -496,9 +496,9 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
/* sqlite3ParserTrace(stdout, "parser: "); */
|
||||
#ifdef sqlite3Parser_ENGINEALWAYSONSTACK
|
||||
pEngine = &sEngine;
|
||||
sqlite3ParserInit(pEngine);
|
||||
sqlite3ParserInit(pEngine, pParse);
|
||||
#else
|
||||
pEngine = sqlite3ParserAlloc(sqlite3Malloc);
|
||||
pEngine = sqlite3ParserAlloc(sqlite3Malloc, pParse);
|
||||
if( pEngine==0 ){
|
||||
sqlite3OomFault(db);
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
@@ -542,7 +542,7 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
|
||||
}else{
|
||||
pParse->sLastToken.z = zSql;
|
||||
pParse->sLastToken.n = n;
|
||||
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse);
|
||||
sqlite3Parser(pEngine, tokenType, pParse->sLastToken);
|
||||
lastTokenParsed = tokenType;
|
||||
zSql += n;
|
||||
if( pParse->rc!=SQLITE_OK || db->mallocFailed ) break;
|
||||
|
||||
+32
-25
@@ -58,15 +58,17 @@ static void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
|
||||
sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
|
||||
if( p ){
|
||||
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
|
||||
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
|
||||
sqlite3_str_append(&acc, p->bLine[i] ? "| " : " ", 4);
|
||||
}
|
||||
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
|
||||
sqlite3_str_append(&acc, p->bLine[i] ? "|-- " : "'-- ", 4);
|
||||
}
|
||||
if( zFormat!=0 ){
|
||||
va_start(ap, zFormat);
|
||||
sqlite3_str_vappendf(&acc, zFormat, ap);
|
||||
va_end(ap);
|
||||
assert( acc.nChar>0 );
|
||||
sqlite3_str_append(&acc, "\n", 1);
|
||||
}
|
||||
va_start(ap, zFormat);
|
||||
sqlite3VXPrintf(&acc, zFormat, ap);
|
||||
va_end(ap);
|
||||
assert( acc.nChar>0 );
|
||||
if( zBuf[acc.nChar-1]!='\n' ) sqlite3StrAccumAppend(&acc, "\n", 1);
|
||||
sqlite3StrAccumFinish(&acc);
|
||||
fprintf(stdout,"%s", zBuf);
|
||||
fflush(stdout);
|
||||
@@ -99,17 +101,17 @@ void sqlite3TreeViewWith(TreeView *pView, const With *pWith, u8 moreToFollow){
|
||||
char zLine[1000];
|
||||
const struct Cte *pCte = &pWith->a[i];
|
||||
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
||||
sqlite3XPrintf(&x, "%s", pCte->zName);
|
||||
sqlite3_str_appendf(&x, "%s", pCte->zName);
|
||||
if( pCte->pCols && pCte->pCols->nExpr>0 ){
|
||||
char cSep = '(';
|
||||
int j;
|
||||
for(j=0; j<pCte->pCols->nExpr; j++){
|
||||
sqlite3XPrintf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
|
||||
sqlite3_str_appendf(&x, "%c%s", cSep, pCte->pCols->a[j].zName);
|
||||
cSep = ',';
|
||||
}
|
||||
sqlite3XPrintf(&x, ")");
|
||||
sqlite3_str_appendf(&x, ")");
|
||||
}
|
||||
sqlite3XPrintf(&x, " AS");
|
||||
sqlite3_str_appendf(&x, " AS");
|
||||
sqlite3StrAccumFinish(&x);
|
||||
sqlite3TreeViewItem(pView, zLine, i<pWith->nCte-1);
|
||||
sqlite3TreeViewSelect(pView, pCte->pSelect, 0);
|
||||
@@ -174,20 +176,20 @@ void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
|
||||
StrAccum x;
|
||||
char zLine[100];
|
||||
sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
|
||||
sqlite3XPrintf(&x, "{%d,*}", pItem->iCursor);
|
||||
sqlite3_str_appendf(&x, "{%d,*}", pItem->iCursor);
|
||||
if( pItem->zDatabase ){
|
||||
sqlite3XPrintf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
|
||||
sqlite3_str_appendf(&x, " %s.%s", pItem->zDatabase, pItem->zName);
|
||||
}else if( pItem->zName ){
|
||||
sqlite3XPrintf(&x, " %s", pItem->zName);
|
||||
sqlite3_str_appendf(&x, " %s", pItem->zName);
|
||||
}
|
||||
if( pItem->pTab ){
|
||||
sqlite3XPrintf(&x, " tabname=%Q", pItem->pTab->zName);
|
||||
sqlite3_str_appendf(&x, " tabname=%Q", pItem->pTab->zName);
|
||||
}
|
||||
if( pItem->zAlias ){
|
||||
sqlite3XPrintf(&x, " (AS %s)", pItem->zAlias);
|
||||
sqlite3_str_appendf(&x, " (AS %s)", pItem->zAlias);
|
||||
}
|
||||
if( pItem->fg.jointype & JT_LEFT ){
|
||||
sqlite3XPrintf(&x, " LEFT-JOIN");
|
||||
sqlite3_str_appendf(&x, " LEFT-JOIN");
|
||||
}
|
||||
sqlite3StrAccumFinish(&x);
|
||||
sqlite3TreeViewItem(pView, zLine, i<p->pSrc->nSrc-1);
|
||||
@@ -536,16 +538,21 @@ void sqlite3TreeViewBareExprList(
|
||||
for(i=0; i<pList->nExpr; i++){
|
||||
int j = pList->a[i].u.x.iOrderByCol;
|
||||
char *zName = pList->a[i].zName;
|
||||
int moreToFollow = i<pList->nExpr - 1;
|
||||
if( j || zName ){
|
||||
sqlite3TreeViewPush(pView, 0);
|
||||
sqlite3TreeViewPush(pView, moreToFollow);
|
||||
moreToFollow = 0;
|
||||
sqlite3TreeViewLine(pView, 0);
|
||||
if( zName ){
|
||||
fprintf(stdout, "AS %s ", zName);
|
||||
}
|
||||
if( j ){
|
||||
fprintf(stdout, "iOrderByCol=%d", j);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
fflush(stdout);
|
||||
}
|
||||
if( zName ){
|
||||
sqlite3TreeViewLine(pView, "AS %s", zName);
|
||||
}
|
||||
if( j ){
|
||||
sqlite3TreeViewLine(pView, "iOrderByCol=%d", j);
|
||||
}
|
||||
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, i<pList->nExpr-1);
|
||||
sqlite3TreeViewExpr(pView, pList->a[i].pExpr, moreToFollow);
|
||||
if( j || zName ){
|
||||
sqlite3TreeViewPop(pView);
|
||||
}
|
||||
|
||||
+36
-25
@@ -339,7 +339,7 @@ void sqlite3Update(
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v==0 ) goto update_cleanup;
|
||||
if( pParse->nested==0 ) sqlite3VdbeCountChanges(v);
|
||||
sqlite3BeginWriteOperation(pParse, 1, iDb);
|
||||
sqlite3BeginWriteOperation(pParse, pTrigger || hasFK, iDb);
|
||||
|
||||
/* Allocate required registers. */
|
||||
if( !IsVirtual(pTab) ){
|
||||
@@ -391,7 +391,7 @@ void sqlite3Update(
|
||||
#endif
|
||||
|
||||
/* Jump to labelBreak to abandon further processing of this UPDATE */
|
||||
labelBreak = sqlite3VdbeMakeLabel(v);
|
||||
labelContinue = labelBreak = sqlite3VdbeMakeLabel(v);
|
||||
|
||||
/* Not an UPSERT. Normal processing. Begin by
|
||||
** initialize the count of updated rows */
|
||||
@@ -428,7 +428,6 @@ void sqlite3Update(
|
||||
*/
|
||||
pWInfo = 0;
|
||||
eOnePass = ONEPASS_SINGLE;
|
||||
labelContinue = labelBreak;
|
||||
sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL);
|
||||
}else{
|
||||
/* Begin the database scan.
|
||||
@@ -456,12 +455,15 @@ void sqlite3Update(
|
||||
** strategy that uses an index for which one or more columns are being
|
||||
** updated. */
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aiCurOnePass);
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
int iCur = aiCurOnePass[1];
|
||||
if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
|
||||
eOnePass = ONEPASS_OFF;
|
||||
if( eOnePass!=ONEPASS_SINGLE ){
|
||||
sqlite3MultiWrite(pParse);
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
int iCur = aiCurOnePass[1];
|
||||
if( iCur>=0 && iCur!=iDataCur && aToOpen[iCur-iBaseCur] ){
|
||||
eOnePass = ONEPASS_OFF;
|
||||
}
|
||||
assert( iCur!=iDataCur || !HasRowid(pTab) );
|
||||
}
|
||||
assert( iCur!=iDataCur || !HasRowid(pTab) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -523,9 +525,7 @@ void sqlite3Update(
|
||||
sqlite3VdbeAddOp4Int(v, OP_NotFound, iDataCur, labelBreak, regKey,nKey);
|
||||
VdbeCoverageNeverTaken(v);
|
||||
}
|
||||
if( eOnePass==ONEPASS_SINGLE ){
|
||||
labelContinue = labelBreak;
|
||||
}else{
|
||||
if( eOnePass!=ONEPASS_SINGLE ){
|
||||
labelContinue = sqlite3VdbeMakeLabel(v);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, pPk ? regKey : regOldRowid, labelBreak);
|
||||
@@ -611,6 +611,12 @@ void sqlite3Update(
|
||||
testcase( i==31 );
|
||||
testcase( i==32 );
|
||||
sqlite3ExprCodeGetColumnToReg(pParse, pTab, i, iDataCur, regNew+i);
|
||||
if( tmask & TRIGGER_BEFORE ){
|
||||
/* This value will be recomputed in After-BEFORE-trigger-reload-loop
|
||||
** below, so make sure that it is not cached and reused.
|
||||
** Ticket d85fffd6ffe856092ed8daefa811b1e399706b28. */
|
||||
sqlite3ExprCacheRemove(pParse, regNew+i, 1);
|
||||
}
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regNew+i);
|
||||
}
|
||||
@@ -639,10 +645,14 @@ void sqlite3Update(
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
|
||||
/* If it did not delete it, the row-trigger may still have modified
|
||||
/* After-BEFORE-trigger-reload-loop:
|
||||
** If it did not delete it, the BEFORE trigger may still have modified
|
||||
** some of the columns of the row being updated. Load the values for
|
||||
** all columns not modified by the update statement into their
|
||||
** registers in case this has happened.
|
||||
** all columns not modified by the update statement into their registers
|
||||
** in case this has happened. Only unmodified columns are reloaded.
|
||||
** The values computed for modified columns use the values before the
|
||||
** BEFORE trigger runs. See test case trigger1-18.0 (added 2018-04-26)
|
||||
** for an example.
|
||||
*/
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( aXRef[i]<0 && i!=pTab->iPKey ){
|
||||
@@ -755,7 +765,7 @@ void sqlite3Update(
|
||||
** maximum rowid counter values recorded while inserting into
|
||||
** autoincrement tables.
|
||||
*/
|
||||
if( pParse->nested==0 && pParse->pTriggerTab==0 ){
|
||||
if( pParse->nested==0 && pParse->pTriggerTab==0 && pUpsert==0 ){
|
||||
sqlite3AutoincrementEnd(pParse);
|
||||
}
|
||||
|
||||
@@ -835,7 +845,7 @@ static void updateVirtualTable(
|
||||
int regRowid; /* Register for ephem table rowid */
|
||||
int iCsr = pSrc->a[0].iCursor; /* Cursor used for virtual table scan */
|
||||
int aDummy[2]; /* Unused arg for sqlite3WhereOkOnePass() */
|
||||
int bOnePass; /* True to use onepass strategy */
|
||||
int eOnePass; /* True to use onepass strategy */
|
||||
int addr; /* Address of OP_OpenEphemeral */
|
||||
|
||||
/* Allocate nArg registers in which to gather the arguments for VUpdate. Then
|
||||
@@ -880,19 +890,20 @@ static void updateVirtualTable(
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, regArg+2+iPk, regArg+1);
|
||||
}
|
||||
|
||||
bOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
|
||||
eOnePass = sqlite3WhereOkOnePass(pWInfo, aDummy);
|
||||
|
||||
if( bOnePass ){
|
||||
/* There is no ONEPASS_MULTI on virtual tables */
|
||||
assert( eOnePass==ONEPASS_OFF || eOnePass==ONEPASS_SINGLE );
|
||||
|
||||
if( eOnePass ){
|
||||
/* If using the onepass strategy, no-op out the OP_OpenEphemeral coded
|
||||
** above. Also, if this is a top-level parse (not a trigger), clear the
|
||||
** multi-write flag so that the VM does not open a statement journal */
|
||||
** above. */
|
||||
sqlite3VdbeChangeToNoop(v, addr);
|
||||
if( sqlite3IsToplevel(pParse) ){
|
||||
pParse->isMultiWrite = 0;
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_Close, iCsr);
|
||||
}else{
|
||||
/* Create a record from the argument register contents and insert it into
|
||||
** the ephemeral table. */
|
||||
sqlite3MultiWrite(pParse);
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regArg, nArg, regRec);
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Signal an assert() within OP_MakeRecord that it is allowed to
|
||||
@@ -904,7 +915,7 @@ static void updateVirtualTable(
|
||||
}
|
||||
|
||||
|
||||
if( bOnePass==0 ){
|
||||
if( eOnePass==ONEPASS_OFF ){
|
||||
/* End the virtual table scan */
|
||||
sqlite3WhereEnd(pWInfo);
|
||||
|
||||
@@ -924,7 +935,7 @@ static void updateVirtualTable(
|
||||
|
||||
/* End of the ephemeral table scan. Or, if using the onepass strategy,
|
||||
** jump to here if the scan visited zero rows. */
|
||||
if( bOnePass==0 ){
|
||||
if( eOnePass==ONEPASS_OFF ){
|
||||
sqlite3VdbeAddOp2(v, OP_Next, ephemTab, addr+1); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, ephemTab, 0);
|
||||
|
||||
+5
-2
@@ -226,11 +226,14 @@ void sqlite3UpsertDoUpdate(
|
||||
assert( pPk->aiColumn[i]>=0 );
|
||||
k = sqlite3ColumnOfIndex(pIdx, pPk->aiColumn[i]);
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iCur, k, iPk+i);
|
||||
VdbeComment((v, "%s.%s", pIdx->zName, pTab->aCol[i].zName));
|
||||
VdbeComment((v, "%s.%s", pIdx->zName,
|
||||
pTab->aCol[pPk->aiColumn[i]].zName));
|
||||
}
|
||||
sqlite3VdbeVerifyAbortable(v, OE_Abort);
|
||||
i = sqlite3VdbeAddOp4Int(v, OP_Found, iDataCur, 0, iPk, nPk);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_CORRUPT, OE_Abort);
|
||||
sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CORRUPT, OE_Abort, 0,
|
||||
"corrupt database", P4_STATIC);
|
||||
sqlite3VdbeJumpHere(v, i);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-3
@@ -39,8 +39,14 @@ static int execSql(sqlite3 *db, char **pzErrMsg, const char *zSql){
|
||||
while( SQLITE_ROW==(rc = sqlite3_step(pStmt)) ){
|
||||
const char *zSubSql = (const char*)sqlite3_column_text(pStmt,0);
|
||||
assert( sqlite3_strnicmp(zSql,"SELECT",6)==0 );
|
||||
assert( sqlite3_strnicmp(zSubSql,"SELECT",6)!=0 || CORRUPT_DB );
|
||||
if( zSubSql && zSubSql[0]!='S' ){
|
||||
/* The secondary SQL must be one of CREATE TABLE, CREATE INDEX,
|
||||
** or INSERT. Historically there have been attacks that first
|
||||
** corrupt the sqlite_master.sql field with other kinds of statements
|
||||
** then run VACUUM to get those statements to execute at inappropriate
|
||||
** times. */
|
||||
if( zSubSql
|
||||
&& (strncmp(zSubSql,"CRE",3)==0 || strncmp(zSubSql,"INS",3)==0)
|
||||
){
|
||||
rc = execSql(db, pzErrMsg, zSubSql);
|
||||
if( rc!=SQLITE_OK ) break;
|
||||
}
|
||||
@@ -253,7 +259,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
rc = execSqlF(db, pzErrMsg,
|
||||
"SELECT sql FROM \"%w\".sqlite_master"
|
||||
" WHERE type='index' AND length(sql)>10",
|
||||
" WHERE type='index'",
|
||||
zDbMain
|
||||
);
|
||||
if( rc!=SQLITE_OK ) goto end_of_vacuum;
|
||||
|
||||
+43
-9
@@ -915,6 +915,9 @@ case OP_Yield: { /* in1, jump */
|
||||
*/
|
||||
case OP_HaltIfNull: { /* in3 */
|
||||
pIn3 = &aMem[pOp->p3];
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
|
||||
#endif
|
||||
if( (pIn3->flags & MEM_Null)==0 ) break;
|
||||
/* Fall through into OP_Halt */
|
||||
}
|
||||
@@ -954,6 +957,9 @@ case OP_Halt: {
|
||||
int pcx;
|
||||
|
||||
pcx = (int)(pOp - aOp);
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); }
|
||||
#endif
|
||||
if( pOp->p1==SQLITE_OK && p->pFrame ){
|
||||
/* Halt the sub-program. Return control to the parent frame. */
|
||||
pFrame = p->pFrame;
|
||||
@@ -3324,6 +3330,8 @@ case OP_ReadCookie: { /* out2 */
|
||||
*/
|
||||
case OP_SetCookie: {
|
||||
Db *pDb;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
assert( pOp->p2<SQLITE_N_BTREE_META );
|
||||
assert( pOp->p1>=0 && pOp->p1<db->nDb );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p1) );
|
||||
@@ -4287,11 +4295,8 @@ case OP_NewRowid: { /* out2 */
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
if( !pC->isTable ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
assert( pC!=0 );
|
||||
assert( pC->isTable );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( pC->uc.pCursor!=0 );
|
||||
{
|
||||
@@ -4460,6 +4465,7 @@ case OP_InsertInt: {
|
||||
assert( (pOp->p5 & OPFLAG_ISNOOP) || pC->isTable );
|
||||
assert( pOp->p4type==P4_TABLE || pOp->p4type>=P4_STATIC );
|
||||
REGISTER_TRACE(pOp->p2, pData);
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
|
||||
if( pOp->opcode==OP_Insert ){
|
||||
pKey = &aMem[pOp->p3];
|
||||
@@ -4574,6 +4580,7 @@ case OP_Delete: {
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
assert( pC->uc.pCursor!=0 );
|
||||
assert( pC->deferredMoveto==0 );
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( pOp->p4type==P4_TABLE && HasRowid(pOp->p4.pTab) && pOp->p5==0 ){
|
||||
@@ -4742,10 +4749,10 @@ case OP_SorterData: {
|
||||
** If the P1 cursor must be pointing to a valid row (not a NULL row)
|
||||
** of a real table, not a pseudo-table.
|
||||
**
|
||||
** If P3!=0 then this opcode is allowed to make an ephermeral pointer
|
||||
** If P3!=0 then this opcode is allowed to make an ephemeral pointer
|
||||
** into the database page. That means that the content of the output
|
||||
** register will be invalidated as soon as the cursor moves - including
|
||||
** moves caused by other cursors that "save" the the current cursors
|
||||
** moves caused by other cursors that "save" the current cursors
|
||||
** position in order that they can write to the same table. If P3==0
|
||||
** then a copy of the data is made into memory. P3!=0 is faster, but
|
||||
** P3==0 is safer.
|
||||
@@ -5192,6 +5199,7 @@ case OP_IdxInsert: { /* in2 */
|
||||
|
||||
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||
pC = p->apCsr[pOp->p1];
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
assert( pC!=0 );
|
||||
assert( isSorter(pC)==(pOp->opcode==OP_SorterInsert) );
|
||||
pIn2 = &aMem[pOp->p2];
|
||||
@@ -5238,6 +5246,7 @@ case OP_IdxDelete: {
|
||||
pC = p->apCsr[pOp->p1];
|
||||
assert( pC!=0 );
|
||||
assert( pC->eCurType==CURTYPE_BTREE );
|
||||
sqlite3VdbeIncrWriteCounter(p, pC);
|
||||
pCrsr = pC->uc.pCursor;
|
||||
assert( pCrsr!=0 );
|
||||
assert( pOp->p5==0 );
|
||||
@@ -5460,6 +5469,7 @@ case OP_Destroy: { /* out2 */
|
||||
int iMoved;
|
||||
int iDb;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
assert( p->readOnly==0 );
|
||||
assert( pOp->p1>1 );
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
@@ -5509,6 +5519,7 @@ case OP_Destroy: { /* out2 */
|
||||
case OP_Clear: {
|
||||
int nChange;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
nChange = 0;
|
||||
assert( p->readOnly==0 );
|
||||
assert( DbMaskTest(p->btreeMask, pOp->p2) );
|
||||
@@ -5558,13 +5569,14 @@ case OP_ResetSorter: {
|
||||
** Allocate a new b-tree in the main database file if P1==0 or in the
|
||||
** TEMP database file if P1==1 or in an attached database if
|
||||
** P1>1. The P3 argument must be 1 (BTREE_INTKEY) for a rowid table
|
||||
** it must be 2 (BTREE_BLOBKEY) for a index or WITHOUT ROWID table.
|
||||
** it must be 2 (BTREE_BLOBKEY) for an index or WITHOUT ROWID table.
|
||||
** The root page number of the new b-tree is stored in register P2.
|
||||
*/
|
||||
case OP_CreateBtree: { /* out2 */
|
||||
int pgno;
|
||||
Db *pDb;
|
||||
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
pOut = out2Prerelease(p, pOp);
|
||||
pgno = 0;
|
||||
assert( pOp->p3==BTREE_INTKEY || pOp->p3==BTREE_BLOBKEY );
|
||||
@@ -5584,6 +5596,7 @@ case OP_CreateBtree: { /* out2 */
|
||||
** Run the SQL statement or statements specified in the P4 string.
|
||||
*/
|
||||
case OP_SqlExec: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
db->nSqlExec++;
|
||||
rc = sqlite3_exec(db, pOp->p4.z, 0, 0, 0);
|
||||
db->nSqlExec--;
|
||||
@@ -5673,6 +5686,7 @@ case OP_LoadAnalysis: {
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropTable: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p4.z);
|
||||
break;
|
||||
}
|
||||
@@ -5686,6 +5700,7 @@ case OP_DropTable: {
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropIndex: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p4.z);
|
||||
break;
|
||||
}
|
||||
@@ -5699,6 +5714,7 @@ case OP_DropIndex: {
|
||||
** schema consistent with what is on disk.
|
||||
*/
|
||||
case OP_DropTrigger: {
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p4.z);
|
||||
break;
|
||||
}
|
||||
@@ -6745,7 +6761,7 @@ case OP_VFilter: { /* jump */
|
||||
** If the VColumn opcode is being used to fetch the value of
|
||||
** an unchanging column during an UPDATE operation, then the P5
|
||||
** value is 1. Otherwise, P5 is 0. The P5 value is returned
|
||||
** by sqlite3_vtab_nochange() routine can can be used
|
||||
** by sqlite3_vtab_nochange() routine and can be used
|
||||
** by virtual table implementations to return special "no-change"
|
||||
** marks which can be more efficient, depending on the virtual table.
|
||||
*/
|
||||
@@ -6908,6 +6924,7 @@ case OP_VUpdate: {
|
||||
|| pOp->p5==OE_Abort || pOp->p5==OE_Ignore || pOp->p5==OE_Replace
|
||||
);
|
||||
assert( p->readOnly==0 );
|
||||
sqlite3VdbeIncrWriteCounter(p, 0);
|
||||
pVtab = pOp->p4.pVtab->pVtab;
|
||||
if( pVtab==0 || NEVER(pVtab->pModule==0) ){
|
||||
rc = SQLITE_LOCKED;
|
||||
@@ -7225,6 +7242,22 @@ case OP_CursorHint: {
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_CURSOR_HINTS */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Opcode: Abortable * * * * *
|
||||
**
|
||||
** Verify that an Abort can happen. Assert if an Abort at this point
|
||||
** might cause database corruption. This opcode only appears in debugging
|
||||
** builds.
|
||||
**
|
||||
** An Abort is safe if either there have been no writes, or if there is
|
||||
** an active statement journal.
|
||||
*/
|
||||
case OP_Abortable: {
|
||||
sqlite3VdbeAssertAbortable(p);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Opcode: Noop * * * * *
|
||||
**
|
||||
** Do nothing. This instruction is often useful as a jump
|
||||
@@ -7236,8 +7269,9 @@ case OP_CursorHint: {
|
||||
** This opcode records information from the optimizer. It is the
|
||||
** the same as a no-op. This opcodesnever appears in a real VM program.
|
||||
*/
|
||||
default: { /* This is really OP_Noop and OP_Explain */
|
||||
default: { /* This is really OP_Noop, OP_Explain */
|
||||
assert( pOp->opcode==OP_Noop || pOp->opcode==OP_Explain );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
+18
-1
@@ -197,7 +197,24 @@ void sqlite3VdbeEndCoroutine(Vdbe*,int);
|
||||
# define sqlite3VdbeVerifyNoMallocRequired(A,B)
|
||||
# define sqlite3VdbeVerifyNoResultRow(A)
|
||||
#endif
|
||||
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp, int iLineno);
|
||||
#if defined(SQLITE_DEBUG)
|
||||
void sqlite3VdbeVerifyAbortable(Vdbe *p, int);
|
||||
#else
|
||||
# define sqlite3VdbeVerifyAbortable(A,B)
|
||||
#endif
|
||||
VdbeOp *sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp,int iLineno);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
void sqlite3VdbeExplain(Parse*,u8,const char*,...);
|
||||
void sqlite3VdbeExplainPop(Parse*);
|
||||
int sqlite3VdbeExplainParent(Parse*);
|
||||
# define ExplainQueryPlan(P) sqlite3VdbeExplain P
|
||||
# define ExplainQueryPlanPop(P) sqlite3VdbeExplainPop(P)
|
||||
# define ExplainQueryPlanParent(P) sqlite3VdbeExplainParent(P)
|
||||
#else
|
||||
# define ExplainQueryPlan(P)
|
||||
# define ExplainQueryPlanPop(P)
|
||||
# define ExplainQueryPlanParent(P) 0
|
||||
#endif
|
||||
void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*);
|
||||
void sqlite3VdbeChangeOpcode(Vdbe*, u32 addr, u8);
|
||||
void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1);
|
||||
|
||||
@@ -379,6 +379,7 @@ struct Vdbe {
|
||||
int nOp; /* Number of instructions in the program */
|
||||
#ifdef SQLITE_DEBUG
|
||||
int rcApp; /* errcode set by sqlite3_result_error_code() */
|
||||
u32 nWrite; /* Number of write operations that have occurred */
|
||||
#endif
|
||||
u16 nResColumn; /* Number of columns in one row of the result set */
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
@@ -514,6 +515,14 @@ int sqlite3VdbeSorterRewind(const VdbeCursor *, int *);
|
||||
int sqlite3VdbeSorterWrite(const VdbeCursor *, Mem *);
|
||||
int sqlite3VdbeSorterCompare(const VdbeCursor *, Mem *, int, int *);
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
void sqlite3VdbeIncrWriteCounter(Vdbe*, VdbeCursor*);
|
||||
void sqlite3VdbeAssertAbortable(Vdbe*);
|
||||
#else
|
||||
# define sqlite3VdbeIncrWriteCounter(V,C)
|
||||
# define sqlite3VdbeAssertAbortable(V)
|
||||
#endif
|
||||
|
||||
#if !defined(SQLITE_OMIT_SHARED_CACHE)
|
||||
void sqlite3VdbeEnter(Vdbe*);
|
||||
#else
|
||||
|
||||
@@ -787,28 +787,6 @@ sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
|
||||
return *piTime;
|
||||
}
|
||||
|
||||
/*
|
||||
** The following is the implementation of an SQL function that always
|
||||
** fails with an error message stating that the function is used in the
|
||||
** wrong context. The sqlite3_overload_function() API might construct
|
||||
** SQL function that use this routine so that the functions will exist
|
||||
** for name resolution but are actually overloaded by the xFindFunction
|
||||
** method of virtual tables.
|
||||
*/
|
||||
void sqlite3InvalidFunction(
|
||||
sqlite3_context *context, /* The function calling context */
|
||||
int NotUsed, /* Number of arguments to the function */
|
||||
sqlite3_value **NotUsed2 /* Value of each argument */
|
||||
){
|
||||
const char *zName = context->pFunc->zName;
|
||||
char *zErr;
|
||||
UNUSED_PARAMETER2(NotUsed, NotUsed2);
|
||||
zErr = sqlite3_mprintf(
|
||||
"unable to use function %s in the requested context", zName);
|
||||
sqlite3_result_error(context, zErr, -1);
|
||||
sqlite3_free(zErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new aggregate context for p and return a pointer to
|
||||
** its pMem->z element.
|
||||
|
||||
+120
-33
@@ -303,6 +303,49 @@ int sqlite3VdbeAddOp4Dup8(
|
||||
return sqlite3VdbeAddOp4(p, op, p1, p2, p3, p4copy, p4type);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
/*
|
||||
** Return the address of the current EXPLAIN QUERY PLAN baseline.
|
||||
** 0 means "none".
|
||||
*/
|
||||
int sqlite3VdbeExplainParent(Parse *pParse){
|
||||
VdbeOp *pOp;
|
||||
if( pParse->addrExplain==0 ) return 0;
|
||||
pOp = sqlite3VdbeGetOp(pParse->pVdbe, pParse->addrExplain);
|
||||
return pOp->p2;
|
||||
}
|
||||
|
||||
/*
|
||||
** Add a new OP_Explain opcode.
|
||||
**
|
||||
** If the bPush flag is true, then make this opcode the parent for
|
||||
** subsequent Explains until sqlite3VdbeExplainPop() is called.
|
||||
*/
|
||||
void sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){
|
||||
if( pParse->explain==2 ){
|
||||
char *zMsg;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
va_list ap;
|
||||
int iThis;
|
||||
va_start(ap, zFmt);
|
||||
zMsg = sqlite3VMPrintf(pParse->db, zFmt, ap);
|
||||
va_end(ap);
|
||||
v = pParse->pVdbe;
|
||||
iThis = v->nOp;
|
||||
sqlite3VdbeAddOp4(v, OP_Explain, iThis, pParse->addrExplain, 0,
|
||||
zMsg, P4_DYNAMIC);
|
||||
if( bPush) pParse->addrExplain = iThis;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Pop the EXPLAIN QUERY PLAN stack one level.
|
||||
*/
|
||||
void sqlite3VdbeExplainPop(Parse *pParse){
|
||||
pParse->addrExplain = sqlite3VdbeExplainParent(pParse);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||
|
||||
/*
|
||||
** Add an OP_ParseSchema opcode. This routine is broken out from
|
||||
** sqlite3VdbeAddOp4() since it needs to also needs to mark all btrees
|
||||
@@ -560,6 +603,32 @@ int sqlite3VdbeAssertMayAbort(Vdbe *v, int mayAbort){
|
||||
}
|
||||
#endif /* SQLITE_DEBUG - the sqlite3AssertMayAbort() function */
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Increment the nWrite counter in the VDBE if the cursor is not an
|
||||
** ephemeral cursor, or if the cursor argument is NULL.
|
||||
*/
|
||||
void sqlite3VdbeIncrWriteCounter(Vdbe *p, VdbeCursor *pC){
|
||||
if( pC==0
|
||||
|| (pC->eCurType!=CURTYPE_SORTER
|
||||
&& pC->eCurType!=CURTYPE_PSEUDO
|
||||
&& !pC->isEphemeral)
|
||||
){
|
||||
p->nWrite++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/*
|
||||
** Assert if an Abort at this point in time might result in a corrupt
|
||||
** database.
|
||||
*/
|
||||
void sqlite3VdbeAssertAbortable(Vdbe *p){
|
||||
assert( p->nWrite==0 || p->usesStmtJournal );
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine is called after all opcodes have been inserted. It loops
|
||||
** through all the opcodes and fixes up some details.
|
||||
@@ -719,6 +788,17 @@ void sqlite3VdbeVerifyNoResultRow(Vdbe *p){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Generate code (a single OP_Abortable opcode) that will
|
||||
** verify that the VDBE program can safely call Abort in the current
|
||||
** context.
|
||||
*/
|
||||
#if defined(SQLITE_DEBUG)
|
||||
void sqlite3VdbeVerifyAbortable(Vdbe *p, int onError){
|
||||
if( onError==OE_Abort ) sqlite3VdbeAddOp0(p, OP_Abortable);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This function returns a pointer to the array of opcodes associated with
|
||||
** the Vdbe passed as the first argument. It is the callers responsibility
|
||||
@@ -1263,23 +1343,23 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
|
||||
const char *zOp = 0;
|
||||
switch( pExpr->op ){
|
||||
case TK_STRING:
|
||||
sqlite3XPrintf(p, "%Q", pExpr->u.zToken);
|
||||
sqlite3_str_appendf(p, "%Q", pExpr->u.zToken);
|
||||
break;
|
||||
case TK_INTEGER:
|
||||
sqlite3XPrintf(p, "%d", pExpr->u.iValue);
|
||||
sqlite3_str_appendf(p, "%d", pExpr->u.iValue);
|
||||
break;
|
||||
case TK_NULL:
|
||||
sqlite3XPrintf(p, "NULL");
|
||||
sqlite3_str_appendf(p, "NULL");
|
||||
break;
|
||||
case TK_REGISTER: {
|
||||
sqlite3XPrintf(p, "r[%d]", pExpr->iTable);
|
||||
sqlite3_str_appendf(p, "r[%d]", pExpr->iTable);
|
||||
break;
|
||||
}
|
||||
case TK_COLUMN: {
|
||||
if( pExpr->iColumn<0 ){
|
||||
sqlite3XPrintf(p, "rowid");
|
||||
sqlite3_str_appendf(p, "rowid");
|
||||
}else{
|
||||
sqlite3XPrintf(p, "c%d", (int)pExpr->iColumn);
|
||||
sqlite3_str_appendf(p, "c%d", (int)pExpr->iColumn);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1311,18 +1391,18 @@ static void displayP4Expr(StrAccum *p, Expr *pExpr){
|
||||
case TK_NOTNULL: zOp = "NOTNULL"; break;
|
||||
|
||||
default:
|
||||
sqlite3XPrintf(p, "%s", "expr");
|
||||
sqlite3_str_appendf(p, "%s", "expr");
|
||||
break;
|
||||
}
|
||||
|
||||
if( zOp ){
|
||||
sqlite3XPrintf(p, "%s(", zOp);
|
||||
sqlite3_str_appendf(p, "%s(", zOp);
|
||||
displayP4Expr(p, pExpr->pLeft);
|
||||
if( pExpr->pRight ){
|
||||
sqlite3StrAccumAppend(p, ",", 1);
|
||||
sqlite3_str_append(p, ",", 1);
|
||||
displayP4Expr(p, pExpr->pRight);
|
||||
}
|
||||
sqlite3StrAccumAppend(p, ")", 1);
|
||||
sqlite3_str_append(p, ")", 1);
|
||||
}
|
||||
}
|
||||
#endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */
|
||||
@@ -1343,14 +1423,15 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
int j;
|
||||
KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
|
||||
assert( pKeyInfo->aSortOrder!=0 );
|
||||
sqlite3XPrintf(&x, "k(%d", pKeyInfo->nKeyField);
|
||||
sqlite3_str_appendf(&x, "k(%d", pKeyInfo->nKeyField);
|
||||
for(j=0; j<pKeyInfo->nKeyField; j++){
|
||||
CollSeq *pColl = pKeyInfo->aColl[j];
|
||||
const char *zColl = pColl ? pColl->zName : "";
|
||||
if( strcmp(zColl, "BINARY")==0 ) zColl = "B";
|
||||
sqlite3XPrintf(&x, ",%s%s", pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
|
||||
sqlite3_str_appendf(&x, ",%s%s",
|
||||
pKeyInfo->aSortOrder[j] ? "-" : "", zColl);
|
||||
}
|
||||
sqlite3StrAccumAppend(&x, ")", 1);
|
||||
sqlite3_str_append(&x, ")", 1);
|
||||
break;
|
||||
}
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
@@ -1361,31 +1442,31 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
#endif
|
||||
case P4_COLLSEQ: {
|
||||
CollSeq *pColl = pOp->p4.pColl;
|
||||
sqlite3XPrintf(&x, "(%.20s)", pColl->zName);
|
||||
sqlite3_str_appendf(&x, "(%.20s)", pColl->zName);
|
||||
break;
|
||||
}
|
||||
case P4_FUNCDEF: {
|
||||
FuncDef *pDef = pOp->p4.pFunc;
|
||||
sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
||||
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
||||
break;
|
||||
}
|
||||
#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
|
||||
case P4_FUNCCTX: {
|
||||
FuncDef *pDef = pOp->p4.pCtx->pFunc;
|
||||
sqlite3XPrintf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
||||
sqlite3_str_appendf(&x, "%s(%d)", pDef->zName, pDef->nArg);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
case P4_INT64: {
|
||||
sqlite3XPrintf(&x, "%lld", *pOp->p4.pI64);
|
||||
sqlite3_str_appendf(&x, "%lld", *pOp->p4.pI64);
|
||||
break;
|
||||
}
|
||||
case P4_INT32: {
|
||||
sqlite3XPrintf(&x, "%d", pOp->p4.i);
|
||||
sqlite3_str_appendf(&x, "%d", pOp->p4.i);
|
||||
break;
|
||||
}
|
||||
case P4_REAL: {
|
||||
sqlite3XPrintf(&x, "%.16g", *pOp->p4.pReal);
|
||||
sqlite3_str_appendf(&x, "%.16g", *pOp->p4.pReal);
|
||||
break;
|
||||
}
|
||||
case P4_MEM: {
|
||||
@@ -1393,9 +1474,9 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
if( pMem->flags & MEM_Str ){
|
||||
zP4 = pMem->z;
|
||||
}else if( pMem->flags & MEM_Int ){
|
||||
sqlite3XPrintf(&x, "%lld", pMem->u.i);
|
||||
sqlite3_str_appendf(&x, "%lld", pMem->u.i);
|
||||
}else if( pMem->flags & MEM_Real ){
|
||||
sqlite3XPrintf(&x, "%.16g", pMem->u.r);
|
||||
sqlite3_str_appendf(&x, "%.16g", pMem->u.r);
|
||||
}else if( pMem->flags & MEM_Null ){
|
||||
zP4 = "NULL";
|
||||
}else{
|
||||
@@ -1407,7 +1488,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
case P4_VTAB: {
|
||||
sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
|
||||
sqlite3XPrintf(&x, "vtab:%p", pVtab);
|
||||
sqlite3_str_appendf(&x, "vtab:%p", pVtab);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1417,14 +1498,14 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
int n = ai[0]; /* The first element of an INTARRAY is always the
|
||||
** count of the number of elements to follow */
|
||||
for(i=1; i<=n; i++){
|
||||
sqlite3XPrintf(&x, ",%d", ai[i]);
|
||||
sqlite3_str_appendf(&x, ",%d", ai[i]);
|
||||
}
|
||||
zTemp[0] = '[';
|
||||
sqlite3StrAccumAppend(&x, "]", 1);
|
||||
sqlite3_str_append(&x, "]", 1);
|
||||
break;
|
||||
}
|
||||
case P4_SUBPROGRAM: {
|
||||
sqlite3XPrintf(&x, "program");
|
||||
sqlite3_str_appendf(&x, "program");
|
||||
break;
|
||||
}
|
||||
case P4_DYNBLOB:
|
||||
@@ -1433,7 +1514,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
|
||||
break;
|
||||
}
|
||||
case P4_TABLE: {
|
||||
sqlite3XPrintf(&x, "%s", pOp->p4.pTab->zName);
|
||||
sqlite3_str_appendf(&x, "%s", pOp->p4.pTab->zName);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -1645,6 +1726,9 @@ void sqlite3VdbeFrameDelete(VdbeFrame *p){
|
||||
** p->explain==2, only OP_Explain instructions are listed and these
|
||||
** are shown in a different format. p->explain==2 is used to implement
|
||||
** EXPLAIN QUERY PLAN.
|
||||
** 2018-04-24: In p->explain==2 mode, the OP_Init opcodes of triggers
|
||||
** are also shown, so that the boundaries between the main program and
|
||||
** each trigger are clear.
|
||||
**
|
||||
** When p->explain==1, first the main program is listed, then each of
|
||||
** the trigger subprograms are listed one by one.
|
||||
@@ -1707,7 +1791,7 @@ int sqlite3VdbeList(
|
||||
}
|
||||
}
|
||||
|
||||
do{
|
||||
while(1){ /* Loop exits via break */
|
||||
i = p->pc++;
|
||||
if( i>=nRow ){
|
||||
p->rc = SQLITE_OK;
|
||||
@@ -1753,7 +1837,10 @@ int sqlite3VdbeList(
|
||||
nRow += pOp->p4.pProgram->nOp;
|
||||
}
|
||||
}
|
||||
}while( p->explain==2 && pOp->opcode!=OP_Explain );
|
||||
if( p->explain<2 ) break;
|
||||
if( pOp->opcode==OP_Explain ) break;
|
||||
if( pOp->opcode==OP_Init && p->pc>1 ) break;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( db->u1.isInterrupted ){
|
||||
@@ -2945,6 +3032,9 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
p->pResultSet = 0;
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->nWrite = 0;
|
||||
#endif
|
||||
|
||||
/* Save profiling information from this VDBE run.
|
||||
*/
|
||||
@@ -3867,13 +3957,10 @@ static int sqlite3IntFloatCompare(i64 i, double r){
|
||||
i64 y;
|
||||
double s;
|
||||
if( r<-9223372036854775808.0 ) return +1;
|
||||
if( r>9223372036854775807.0 ) return -1;
|
||||
if( r>=9223372036854775808.0 ) return -1;
|
||||
y = (i64)r;
|
||||
if( i<y ) return -1;
|
||||
if( i>y ){
|
||||
if( y==SMALLEST_INT64 && r>0.0 ) return -1;
|
||||
return +1;
|
||||
}
|
||||
if( i>y ) return +1;
|
||||
s = (double)i;
|
||||
if( s<r ) return -1;
|
||||
if( s>r ) return +1;
|
||||
|
||||
+1
-1
@@ -800,7 +800,7 @@ void sqlite3VdbeMemSetInt64(Mem *pMem, i64 val){
|
||||
}
|
||||
|
||||
/* A no-op destructor */
|
||||
static void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
|
||||
void sqlite3NoopDestructor(void *p){ UNUSED_PARAMETER(p); }
|
||||
|
||||
/*
|
||||
** Set the value stored in *pMem should already be a NULL.
|
||||
|
||||
+16
-16
@@ -93,17 +93,17 @@ char *sqlite3VdbeExpandSql(
|
||||
while( *zRawSql ){
|
||||
const char *zStart = zRawSql;
|
||||
while( *(zRawSql++)!='\n' && *zRawSql );
|
||||
sqlite3StrAccumAppend(&out, "-- ", 3);
|
||||
sqlite3_str_append(&out, "-- ", 3);
|
||||
assert( (zRawSql - zStart) > 0 );
|
||||
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
|
||||
sqlite3_str_append(&out, zStart, (int)(zRawSql-zStart));
|
||||
}
|
||||
}else if( p->nVar==0 ){
|
||||
sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql));
|
||||
sqlite3_str_append(&out, zRawSql, sqlite3Strlen30(zRawSql));
|
||||
}else{
|
||||
while( zRawSql[0] ){
|
||||
n = findNextHostParameter(zRawSql, &nToken);
|
||||
assert( n>0 );
|
||||
sqlite3StrAccumAppend(&out, zRawSql, n);
|
||||
sqlite3_str_append(&out, zRawSql, n);
|
||||
zRawSql += n;
|
||||
assert( zRawSql[0] || nToken==0 );
|
||||
if( nToken==0 ) break;
|
||||
@@ -129,11 +129,11 @@ char *sqlite3VdbeExpandSql(
|
||||
assert( idx>0 && idx<=p->nVar );
|
||||
pVar = &p->aVar[idx-1];
|
||||
if( pVar->flags & MEM_Null ){
|
||||
sqlite3StrAccumAppend(&out, "NULL", 4);
|
||||
sqlite3_str_append(&out, "NULL", 4);
|
||||
}else if( pVar->flags & MEM_Int ){
|
||||
sqlite3XPrintf(&out, "%lld", pVar->u.i);
|
||||
sqlite3_str_appendf(&out, "%lld", pVar->u.i);
|
||||
}else if( pVar->flags & MEM_Real ){
|
||||
sqlite3XPrintf(&out, "%!.15g", pVar->u.r);
|
||||
sqlite3_str_appendf(&out, "%!.15g", pVar->u.r);
|
||||
}else if( pVar->flags & MEM_Str ){
|
||||
int nOut; /* Number of bytes of the string text to include in output */
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
@@ -143,7 +143,7 @@ char *sqlite3VdbeExpandSql(
|
||||
utf8.db = db;
|
||||
sqlite3VdbeMemSetStr(&utf8, pVar->z, pVar->n, enc, SQLITE_STATIC);
|
||||
if( SQLITE_NOMEM==sqlite3VdbeChangeEncoding(&utf8, SQLITE_UTF8) ){
|
||||
out.accError = STRACCUM_NOMEM;
|
||||
out.accError = SQLITE_NOMEM;
|
||||
out.nAlloc = 0;
|
||||
}
|
||||
pVar = &utf8;
|
||||
@@ -156,38 +156,38 @@ char *sqlite3VdbeExpandSql(
|
||||
while( nOut<pVar->n && (pVar->z[nOut]&0xc0)==0x80 ){ nOut++; }
|
||||
}
|
||||
#endif
|
||||
sqlite3XPrintf(&out, "'%.*q'", nOut, pVar->z);
|
||||
sqlite3_str_appendf(&out, "'%.*q'", nOut, pVar->z);
|
||||
#ifdef SQLITE_TRACE_SIZE_LIMIT
|
||||
if( nOut<pVar->n ){
|
||||
sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
|
||||
sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut);
|
||||
}
|
||||
#endif
|
||||
#ifndef SQLITE_OMIT_UTF16
|
||||
if( enc!=SQLITE_UTF8 ) sqlite3VdbeMemRelease(&utf8);
|
||||
#endif
|
||||
}else if( pVar->flags & MEM_Zero ){
|
||||
sqlite3XPrintf(&out, "zeroblob(%d)", pVar->u.nZero);
|
||||
sqlite3_str_appendf(&out, "zeroblob(%d)", pVar->u.nZero);
|
||||
}else{
|
||||
int nOut; /* Number of bytes of the blob to include in output */
|
||||
assert( pVar->flags & MEM_Blob );
|
||||
sqlite3StrAccumAppend(&out, "x'", 2);
|
||||
sqlite3_str_append(&out, "x'", 2);
|
||||
nOut = pVar->n;
|
||||
#ifdef SQLITE_TRACE_SIZE_LIMIT
|
||||
if( nOut>SQLITE_TRACE_SIZE_LIMIT ) nOut = SQLITE_TRACE_SIZE_LIMIT;
|
||||
#endif
|
||||
for(i=0; i<nOut; i++){
|
||||
sqlite3XPrintf(&out, "%02x", pVar->z[i]&0xff);
|
||||
sqlite3_str_appendf(&out, "%02x", pVar->z[i]&0xff);
|
||||
}
|
||||
sqlite3StrAccumAppend(&out, "'", 1);
|
||||
sqlite3_str_append(&out, "'", 1);
|
||||
#ifdef SQLITE_TRACE_SIZE_LIMIT
|
||||
if( nOut<pVar->n ){
|
||||
sqlite3XPrintf(&out, "/*+%d bytes*/", pVar->n-nOut);
|
||||
sqlite3_str_appendf(&out, "/*+%d bytes*/", pVar->n-nOut);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
if( out.accError ) sqlite3StrAccumReset(&out);
|
||||
if( out.accError ) sqlite3_str_reset(&out);
|
||||
return sqlite3StrAccumFinish(&out);
|
||||
}
|
||||
|
||||
|
||||
+13
-10
@@ -1049,9 +1049,6 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
void *pArg = 0;
|
||||
FuncDef *pNew;
|
||||
int rc = 0;
|
||||
char *zLowerName;
|
||||
unsigned char *z;
|
||||
|
||||
|
||||
/* Check to see the left operand is a column in a virtual table */
|
||||
if( NEVER(pExpr==0) ) return pDef;
|
||||
@@ -1066,16 +1063,22 @@ FuncDef *sqlite3VtabOverloadFunction(
|
||||
if( pMod->xFindFunction==0 ) return pDef;
|
||||
|
||||
/* Call the xFindFunction method on the virtual table implementation
|
||||
** to see if the implementation wants to overload this function
|
||||
** to see if the implementation wants to overload this function.
|
||||
**
|
||||
** Though undocumented, we have historically always invoked xFindFunction
|
||||
** with an all lower-case function name. Continue in this tradition to
|
||||
** avoid any chance of an incompatibility.
|
||||
*/
|
||||
zLowerName = sqlite3DbStrDup(db, pDef->zName);
|
||||
if( zLowerName ){
|
||||
for(z=(unsigned char*)zLowerName; *z; z++){
|
||||
*z = sqlite3UpperToLower[*z];
|
||||
#ifdef SQLITE_DEBUG
|
||||
{
|
||||
int i;
|
||||
for(i=0; pDef->zName[i]; i++){
|
||||
unsigned char x = (unsigned char)pDef->zName[i];
|
||||
assert( x==sqlite3UpperToLower[x] );
|
||||
}
|
||||
rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg);
|
||||
sqlite3DbFree(db, zLowerName);
|
||||
}
|
||||
#endif
|
||||
rc = pMod->xFindFunction(pVtab, nArg, pDef->zName, &xSFunc, &pArg);
|
||||
if( rc==0 ){
|
||||
return pDef;
|
||||
}
|
||||
|
||||
+13
-10
@@ -2420,15 +2420,12 @@ static int whereLoopAddBtreeIndex(
|
||||
** to mix with a lower range bound from some other source */
|
||||
if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
|
||||
|
||||
/* Do not allow IS constraints from the WHERE clause to be used by the
|
||||
/* Do not allow constraints from the WHERE clause to be used by the
|
||||
** right table of a LEFT JOIN. Only constraints in the ON clause are
|
||||
** allowed */
|
||||
if( (pSrc->fg.jointype & JT_LEFT)!=0
|
||||
&& !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
|
||||
&& (eOp & (WO_IS|WO_ISNULL))!=0
|
||||
){
|
||||
testcase( eOp & WO_IS );
|
||||
testcase( eOp & WO_ISNULL );
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2865,14 +2862,16 @@ static int whereLoopAddBtree(
|
||||
/* TUNING: One-time cost for computing the automatic index is
|
||||
** estimated to be X*N*log2(N) where N is the number of rows in
|
||||
** the table being indexed and where X is 7 (LogEst=28) for normal
|
||||
** tables or 1.375 (LogEst=4) for views and subqueries. The value
|
||||
** tables or 0.5 (LogEst=-10) for views and subqueries. The value
|
||||
** of X is smaller for views and subqueries so that the query planner
|
||||
** will be more aggressive about generating automatic indexes for
|
||||
** those objects, since there is no opportunity to add schema
|
||||
** indexes on subqueries and views. */
|
||||
pNew->rSetup = rLogSize + rSize + 4;
|
||||
pNew->rSetup = rLogSize + rSize;
|
||||
if( pTab->pSelect==0 && (pTab->tabFlags & TF_Ephemeral)==0 ){
|
||||
pNew->rSetup += 24;
|
||||
pNew->rSetup += 28;
|
||||
}else{
|
||||
pNew->rSetup -= 10;
|
||||
}
|
||||
ApplyCostMultiplier(pNew->rSetup, pTab->costMult);
|
||||
if( pNew->rSetup<0 ) pNew->rSetup = 0;
|
||||
@@ -4008,12 +4007,15 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
|
||||
if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue;
|
||||
if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue;
|
||||
if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<10 ){
|
||||
if( (pWLoop->wsFlags & WHERE_AUTO_INDEX)!=0 && pFrom->nRow<3 ){
|
||||
/* Do not use an automatic index if the this loop is expected
|
||||
** to run less than 2 times. */
|
||||
** to run less than 1.25 times. It is tempting to also exclude
|
||||
** automatic index usage on an outer loop, but sometimes an automatic
|
||||
** index is useful in the outer loop of a correlated subquery. */
|
||||
assert( 10==sqlite3LogEst(2) );
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At this point, pWLoop is a candidate to be the next loop.
|
||||
** Compute its cost */
|
||||
rUnsorted = sqlite3LogEstAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow);
|
||||
@@ -4595,6 +4597,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
if( wctrlFlags & WHERE_WANT_DISTINCT ){
|
||||
pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE;
|
||||
}
|
||||
ExplainQueryPlan((pParse, 0, "SCAN CONSTANT ROW"));
|
||||
}else{
|
||||
/* Assign a bit from the bitmask to every term in the FROM clause.
|
||||
**
|
||||
@@ -4990,7 +4993,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
}
|
||||
#endif
|
||||
addrExplain = sqlite3WhereExplainOneScan(
|
||||
pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags
|
||||
pParse, pTabList, pLevel, wctrlFlags
|
||||
);
|
||||
pLevel->addrBody = sqlite3VdbeCurrentAddr(v);
|
||||
notReady = sqlite3WhereCodeOneLoopStart(pWInfo, ii, notReady);
|
||||
|
||||
+1
-3
@@ -467,12 +467,10 @@ int sqlite3WhereExplainOneScan(
|
||||
Parse *pParse, /* Parse context */
|
||||
SrcList *pTabList, /* Table list this loop refers to */
|
||||
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
|
||||
int iLevel, /* Value for "level" column of output */
|
||||
int iFrom, /* Value for "from" column of output */
|
||||
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||
);
|
||||
#else
|
||||
# define sqlite3WhereExplainOneScan(u,v,w,x,y,z) 0
|
||||
# define sqlite3WhereExplainOneScan(u,v,w,x) 0
|
||||
#endif /* SQLITE_OMIT_EXPLAIN */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
void sqlite3WhereAddScanStatus(
|
||||
|
||||
+48
-34
@@ -51,23 +51,23 @@ static void explainAppendTerm(
|
||||
int i;
|
||||
|
||||
assert( nTerm>=1 );
|
||||
if( bAnd ) sqlite3StrAccumAppend(pStr, " AND ", 5);
|
||||
if( bAnd ) sqlite3_str_append(pStr, " AND ", 5);
|
||||
|
||||
if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1);
|
||||
if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1);
|
||||
for(i=0; i<nTerm; i++){
|
||||
if( i ) sqlite3StrAccumAppend(pStr, ",", 1);
|
||||
sqlite3StrAccumAppendAll(pStr, explainIndexColumnName(pIdx, iTerm+i));
|
||||
if( i ) sqlite3_str_append(pStr, ",", 1);
|
||||
sqlite3_str_appendall(pStr, explainIndexColumnName(pIdx, iTerm+i));
|
||||
}
|
||||
if( nTerm>1 ) sqlite3StrAccumAppend(pStr, ")", 1);
|
||||
if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1);
|
||||
|
||||
sqlite3StrAccumAppend(pStr, zOp, 1);
|
||||
sqlite3_str_append(pStr, zOp, 1);
|
||||
|
||||
if( nTerm>1 ) sqlite3StrAccumAppend(pStr, "(", 1);
|
||||
if( nTerm>1 ) sqlite3_str_append(pStr, "(", 1);
|
||||
for(i=0; i<nTerm; i++){
|
||||
if( i ) sqlite3StrAccumAppend(pStr, ",", 1);
|
||||
sqlite3StrAccumAppend(pStr, "?", 1);
|
||||
if( i ) sqlite3_str_append(pStr, ",", 1);
|
||||
sqlite3_str_append(pStr, "?", 1);
|
||||
}
|
||||
if( nTerm>1 ) sqlite3StrAccumAppend(pStr, ")", 1);
|
||||
if( nTerm>1 ) sqlite3_str_append(pStr, ")", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -91,11 +91,11 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
|
||||
int i, j;
|
||||
|
||||
if( nEq==0 && (pLoop->wsFlags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ) return;
|
||||
sqlite3StrAccumAppend(pStr, " (", 2);
|
||||
sqlite3_str_append(pStr, " (", 2);
|
||||
for(i=0; i<nEq; i++){
|
||||
const char *z = explainIndexColumnName(pIndex, i);
|
||||
if( i ) sqlite3StrAccumAppend(pStr, " AND ", 5);
|
||||
sqlite3XPrintf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z);
|
||||
if( i ) sqlite3_str_append(pStr, " AND ", 5);
|
||||
sqlite3_str_appendf(pStr, i>=nSkip ? "%s=?" : "ANY(%s)", z);
|
||||
}
|
||||
|
||||
j = i;
|
||||
@@ -106,7 +106,7 @@ static void explainIndexRange(StrAccum *pStr, WhereLoop *pLoop){
|
||||
if( pLoop->wsFlags&WHERE_TOP_LIMIT ){
|
||||
explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<");
|
||||
}
|
||||
sqlite3StrAccumAppend(pStr, ")", 1);
|
||||
sqlite3_str_append(pStr, ")", 1);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -122,8 +122,6 @@ int sqlite3WhereExplainOneScan(
|
||||
Parse *pParse, /* Parse context */
|
||||
SrcList *pTabList, /* Table list this loop refers to */
|
||||
WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */
|
||||
int iLevel, /* Value for "level" column of output */
|
||||
int iFrom, /* Value for "from" column of output */
|
||||
u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */
|
||||
){
|
||||
int ret = 0;
|
||||
@@ -134,7 +132,6 @@ int sqlite3WhereExplainOneScan(
|
||||
struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];
|
||||
Vdbe *v = pParse->pVdbe; /* VM being constructed */
|
||||
sqlite3 *db = pParse->db; /* Database handle */
|
||||
int iId = pParse->iSelectId; /* Select id (left-most output column) */
|
||||
int isSearch; /* True for a SEARCH. False for SCAN. */
|
||||
WhereLoop *pLoop; /* The controlling WhereLoop object */
|
||||
u32 flags; /* Flags that describe this loop */
|
||||
@@ -151,15 +148,15 @@ int sqlite3WhereExplainOneScan(
|
||||
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
|
||||
|
||||
sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
|
||||
sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
|
||||
sqlite3_str_appendall(&str, isSearch ? "SEARCH" : "SCAN");
|
||||
if( pItem->pSelect ){
|
||||
sqlite3XPrintf(&str, " SUBQUERY %d", pItem->iSelectId);
|
||||
sqlite3_str_appendf(&str, " SUBQUERY 0x%p", pItem->pSelect);
|
||||
}else{
|
||||
sqlite3XPrintf(&str, " TABLE %s", pItem->zName);
|
||||
sqlite3_str_appendf(&str, " TABLE %s", pItem->zName);
|
||||
}
|
||||
|
||||
if( pItem->zAlias ){
|
||||
sqlite3XPrintf(&str, " AS %s", pItem->zAlias);
|
||||
sqlite3_str_appendf(&str, " AS %s", pItem->zAlias);
|
||||
}
|
||||
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){
|
||||
const char *zFmt = 0;
|
||||
@@ -182,8 +179,8 @@ int sqlite3WhereExplainOneScan(
|
||||
zFmt = "INDEX %s";
|
||||
}
|
||||
if( zFmt ){
|
||||
sqlite3StrAccumAppend(&str, " USING ", 7);
|
||||
sqlite3XPrintf(&str, zFmt, pIdx->zName);
|
||||
sqlite3_str_append(&str, " USING ", 7);
|
||||
sqlite3_str_appendf(&str, zFmt, pIdx->zName);
|
||||
explainIndexRange(&str, pLoop);
|
||||
}
|
||||
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
|
||||
@@ -198,23 +195,26 @@ int sqlite3WhereExplainOneScan(
|
||||
assert( flags&WHERE_TOP_LIMIT);
|
||||
zRangeOp = "<";
|
||||
}
|
||||
sqlite3XPrintf(&str, " USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp);
|
||||
sqlite3_str_appendf(&str,
|
||||
" USING INTEGER PRIMARY KEY (rowid%s?)",zRangeOp);
|
||||
}
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
else if( (flags & WHERE_VIRTUALTABLE)!=0 ){
|
||||
sqlite3XPrintf(&str, " VIRTUAL TABLE INDEX %d:%s",
|
||||
sqlite3_str_appendf(&str, " VIRTUAL TABLE INDEX %d:%s",
|
||||
pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr);
|
||||
}
|
||||
#endif
|
||||
#ifdef SQLITE_EXPLAIN_ESTIMATED_ROWS
|
||||
if( pLoop->nOut>=10 ){
|
||||
sqlite3XPrintf(&str, " (~%llu rows)", sqlite3LogEstToInt(pLoop->nOut));
|
||||
sqlite3_str_appendf(&str, " (~%llu rows)",
|
||||
sqlite3LogEstToInt(pLoop->nOut));
|
||||
}else{
|
||||
sqlite3StrAccumAppend(&str, " (~1 row)", 9);
|
||||
sqlite3_str_append(&str, " (~1 row)", 9);
|
||||
}
|
||||
#endif
|
||||
zMsg = sqlite3StrAccumFinish(&str);
|
||||
ret = sqlite3VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg,P4_DYNAMIC);
|
||||
ret = sqlite3VdbeAddOp4(v, OP_Explain, sqlite3VdbeCurrentAddr(v),
|
||||
pParse->addrExplain, 0, zMsg,P4_DYNAMIC);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1215,6 +1215,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** initialize a memory cell that records if this table matches any
|
||||
** row of the left table of the join.
|
||||
*/
|
||||
assert( (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)
|
||||
|| pLevel->iFrom>0 || (pTabItem[0].fg.jointype & JT_LEFT)==0
|
||||
);
|
||||
if( pLevel->iFrom>0 && (pTabItem[0].fg.jointype & JT_LEFT)!=0 ){
|
||||
pLevel->iLeftJoin = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin);
|
||||
@@ -1748,9 +1751,16 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
/* If pIdx is an index on one or more expressions, then look through
|
||||
** all the expressions in pWInfo and try to transform matching expressions
|
||||
** into reference to index columns.
|
||||
**
|
||||
** Do not do this for the RHS of a LEFT JOIN. This is because the
|
||||
** expression may be evaluated after OP_NullRow has been executed on
|
||||
** the cursor. In this case it is important to do the full evaluation,
|
||||
** as the result of the expression may not be NULL, even if all table
|
||||
** column values are. https://www.sqlite.org/src/info/7fa8049685b50b5a
|
||||
*/
|
||||
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
|
||||
|
||||
if( pLevel->iLeftJoin==0 ){
|
||||
whereIndexExprTrans(pIdx, iCur, iIdxCur, pWInfo);
|
||||
}
|
||||
|
||||
/* Record the instruction used to terminate the loop. */
|
||||
if( pLoop->wsFlags & WHERE_ONEROW ){
|
||||
@@ -1906,7 +1916,6 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
for(iTerm=0; iTerm<pWC->nTerm; iTerm++){
|
||||
Expr *pExpr = pWC->a[iTerm].pExpr;
|
||||
if( &pWC->a[iTerm] == pTerm ) continue;
|
||||
if( ExprHasProperty(pExpr, EP_FromJoin) ) continue;
|
||||
testcase( pWC->a[iTerm].wtFlags & TERM_VIRTUAL );
|
||||
testcase( pWC->a[iTerm].wtFlags & TERM_CODED );
|
||||
if( (pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_CODED))!=0 ) continue;
|
||||
@@ -1925,13 +1934,17 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
|
||||
*/
|
||||
wctrlFlags = WHERE_OR_SUBCLAUSE | (pWInfo->wctrlFlags & WHERE_SEEK_TABLE);
|
||||
ExplainQueryPlan((pParse, 1, "MULTI-INDEX OR"));
|
||||
for(ii=0; ii<pOrWc->nTerm; ii++){
|
||||
WhereTerm *pOrTerm = &pOrWc->a[ii];
|
||||
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
|
||||
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
|
||||
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
|
||||
int jmp1 = 0; /* Address of jump operation */
|
||||
if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
|
||||
assert( (pTabItem[0].fg.jointype & JT_LEFT)==0
|
||||
|| ExprHasProperty(pOrExpr, EP_FromJoin)
|
||||
);
|
||||
if( pAndExpr ){
|
||||
pAndExpr->pLeft = pOrExpr;
|
||||
pOrExpr = pAndExpr;
|
||||
}
|
||||
@@ -1943,7 +1956,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
if( pSubWInfo ){
|
||||
WhereLoop *pSubLoop;
|
||||
int addrExplain = sqlite3WhereExplainOneScan(
|
||||
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
|
||||
pParse, pOrTab, &pSubWInfo->a[0], 0
|
||||
);
|
||||
sqlite3WhereAddScanStatus(v, pOrTab, &pSubWInfo->a[0], addrExplain);
|
||||
|
||||
@@ -2042,6 +2055,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
}
|
||||
}
|
||||
ExplainQueryPlanPop(pParse);
|
||||
pLevel->u.pCovidx = pCov;
|
||||
if( pCov ) pLevel->iIdxCur = iCovCur;
|
||||
if( pAndExpr ){
|
||||
@@ -2114,7 +2128,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
}
|
||||
pE = pTerm->pExpr;
|
||||
assert( pE!=0 );
|
||||
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
|
||||
if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -818,7 +818,6 @@ static void exprAnalyzeOrTerm(
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, pList);
|
||||
}
|
||||
pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-15
@@ -118,10 +118,10 @@ do_execsql_test analyze3-1.1.x {
|
||||
#
|
||||
do_eqp_test analyze3-1.1.2 {
|
||||
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
do_eqp_test analyze3-1.1.3 {
|
||||
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
# 2017-06-26: Verify that the SQLITE_DBCONFIG_ENABLE_QPSG setting disables
|
||||
# the use of bound parameters by STAT4
|
||||
@@ -131,27 +131,27 @@ unset -nocomplain l
|
||||
unset -nocomplain u
|
||||
do_eqp_test analyze3-1.1.3.100 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
set l 200
|
||||
set u 300
|
||||
do_eqp_test analyze3-1.1.3.101 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
set l 0
|
||||
set u 1100
|
||||
do_eqp_test analyze3-1.1.3.102 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
db cache flush
|
||||
sqlite3_db_config db ENABLE_QPSG 1
|
||||
do_eqp_test analyze3-1.1.3.103 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}
|
||||
db cache flush
|
||||
sqlite3_db_config db ENABLE_QPSG 0
|
||||
do_eqp_test analyze3-1.1.3.104 {
|
||||
SELECT sum(y) FROM t1 WHERE x>$l AND x<$u
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
do_test analyze3-1.1.4 {
|
||||
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
|
||||
@@ -201,10 +201,10 @@ do_execsql_test analyze3-2.1.x {
|
||||
} {200 990}
|
||||
do_eqp_test analyze3-1.2.2 {
|
||||
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
|
||||
} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}
|
||||
do_eqp_test analyze3-1.2.3 {
|
||||
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
|
||||
} {0 0 0 {SCAN TABLE t2}}
|
||||
} {SCAN TABLE t2}
|
||||
|
||||
do_test analyze3-1.2.4 {
|
||||
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
|
||||
@@ -253,10 +253,10 @@ do_execsql_test analyze3-1.3.x {
|
||||
} {99 1000}
|
||||
do_eqp_test analyze3-1.3.2 {
|
||||
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
|
||||
} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
|
||||
} {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}
|
||||
do_eqp_test analyze3-1.3.3 {
|
||||
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
|
||||
} {0 0 0 {SCAN TABLE t3}}
|
||||
} {SCAN TABLE t3}
|
||||
|
||||
do_test analyze3-1.3.4 {
|
||||
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
|
||||
@@ -308,10 +308,10 @@ do_test analyze3-2.1 {
|
||||
} {}
|
||||
do_eqp_test analyze3-2.2 {
|
||||
SELECT count(a) FROM t1 WHERE b LIKE 'a%'
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (b>? AND b<?)}
|
||||
do_eqp_test analyze3-2.3 {
|
||||
SELECT count(a) FROM t1 WHERE b LIKE '%a'
|
||||
} {0 0 0 {SCAN TABLE t1}}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
# Return the first argument if like_match_blobs is true (the default)
|
||||
# or the second argument if not
|
||||
@@ -698,11 +698,11 @@ do_test analyze3-6.1 {
|
||||
|
||||
do_eqp_test analyze3-6-3 {
|
||||
SELECT * FROM t1 WHERE a = 5 AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
|
||||
do_eqp_test analyze3-6-2 {
|
||||
SELECT * FROM t1 WHERE a = 5 AND b > 'w' AND c = 13;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (c=?)}
|
||||
|
||||
#-----------------------------------------------------------------------------
|
||||
# 2015-04-20.
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ do_test analyze4-1.0 {
|
||||
|
||||
# Should choose the t1a index since it is more specific than t1b.
|
||||
db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
|
||||
# Verify that the t1b index shows that it does not narrow down the
|
||||
# search any at all.
|
||||
|
||||
+17
-13
@@ -61,14 +61,18 @@ do_test analyze6-1.0 {
|
||||
#
|
||||
do_test analyze6-1.1 {
|
||||
eqp {SELECT count(*) FROM ev, cat WHERE x=y}
|
||||
} {0 0 1 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 0 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}}
|
||||
} {/*SCAN TABLE cat USING COVERING INDEX catx*SEARCH TABLE ev USING COVERING INDEX evy (y=?)*/}
|
||||
|
||||
# The same plan is chosen regardless of the order of the tables in the
|
||||
# FROM clause.
|
||||
#
|
||||
do_test analyze6-1.2 {
|
||||
eqp {SELECT count(*) FROM cat, ev WHERE x=y}
|
||||
} {0 0 0 {SCAN TABLE cat USING COVERING INDEX catx} 0 1 1 {SEARCH TABLE ev USING COVERING INDEX evy (y=?)}}
|
||||
do_eqp_test analyze6-1.2 {
|
||||
SELECT count(*) FROM cat, ev WHERE x=y
|
||||
} {
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE cat USING COVERING INDEX catx
|
||||
`--SEARCH TABLE ev USING COVERING INDEX evy (y=?)
|
||||
}
|
||||
|
||||
|
||||
# Ticket [83ea97620bd3101645138b7b0e71c12c5498fe3d] 2011-03-30
|
||||
@@ -82,26 +86,26 @@ do_test analyze6-2.1 {
|
||||
ANALYZE;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
|
||||
do_test analyze6-2.2 {
|
||||
eqp {SELECT * FROM t201 WHERE y=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
|
||||
do_test analyze6-2.3 {
|
||||
eqp {SELECT * FROM t201 WHERE x=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
|
||||
do_test analyze6-2.4 {
|
||||
execsql {
|
||||
INSERT INTO t201 VALUES(1,2,3),(2,3,4),(3,4,5);
|
||||
ANALYZE t201;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
|
||||
do_test analyze6-2.5 {
|
||||
eqp {SELECT * FROM t201 WHERE y=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
|
||||
do_test analyze6-2.6 {
|
||||
eqp {SELECT * FROM t201 WHERE x=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
|
||||
do_test analyze6-2.7 {
|
||||
execsql {
|
||||
INSERT INTO t201 VALUES(4,5,7);
|
||||
@@ -111,12 +115,12 @@ do_test analyze6-2.7 {
|
||||
ANALYZE t201;
|
||||
}
|
||||
eqp {SELECT * FROM t201 WHERE z=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX t201z (z=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX t201z (z=?)*/}
|
||||
do_test analyze6-2.8 {
|
||||
eqp {SELECT * FROM t201 WHERE y=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INDEX sqlite_autoindex_t201_1 (y=?)*/}
|
||||
do_test analyze6-2.9 {
|
||||
eqp {SELECT * FROM t201 WHERE x=5}
|
||||
} {0 0 0 {SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)}}
|
||||
} {/*SEARCH TABLE t201 USING INTEGER PRIMARY KEY (rowid=?)*/}
|
||||
|
||||
finish_test
|
||||
|
||||
+16
-16
@@ -37,13 +37,13 @@ do_test analyze7-1.0 {
|
||||
WHERE value BETWEEN 1 AND 256;
|
||||
EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;
|
||||
}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test analyze7-1.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-1.2 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
|
||||
# Run an analyze on one of the three indices. Verify that this
|
||||
# effects the row-count estimate on the one query that uses that
|
||||
@@ -53,20 +53,20 @@ do_test analyze7-2.0 {
|
||||
execsql {ANALYZE t1a;}
|
||||
db cache flush
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test analyze7-2.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-2.2 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
|
||||
# Verify that since the query planner now things that t1a is more
|
||||
# selective than t1b, it prefers to use t1a.
|
||||
#
|
||||
do_test analyze7-2.3 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
|
||||
# Run an analysis on another of the three indices. Verify that this
|
||||
# new analysis works and does not disrupt the previous analysis.
|
||||
@@ -75,40 +75,40 @@ do_test analyze7-3.0 {
|
||||
execsql {ANALYZE t1cd;}
|
||||
db cache flush;
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test analyze7-3.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b=123;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-3.2.1 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=?;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
ifcapable stat4||stat3 {
|
||||
# If ENABLE_STAT4 is defined, SQLite comes up with a different estimated
|
||||
# row count for (c=2) than it does for (c=?).
|
||||
do_test analyze7-3.2.2 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
} else {
|
||||
# If ENABLE_STAT4 is not defined, the expected row count for (c=2) is the
|
||||
# same as that for (c=?).
|
||||
do_test analyze7-3.2.3 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=2;}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=?)*/}
|
||||
}
|
||||
do_test analyze7-3.3 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
|
||||
ifcapable {!stat4 && !stat3} {
|
||||
do_test analyze7-3.4 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test analyze7-3.5 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=123 AND c=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
}
|
||||
do_test analyze7-3.6 {
|
||||
execsql {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE c=123 AND d=123 AND b=123}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1cd (c=? AND d=?)*/}
|
||||
|
||||
finish_test
|
||||
|
||||
+11
-11
@@ -61,25 +61,25 @@ do_test 1.0 {
|
||||
#
|
||||
do_test 1.1 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND b=55}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test 1.2 {
|
||||
eqp {SELECT * FROM t1 WHERE a=99 AND b=55}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 1.3 {
|
||||
eqp {SELECT * FROM t1 WHERE a=101 AND b=55}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 1.4 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND b=56}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b=?)*/}
|
||||
do_test 1.5 {
|
||||
eqp {SELECT * FROM t1 WHERE a=99 AND b=56}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 1.6 {
|
||||
eqp {SELECT * FROM t1 WHERE a=101 AND b=56}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 2.1 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND b BETWEEN 50 AND 54}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
|
||||
|
||||
# There are many more values of c between 0 and 100000 than there are
|
||||
# between 800000 and 900000. So t1c is more selective for the latter
|
||||
@@ -99,17 +99,17 @@ do_execsql_test 3.0 {
|
||||
} {50 376 32}
|
||||
do_test 3.1 {
|
||||
eqp {SELECT * FROM t1 WHERE b BETWEEN 30 AND 34 AND c BETWEEN 0 AND 100000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)*/}
|
||||
do_test 3.2 {
|
||||
eqp {SELECT * FROM t1
|
||||
WHERE b BETWEEN 30 AND 34 AND c BETWEEN 800000 AND 900000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
|
||||
do_test 3.3 {
|
||||
eqp {SELECT * FROM t1 WHERE a=100 AND c BETWEEN 0 AND 100000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1a (a=?)*/}
|
||||
do_test 3.4 {
|
||||
eqp {SELECT * FROM t1
|
||||
WHERE a=100 AND c BETWEEN 800000 AND 900000}
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {/*SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)*/}
|
||||
|
||||
finish_test
|
||||
|
||||
+14
-28
@@ -987,7 +987,8 @@ do_eqp_test 21.3 {
|
||||
reset_db
|
||||
do_execsql_test 22.0 {
|
||||
CREATE TABLE t3(a, b, c, d, PRIMARY KEY(a, b)) WITHOUT ROWID;
|
||||
}
|
||||
SELECT * FROM t3;
|
||||
} {}
|
||||
do_execsql_test 22.1 {
|
||||
WITH r(x) AS (
|
||||
SELECT 1
|
||||
@@ -1055,15 +1056,11 @@ do_eqp_test 23.1 {
|
||||
-- Formerly used index i41. But i41 is not a covering index whereas
|
||||
-- the PRIMARY KEY is a covering index, and so as of 2017-10-15, the
|
||||
-- PRIMARY KEY is preferred.
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
|
||||
}
|
||||
} {SEARCH TABLE t4 USING PRIMARY KEY (c=? AND b=? AND a<?)}
|
||||
do_eqp_test 23.2 {
|
||||
SELECT * FROM t4 WHERE
|
||||
(e=1 AND b='xyz' AND c='zyx' AND a<'JJJ') AND f<300
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t4 USING INDEX i42 (f<?)}
|
||||
}
|
||||
} {SEARCH TABLE t4 USING INDEX i42 (f<?)}
|
||||
|
||||
do_execsql_test 24.0 {
|
||||
CREATE TABLE t5(c, d, b, e, a, PRIMARY KEY(a, b, c)) WITHOUT ROWID;
|
||||
@@ -1108,33 +1105,26 @@ ifcapable stat4&&cte {
|
||||
|
||||
# Term (b<?) is estimated at 25%. Better than (a<30) but not as
|
||||
# good as (a<20).
|
||||
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b<?)}
|
||||
}
|
||||
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
}
|
||||
do_eqp_test 25.2.1 { SELECT * FROM t6 WHERE a<30 AND b<? } \
|
||||
{SEARCH TABLE t6 USING INDEX bb (b<?)}
|
||||
do_eqp_test 25.2.2 { SELECT * FROM t6 WHERE a<20 AND b<? } \
|
||||
{SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
|
||||
# Term (b BETWEEN ? AND ?) is estimated at 1/64.
|
||||
do_eqp_test 25.3.1 {
|
||||
SELECT * FROM t6 WHERE a BETWEEN 5 AND 10 AND b BETWEEN ? AND ?
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
|
||||
# Term (b BETWEEN ? AND 60) is estimated to return roughly 15 rows -
|
||||
# 60 from (b<=60) multiplied by 0.25 for the b>=? term. Better than
|
||||
# (a<20) but not as good as (a<10).
|
||||
do_eqp_test 25.4.1 {
|
||||
SELECT * FROM t6 WHERE a < 10 AND (b BETWEEN ? AND 60)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX aa (a<?)}
|
||||
|
||||
do_eqp_test 25.4.2 {
|
||||
SELECT * FROM t6 WHERE a < 20 AND (b BETWEEN ? AND 60)
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX bb (b>? AND b<?)}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -1190,9 +1180,7 @@ do_execsql_test 26.1.3 {
|
||||
#
|
||||
do_eqp_test 26.1.4 {
|
||||
SELECT * FROM t1 WHERE x = 10000 AND y < 50 AND z = 444;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1z (z=?)}
|
||||
|
||||
|
||||
# This test - 26.2.* - tests that another manifestation of the same problem
|
||||
@@ -1241,9 +1229,7 @@ do_execsql_test 26.2.1 {
|
||||
|
||||
do_eqp_test 26.2.2 {
|
||||
SELECT * FROM t1 WHERE x='B' AND y>25 AND z=?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (x=? AND y>?)}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
+8
-8
@@ -136,10 +136,10 @@ foreach {tn analyze_cmd} {
|
||||
|
||||
do_eqp_test 1.$tn.2.5 {
|
||||
SELECT * FROM t1 WHERE b = 31 AND c = 0;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b=?)}
|
||||
do_eqp_test 1.$tn.2.6 {
|
||||
SELECT * FROM t1 WHERE b = 125 AND c = 16;
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c=?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c=?)}
|
||||
|
||||
do_execsql_test 1.$tn.3.1 {
|
||||
SELECT count(*) FROM t1 WHERE b BETWEEN 0 AND 50
|
||||
@@ -156,31 +156,31 @@ foreach {tn analyze_cmd} {
|
||||
|
||||
do_eqp_test 1.$tn.3.5 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN 0 AND 50 AND c BETWEEN 0 AND 50
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.6 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN 75 AND 125 AND c BETWEEN 75 AND 125
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.7 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN +0 AND +50 AND c BETWEEN +0 AND +50
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.8 {
|
||||
SELECT * FROM t1
|
||||
WHERE b BETWEEN cast('0' AS int) AND cast('50.0' AS real)
|
||||
AND c BETWEEN cast('0' AS numeric) AND cast('50.0' AS real)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.9 {
|
||||
SELECT * FROM t1 WHERE b BETWEEN +75 AND +125 AND c BETWEEN +75 AND +125
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
|
||||
|
||||
do_eqp_test 1.$tn.3.10 {
|
||||
SELECT * FROM t1
|
||||
WHERE b BETWEEN cast('75' AS int) AND cast('125.0' AS real)
|
||||
AND c BETWEEN cast('75' AS numeric) AND cast('125.0' AS real)
|
||||
} {0 0 0 {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}}
|
||||
} {SEARCH TABLE t1 USING INDEX t1c (c>? AND c<?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+4
-12
@@ -63,9 +63,7 @@ do_test 1.1 {
|
||||
#
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a=3001 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
|
||||
do_test 1.3 {
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
@@ -80,9 +78,7 @@ do_test 1.3 {
|
||||
#
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM t1 WHERE a=3001 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_ab (a=?)}
|
||||
|
||||
do_test 1.5 {
|
||||
execsql {
|
||||
@@ -93,9 +89,7 @@ do_test 1.5 {
|
||||
|
||||
do_eqp_test 1.6 {
|
||||
SELECT * FROM t1 WHERE a=13 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
|
||||
do_test 1.7 {
|
||||
execsql { DELETE FROM sqlite_stat1 }
|
||||
@@ -108,8 +102,6 @@ do_test 1.7 {
|
||||
# gets this right, even without stat1 data.
|
||||
do_eqp_test 1.8 {
|
||||
SELECT * FROM t1 WHERE a=13 AND c=150;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX t1_c (c=?)}
|
||||
|
||||
finish_test
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ foreach {tn where idx} {
|
||||
11 "x = nullif('19', 0) AND y = nullif('4', 0)" {t1y (y=?)}
|
||||
12 "x = nullif('4', 0) AND y = nullif('19', 0)" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
set res "SEARCH TABLE t1 USING INDEX $idx"
|
||||
do_eqp_test 1.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ foreach {tn where idx} {
|
||||
3 "x = nondet4() AND y = nondet19()" {t1y (y=?)}
|
||||
4 "x = nondet19() AND y = nondet4()" {t1y (y=?)}
|
||||
} {
|
||||
set res "0 0 0 {SEARCH TABLE t1 USING INDEX $idx}"
|
||||
set res "SEARCH TABLE t1 USING INDEX $idx"
|
||||
do_eqp_test 3.$tn "SELECT * FROM t1 WHERE $where" $res
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,11 @@ ifcapable {!autoinc} {
|
||||
return
|
||||
}
|
||||
|
||||
if {[permutation]=="inmemory_journal"} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
|
||||
# The database is initially empty.
|
||||
@@ -675,6 +680,173 @@ do_execsql_test autoinc-10.1 {
|
||||
SELECT * FROM sqlite_sequence;
|
||||
} {t10a 888 t10b 888}
|
||||
|
||||
# 2018-04-21 autoincrement does not cause problems for upsert
|
||||
#
|
||||
do_execsql_test autoinc-11.1 {
|
||||
CREATE TABLE t11(a INTEGER PRIMARY KEY AUTOINCREMENT,b UNIQUE);
|
||||
INSERT INTO t11(a,b) VALUES(2,3),(5,6),(4,3),(1,2)
|
||||
ON CONFLICT(b) DO UPDATE SET a=a+1000;
|
||||
SELECT seq FROM sqlite_sequence WHERE name='t11';
|
||||
} {5}
|
||||
|
||||
# 2018-05-23 ticket d8dc2b3a58cd5dc2918a1d4acbba4676a23ada4c
|
||||
# Does not crash if the sqlite_sequence table schema is missing
|
||||
# or corrupt.
|
||||
#
|
||||
do_test autoinc-12.1 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE fake_sequence(name TEXT PRIMARY KEY,seq) WITHOUT ROWID;
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql=replace(sql,'fake_','sqlite_'),
|
||||
name='sqlite_sequence',
|
||||
tbl_name='sqlite_sequence'
|
||||
WHERE name='fake_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test autoinc-12.2 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql=replace(sql,'sqlite_','x_'),
|
||||
name='x_sequence',
|
||||
tbl_name='x_sequence'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
ifcapable vtab {
|
||||
set err "database disk image is malformed"
|
||||
} else {
|
||||
set err {malformed database schema (sqlite_sequence) - near "VIRTUAL": syntax error}
|
||||
}
|
||||
do_test autoinc-12.3 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE VIRTUAL TABLE sqlite_sequence USING sqlite_dbpage'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} [list 1 $err]
|
||||
do_test autoinc-12.4 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
CREATE TABLE fake(name TEXT PRIMARY KEY,seq) WITHOUT ROWID;
|
||||
}
|
||||
set root1 [db one {SELECT rootpage FROM sqlite_master
|
||||
WHERE name='sqlite_sequence'}]
|
||||
set root2 [db one {SELECT rootpage FROM sqlite_master
|
||||
WHERE name='fake'}]
|
||||
db eval {
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET rootpage=$root2
|
||||
WHERE name='sqlite_sequence';
|
||||
UPDATE sqlite_master SET rootpage=$root1
|
||||
WHERE name='fake';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
breakpoint
|
||||
do_test autoinc-12.5 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE TABLE sqlite_sequence(x)'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two');
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {1 {database disk image is malformed}}
|
||||
do_test autoinc-12.6 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE TABLE sqlite_sequence(x,y INTEGER PRIMARY KEY)'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two'),('three'),('four');
|
||||
INSERT INTO t1(b) VALUES('five');
|
||||
PRAGMA integrity_check;
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {0 ok}
|
||||
do_test autoinc-12.7 {
|
||||
db close
|
||||
forcedelete test.db
|
||||
sqlite3 db test.db
|
||||
db eval {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY AUTOINCREMENT, b TEXT);
|
||||
INSERT INTO t1(b) VALUES('one');
|
||||
PRAGMA writable_schema=on;
|
||||
UPDATE sqlite_master SET
|
||||
sql='CREATE TABLE sqlite_sequence(y INTEGER PRIMARY KEY,x)'
|
||||
WHERE name='sqlite_sequence';
|
||||
}
|
||||
db close
|
||||
sqlite3 db test.db
|
||||
set res [catch {db eval {
|
||||
INSERT INTO t1(b) VALUES('two'),('three'),('four');
|
||||
INSERT INTO t1(b) VALUES('five');
|
||||
PRAGMA integrity_check;
|
||||
}} msg]
|
||||
lappend res $msg
|
||||
} {0 ok}
|
||||
|
||||
finish_test
|
||||
|
||||
+32
-25
@@ -177,35 +177,36 @@ do_execsql_test autoindex1-500 {
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t501',null,'1000000');
|
||||
INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t502',null,'1000');
|
||||
ANALYZE sqlite_master;
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test autoindex1-500.1 {
|
||||
SELECT b FROM t501
|
||||
WHERE t501.a IN (SELECT x FROM t502 WHERE y=?);
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t502}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--LIST SUBQUERY
|
||||
`--SCAN TABLE t502
|
||||
}
|
||||
do_execsql_test autoindex1-501 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test autoindex1-501 {
|
||||
SELECT b FROM t501
|
||||
WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t501}
|
||||
0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
|
||||
1 0 0 {SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t501
|
||||
`--CORRELATED LIST SUBQUERY
|
||||
`--SEARCH TABLE t502 USING AUTOMATIC COVERING INDEX (y=?)
|
||||
}
|
||||
do_execsql_test autoindex1-502 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test autoindex1-502 {
|
||||
SELECT b FROM t501
|
||||
WHERE t501.a=123
|
||||
AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b);
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {EXECUTE CORRELATED LIST SUBQUERY 1}
|
||||
1 0 0 {SCAN TABLE t502}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t501 USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--CORRELATED LIST SUBQUERY
|
||||
`--SCAN TABLE t502
|
||||
}
|
||||
|
||||
|
||||
# The following code checks a performance regression reported on the
|
||||
# mailing list on 2010-10-19. The problem is that the nRowEst field
|
||||
# of ephermeral tables was not being initialized correctly and so no
|
||||
@@ -257,7 +258,8 @@ do_execsql_test autoindex1-600 {
|
||||
ON sheep (originating_flock);
|
||||
CREATE INDEX sheep_reg_flock_index
|
||||
ON sheep (registering_flock);
|
||||
EXPLAIN QUERY PLAN
|
||||
}
|
||||
do_eqp_test autoindex1-600a {
|
||||
SELECT x.sheep_no, x.registering_flock, x.date_of_registration
|
||||
FROM sheep x LEFT JOIN
|
||||
(SELECT s.sheep_no, prev.flock_no, prev.owner_person_id,
|
||||
@@ -274,21 +276,26 @@ do_execsql_test autoindex1-600 {
|
||||
WHERE y.sheep_no IS NULL
|
||||
ORDER BY x.registering_flock;
|
||||
} {
|
||||
1 0 0 {SCAN TABLE sheep AS s}
|
||||
1 1 1 {SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)}
|
||||
1 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 2}
|
||||
2 0 0 {SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)}
|
||||
0 0 0 {SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index}
|
||||
0 1 1 {SEARCH SUBQUERY 1 AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)}
|
||||
QUERY PLAN
|
||||
|--MATERIALIZE xxxxxx
|
||||
| |--SCAN TABLE sheep AS s
|
||||
| |--SEARCH TABLE flock_owner AS prev USING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date<?)
|
||||
| `--CORRELATED SCALAR SUBQUERY
|
||||
| `--SEARCH TABLE flock_owner AS later USING COVERING INDEX sqlite_autoindex_flock_owner_1 (flock_no=? AND owner_change_date>? AND owner_change_date<?)
|
||||
|--SCAN TABLE sheep AS x USING INDEX sheep_reg_flock_index
|
||||
`--SEARCH SUBQUERY xxxxxx AS y USING AUTOMATIC COVERING INDEX (sheep_no=?)
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test autoindex1-700 {
|
||||
CREATE TABLE t5(a, b, c);
|
||||
EXPLAIN QUERY PLAN SELECT a FROM t5 WHERE b=10 ORDER BY c;
|
||||
}
|
||||
do_eqp_test autoindex1-700a {
|
||||
SELECT a FROM t5 WHERE b=10 ORDER BY c;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t5}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t5
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
# The following checks a performance issue reported on the sqlite-dev
|
||||
|
||||
@@ -84,8 +84,9 @@ do_execsql_test 210 {
|
||||
do_eqp_test 220 {
|
||||
select count(*) from u, v where u.b = v.b and v.e > 34;
|
||||
} {
|
||||
0 0 1 {SEARCH TABLE v USING INDEX ve (e>?)}
|
||||
0 1 0 {SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE v USING INDEX ve (e>?)
|
||||
`--SEARCH TABLE u USING AUTOMATIC COVERING INDEX (b=?)
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -84,8 +84,7 @@ do_execsql_test autoindex5-1.0 {
|
||||
# The following query should use an automatic index for the view
|
||||
# in FROM clause of the subquery of the second result column.
|
||||
#
|
||||
do_execsql_test autoindex5-1.1 {
|
||||
EXPLAIN QUERY PLAN
|
||||
do_eqp_test autoindex5-1.1 {
|
||||
SELECT
|
||||
st.bug_name,
|
||||
(SELECT ALL debian_cve.bug FROM debian_cve
|
||||
@@ -103,7 +102,7 @@ do_execsql_test autoindex5-1.1 {
|
||||
AND ( sp.release = 'sid' OR sp.release = 'stretch' OR sp.release = 'jessie'
|
||||
OR sp.release = 'wheezy' OR sp.release = 'squeeze' )
|
||||
ORDER BY sp.name, st.bug_name, sp.release, sp.subrelease;
|
||||
} {/SEARCH SUBQUERY 2 USING AUTOMATIC COVERING INDEX .bug_name=/}
|
||||
} {SEARCH SUBQUERY * USING AUTOMATIC COVERING INDEX (bug_name=?)}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that ticket [8a2adec1] has been fixed.
|
||||
|
||||
+12
-17
@@ -51,16 +51,11 @@ do_execsql_test 1.0 {
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM x1 WHERE a = 'abc'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
}
|
||||
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM x1 WHERE a IN ('abc', 'def');
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
}
|
||||
} {SCAN TABLE x1 VIRTUAL TABLE INDEX 555:eq!}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -145,24 +140,24 @@ foreach {tn mode} {
|
||||
} {1 4}
|
||||
|
||||
set plan(use) {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
set plan(omit) {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x WHERE a='%1%'
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
set plan(use2) {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x}
|
||||
0 0 0 {EXECUTE LIST SUBQUERY 1}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:SELECT * FROM t1x
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 2.2.$mode.6 {
|
||||
SELECT rowid FROM t1 WHERE a IN ('one', 'four') ORDER BY +rowid
|
||||
} $plan($mode)
|
||||
} [string map {"\n " "\n"} $plan($mode)]
|
||||
}
|
||||
|
||||
# 2016-04-09.
|
||||
|
||||
+22
-21
@@ -89,40 +89,40 @@ do_execsql_test 1.0 {
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM t1 WHERE a='abc'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a='abc' AND b='def'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=? AND b=?)}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM t1 WHERE a='abc' AND a='def'
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:indexed(a=?)}
|
||||
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM t1,t2 WHERE c=a
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
`--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
}
|
||||
|
||||
do_eqp_test 1.5 {
|
||||
SELECT * FROM t1, t2 CROSS JOIN t3 WHERE t2.c = +t1.b AND t3.e=t2.d
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
|
||||
}
|
||||
|
||||
do_eqp_test 1.6 {
|
||||
SELECT * FROM t1, t2, t3 WHERE t2.c = +t1.b AND t3.e = t2.d
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 1 1 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
0 2 2 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
|
||||
}
|
||||
|
||||
do_execsql_test 1.7.1 {
|
||||
@@ -132,10 +132,11 @@ do_eqp_test 1.7.2 {
|
||||
SELECT * FROM x1 CROSS JOIN t1, t2, t3
|
||||
WHERE t1.a = t2.c AND t1.b = t3.e
|
||||
} {
|
||||
0 0 0 {SCAN TABLE x1}
|
||||
0 1 1 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:}
|
||||
0 2 2 {SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)}
|
||||
0 3 3 {SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE x1
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:
|
||||
|--SCAN TABLE t2 VIRTUAL TABLE INDEX 0:indexed(c=?)
|
||||
`--SCAN TABLE t3 VIRTUAL TABLE INDEX 0:indexed(e=?)
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+16
-14
@@ -79,28 +79,28 @@ do_execsql_test 1.0 {
|
||||
|
||||
do_eqp_test 1.1 {
|
||||
SELECT * FROM t1 WHERE a LIKE 'abc';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
|
||||
|
||||
do_eqp_test 1.2 {
|
||||
SELECT * FROM t1 WHERE a = 'abc';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
|
||||
}
|
||||
} {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
|
||||
|
||||
do_eqp_test 1.3 {
|
||||
SELECT * FROM t1 WHERE a = 'abc' OR b = 'def';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?}
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
|
||||
QUERY PLAN
|
||||
`--MULTI-INDEX OR
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a EQ ?
|
||||
`--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
|
||||
}
|
||||
|
||||
do_eqp_test 1.4 {
|
||||
SELECT * FROM t1 WHERE a LIKE 'abc%' OR b = 'def';
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?}
|
||||
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?}
|
||||
QUERY PLAN
|
||||
`--MULTI-INDEX OR
|
||||
|--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:a LIKE ?
|
||||
`--SCAN TABLE t1 VIRTUAL TABLE INDEX 0:b EQ ?
|
||||
}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
@@ -147,10 +147,12 @@ ifcapable !icu {
|
||||
|
||||
do_eqp_test 2.2 {
|
||||
SELECT * FROM t2 WHERE x LIKE 'abc%' OR y = 'def'
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)}
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2y (y=?)}
|
||||
}
|
||||
} [string map {"\n " \n} {
|
||||
QUERY PLAN
|
||||
`--MULTI-INDEX OR
|
||||
|--SEARCH TABLE t2 USING INDEX t2x (x>? AND x<?)
|
||||
`--SEARCH TABLE t2 USING INDEX t2y (y=?)
|
||||
}]
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
+6
-6
@@ -92,13 +92,13 @@ for {set i 0} {$i < 9} {incr i} {
|
||||
SELECT * FROM t$t AS o WHERE
|
||||
NOT EXISTS( SELECT * FROM t$t AS i WHERE a=o.a AND +b=o.b AND +c=o.c )
|
||||
ORDER BY b, c;
|
||||
" "
|
||||
0 0 0 {SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1}
|
||||
0 0 0 {EXECUTE CORRELATED SCALAR SUBQUERY 1}
|
||||
1 0 0 {SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
"
|
||||
" [string map {"\n " "\n"} "
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t$t AS o USING COVERING INDEX sqlite_autoindex_t${t}_1
|
||||
`--CORRELATED SCALAR SUBQUERY
|
||||
`--SEARCH TABLE t$t AS i USING INTEGER PRIMARY KEY (rowid=?)
|
||||
"]
|
||||
}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -273,4 +273,23 @@ do_execsql_test 5.1 {
|
||||
ORDER BY id;
|
||||
} {8 9 10 11 12 13 14 15}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# At one point the following join query was causing a malfunction in
|
||||
# xBestIndex.
|
||||
#
|
||||
do_execsql_test 6.0 {
|
||||
CREATE TABLE t4 (
|
||||
id INTEGER PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
parent_id INTEGER
|
||||
);
|
||||
CREATE VIRTUAL TABLE vt4 USING transitive_closure (
|
||||
idcolumn=id, parentcolumn=parent_id, tablename=t4
|
||||
);
|
||||
}
|
||||
|
||||
do_execsql_test 6.1 {
|
||||
SELECT * FROM t4, vt4 WHERE t4.id = vt4.root AND vt4.id=4 AND vt4.depth=2;
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
+40
-47
@@ -24,8 +24,9 @@ do_execsql_test 1.1 {
|
||||
do_eqp_test 1.2 {
|
||||
SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t3 USING COVERING INDEX i3}
|
||||
0 1 1 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t3 USING COVERING INDEX i3
|
||||
`--SEARCH TABLE t4 USING INDEX i4 (c=?)
|
||||
}
|
||||
|
||||
|
||||
@@ -38,9 +39,7 @@ do_execsql_test 2.1 {
|
||||
# if the index is a non-covering index.
|
||||
do_eqp_test 2.2 {
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING INDEX i1}
|
||||
}
|
||||
} {SCAN TABLE t1 USING INDEX i1}
|
||||
|
||||
do_execsql_test 3.1 {
|
||||
CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
|
||||
@@ -57,10 +56,12 @@ do_eqp_test 3.2 {
|
||||
WHERE b IS NULL OR c IS NULL OR d IS NULL
|
||||
ORDER BY a;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t5 USING INDEX t5b (b=?)}
|
||||
0 0 0 {SEARCH TABLE t5 USING INDEX t5c (c=?)}
|
||||
0 0 0 {SEARCH TABLE t5 USING INDEX t5d (d=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--MULTI-INDEX OR
|
||||
| |--SEARCH TABLE t5 USING INDEX t5b (b=?)
|
||||
| |--SEARCH TABLE t5 USING INDEX t5c (c=?)
|
||||
| `--SEARCH TABLE t5 USING INDEX t5d (d=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -79,14 +80,11 @@ do_execsql_test 4.1 {
|
||||
}
|
||||
do_eqp_test 4.2 {
|
||||
SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX i1 (a=?)}
|
||||
|
||||
do_eqp_test 4.3 {
|
||||
SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
|
||||
}
|
||||
} {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
|
||||
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -100,15 +98,17 @@ do_execsql_test 5.1 {
|
||||
do_eqp_test 5.2 {
|
||||
SELECT * FROM t2 ORDER BY x, y;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2 USING INDEX t2i1}
|
||||
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE t2 USING INDEX t2i1
|
||||
`--USE TEMP B-TREE FOR RIGHT PART OF ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 5.3 {
|
||||
SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
# where7.test, where8.test:
|
||||
@@ -122,9 +122,11 @@ do_execsql_test 6.1 {
|
||||
do_eqp_test 6.2 {
|
||||
SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)}
|
||||
0 0 0 {SEARCH TABLE t3 USING INDEX t3i2 (c=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--MULTI-INDEX OR
|
||||
| |--SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)
|
||||
| `--SEARCH TABLE t3 USING INDEX t3i2 (c=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -145,9 +147,11 @@ do_eqp_test 7.2 {
|
||||
WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
|
||||
ORDER BY a
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
|
||||
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
|
||||
QUERY PLAN
|
||||
|--MULTI-INDEX OR
|
||||
| |--SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)
|
||||
| `--SEARCH TABLE t1 USING INDEX t1b (b=?)
|
||||
`--USE TEMP B-TREE FOR ORDER BY
|
||||
}
|
||||
|
||||
do_eqp_test 7.3 {
|
||||
@@ -155,15 +159,11 @@ do_eqp_test 7.3 {
|
||||
WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
|
||||
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
|
||||
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
do_eqp_test 7.4 {
|
||||
SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1}
|
||||
}
|
||||
} {SCAN TABLE t1}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
@@ -194,10 +194,11 @@ do_eqp_test 8.2 {
|
||||
AND unlikely(composer.cid=track.cid)
|
||||
AND unlikely(album.aid=track.aid);
|
||||
} {
|
||||
0 0 2 {SCAN TABLE track}
|
||||
0 1 0 {SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 2 1 {SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)}
|
||||
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
|
||||
QUERY PLAN
|
||||
|--SCAN TABLE track
|
||||
|--SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)
|
||||
|--SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)
|
||||
`--USE TEMP B-TREE FOR DISTINCT
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
@@ -263,27 +264,19 @@ ifcapable stat4 {
|
||||
|
||||
do_eqp_test 10.3 {
|
||||
SELECT rowid FROM t6 WHERE a=0 AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
|
||||
do_eqp_test 10.4 {
|
||||
SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
|
||||
|
||||
do_eqp_test 10.5 {
|
||||
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
|
||||
|
||||
do_eqp_test 10.6 {
|
||||
SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
|
||||
} {
|
||||
0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
|
||||
}
|
||||
} {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -109,16 +109,11 @@ do_execsql_test 5.1.0 "
|
||||
|
||||
do_eqp_test 5.1.1 {
|
||||
SELECT * FROM t1 ORDER BY c1, c2;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
}
|
||||
} {SCAN TABLE t1 USING COVERING INDEX i1}
|
||||
|
||||
do_eqp_test 5.1.2 {
|
||||
SELECT * FROM t2 ORDER BY c1, c2;
|
||||
} {
|
||||
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i2}
|
||||
}
|
||||
|
||||
} {SCAN TABLE t2 USING COVERING INDEX i2}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -140,5 +140,21 @@ do_catchsql_test 4.2 {
|
||||
);
|
||||
} {1 {vtable constructor failed: t5}}
|
||||
|
||||
# 2018-04-24
|
||||
# Memory leak reported on the sqlite-users mailing list by Ralf Junker.
|
||||
#
|
||||
do_catchsql_test 4.3 {
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS temp.t1
|
||||
USING csv(filename='FileDoesNotExist.csv');
|
||||
} {1 {cannot open 'FileDoesNotExist.csv' for reading}}
|
||||
|
||||
# 2018-06-02
|
||||
# Problem with single-column CSV support reported on the mailing list
|
||||
# by Trent W. Buck.
|
||||
#
|
||||
do_execsql_test 4.4 {
|
||||
CREATE VIRTUAL TABLE temp.trent USING csv(data='1');
|
||||
SELECT * FROM trent;
|
||||
} {1}
|
||||
|
||||
finish_test
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user