Compare commits

..

58 Commits

Author SHA1 Message Date
drh 51caa04836 Merge the dbtotxt enhancement from trunk.
FossilOrigin-Name: b386fce9a23e628dce7362dcca2904b8d0af6da58a6fe6eb7f12f058a8363e49
2018-12-13 15:52:31 +00:00
drh 3374648545 Add the "dbtotxt" utility program and the ability to read "dbtotxt" output
as a deserialized input database in the CLI, using the --hexdb option to
the ".open" command.

FossilOrigin-Name: e3bf1d3ea5f748c5142c2403813fdace5aedc1fc68f0dcd5eae40a2fe763fedb
2018-12-13 15:06:26 +00:00
drh 69a66a7be1 Include OPTS in the build of dbfuzz2.
FossilOrigin-Name: eac9c0c49650b008951318a2225b932709a0a8dffbb01ed57684c40357b2e25c
2018-12-13 12:37:13 +00:00
drh bc1be957c1 Fix the Makefile so that it honors CFLAGS when building sessionfuzz.
FossilOrigin-Name: 54231ac4ca506e6c34c31bc02bb8d3db22f14e1b01679bc70529b165d7dabb83
2018-12-13 12:28:01 +00:00
drh 5881dfea2c New database corruption test cases discovered by dbfuzz2. The new cases
have been added to test/fuzzdata7.db, but have not yet all been fixed,
so tests will not currently pass.

FossilOrigin-Name: b4210d320c6426d2838d4cc08709fdfd015c1c95fcad9a5f9e8fd390c23b9fad
2018-12-13 03:36:13 +00:00
drh cb0e04f929 Fix another problem found by Matthew Denton's new fuzzer.
FossilOrigin-Name: 2b690dbdffe144bd69ca0aa291c230faf3d9d73f7a2985d50f016fe54003f9a9
2018-12-12 21:34:17 +00:00
drh 89b6de0357 Remove an ALWAYS() from a branch that is not always taken. The test case
found by OSSFuzz has been added to TH3.

FossilOrigin-Name: 5c7dab85535ac42c021977dbd4a39cef5a72e3d9dccff1c5ca5570a1780516cd
2018-12-12 20:11:23 +00:00
drh 03c5c21328 OSSFuzz found a case where an assert() inside sqlite3ExprCompare() can be
true.  Test case added to TH3.

FossilOrigin-Name: 23b62fb160d86dc9d9073bcc714601f5b7695f96abd893eafecf4b2e565b87f2
2018-12-12 11:23:40 +00:00
drh cfc078318c Small performance improvement in sqlite3_step().
FossilOrigin-Name: d1db8d5894450b24bb0335983503d9bbf6cc48a0ae4b83291283fb2d32b6b25b
2018-12-11 12:51:46 +00:00
drh 368bfe8b00 Small performance improvement in the sqlite3_bind() family of interfaces.
FossilOrigin-Name: 1dc0c3df32572f09265fc73eeaa0748159e0e9523b9b2d6768b834a29c909968
2018-12-11 12:20:41 +00:00
drh 1a6c2b1d38 Further refinements to the sqlite3_normalized_sql() interface. TH3 now
gives 100% MC/DC on that interface.

FossilOrigin-Name: c96bf6cca220e363b099455ce35195ce7e89d374a52dc787f56e7b11e587bced
2018-12-10 20:01:40 +00:00
drh 21b9225ff5 Refactor the sqlite3_normalized_sql() implementation.
FossilOrigin-Name: 06e955e5d2b857b9ce94a73fb174b620c101bdb160842f9a0e958bdb48e8c987
2018-12-10 18:15:44 +00:00
drh 9042ff214b Fix issues with the new normalizer.
FossilOrigin-Name: 057d7d40c56b7416a59a79cb627b2b3e5837eca2d6dbcb50127baaadf1941f51
2018-12-10 16:49:33 +00:00
drh 643d855da9 Refactor the sqlite3_normalized_sql() implementation. This is a
work-in-progress. There are still issues.

FossilOrigin-Name: a4c890b0af9786295e6df05022009d8946550adb873535c610be805c2b7a4083
2018-12-10 16:00:57 +00:00
dan dc6214ee39 Fix a problem with using "<db>-vacuum" (the default) as the state database
when resuming an RBU vacuum.

FossilOrigin-Name: c878d741733a897d47a1a0b57b454bc9095ce302b48cc01089336d5d20e2a24c
2018-12-10 08:41:32 +00:00
drh fb34559eb1 Add support for the VACUUM INTO command.
FossilOrigin-Name: 77f150b8b46761f4f62f9d8926c10a95a70589a4525393fc16b321bd98c083a7
2018-12-10 01:48:29 +00:00
drh 4d342827d6 Fix the shell1.test test for the new format of the .backup command.
FossilOrigin-Name: 9748d7995bc1dd632d66d2d326048d50e29c6f5e6993d5a6294d14421d2cb72f
2018-12-10 00:41:28 +00:00
drh 2134eb5721 Merge fixes from trunk.
FossilOrigin-Name: ab1e58fac9e3f9d7d90cefb39f8f145d211d38ec0cb393208c4531cc646056c1
2018-12-10 00:40:43 +00:00
drh ce706c2cf3 New test case for ticket [1d958d90596593a77420e59].
FossilOrigin-Name: b7bf3c9832bde26b359f4d58ebcf7788c500586d311387d022192ed65a126252
2018-12-09 18:55:05 +00:00
drh d4a4a36171 Do not use a partial index as a table scan in an IN operator.
Fix for ticket [1d958d90596593a77420e59].

FossilOrigin-Name: 15bc915dd7ae25bfdfbe357c3792db3639799e4d121c6b5b24297af2d6d7129e
2018-12-08 20:30:31 +00:00
drh a50bffb85e Add the --async option to the ".backup" command in the CLI.
FossilOrigin-Name: 7b6a605b1883dfcbe237b0a58f6f0c233a109e88b521c3b3d97198526c8a0317
2018-12-08 01:09:14 +00:00
drh 2f6239ed4e Allow the INTO clause of VACUUM to be a text-valued expression.
FossilOrigin-Name: af172b53b46759f491f522356e14c5e2374d3f25ec70fbc1e100cadded8f9b22
2018-12-08 00:43:08 +00:00
drh 7464f578ed Do not allow VACUUM INTO into a file that already exists.
FossilOrigin-Name: 92f70e0fa3c9de7fde046f11cc0a7c2800511bb5ace8e68c845133931607616e
2018-12-07 23:48:41 +00:00
drh 52993b31e1 Merge the VACUUM simplification from trunk.
FossilOrigin-Name: 93d92a0a5d21a1856316c0205ecaa253691b6e5349b552d43027005676d14820
2018-12-07 20:40:12 +00:00
drh 83da91b7bd Remove a line of code from VACUUM that is no longer needed, due to the
change that allows ATTACH to run within a transaction.

FossilOrigin-Name: a92c398fc5df142ff1459c1be4a6832f2219bc7fabe5789535be3bbd41a4269b
2018-12-07 20:26:29 +00:00
drh b0b7db91b8 Prototype implementation for the VACUUM INTO command.
FossilOrigin-Name: 036e3320a4af36c1311b25b2e504b0079c8b33df8ad7b7e5fddad07150e6f87d
2018-12-07 17:28:28 +00:00
drh 893bd3751b Fix the sqlite3_normalized_sql() interface so that it renders
double-quoted string literals as "?".

FossilOrigin-Name: 0d8e150434bbd179696f1ffe71d1e06cb3d43e6468496c7e481fca8486387bad
2018-12-07 16:32:11 +00:00
drh 62a88294e8 Fix dbfuzz2.c so that it works with -DSQLITE_OMIT_INIT
FossilOrigin-Name: 9ad796a8822f1b7e1e99b73c2cc5be59dbfd85e9c27f3e795c29a2c002c611d1
2018-12-07 03:01:07 +00:00
drh b9a0e668f3 Fix the sqlite3ExprDup() function so that it correctly duplicates the
Window object list on a Select that contains window functions.  Fix
for ticket [f09fcd17810f65f717].

FossilOrigin-Name: db5ed2268eda2e6c1df15cd8df4176463d89103b8fda33ba9a0604f0d92bd4da
2018-12-07 01:56:26 +00:00
drh a37b6a5e31 Performance improvement: Avoid using sqlite3WalkerSelectExpr()
and sqlite3WalkerSelectFrom() twice, so that the compiler will in-line their
implementation.

FossilOrigin-Name: 2b9258b8b0342330ebe8c22b59ec276fd042a05547d15b24fdf29e16280868de
2018-12-06 22:12:18 +00:00
drh a838997544 Fix the sqlite3ExprDup() routine so that it makes complete duplications of
subqueries containing window functions.

FossilOrigin-Name: 940174543e87184a0278fcd02e8a096a11510174d9c1d65d21878819790ddaff
2018-12-06 22:04:19 +00:00
drh bb383df7c6 New test case that still hits an assertion fault, just to prove that the
previous checkin merely made the problem more obscure and did not completely
fix it.

FossilOrigin-Name: a9a3b532643b5f106509bb29c3e6bc9d41ec5b2da5a0cd4067898f376eb626a2
2018-12-06 19:56:20 +00:00
drh 11df7d2839 Simplify the query flattener so that it does not duplicate the WHERE clause
of subquery that is being incorporated into the outer query - copies it
directly.  This is more efficient.  And it also fixes the specific test case
show for ticket [f09fcd17810f65f71789525] but it does not resolve the more
general problem that sqlite3ExprDup() does not correctly duplicate expressions
that contain subqueries with window functions.

FossilOrigin-Name: f1b18d44ff855573542c1947a42d4025dff54cacc13dac14d044521762ea9736
2018-12-06 19:15:36 +00:00
drh d5b44d60c7 When masking bits off of sqlite3.flags, make sure the mask is 64 bits
in size so as not to accidentally mask of high-order bits.

FossilOrigin-Name: 53d3b169d8e1892163526caff2c843302c92e280fdeff6831e23a9bb15b82be3
2018-12-06 17:06:02 +00:00
drh 70d5dfba68 When saving off the value of sqlite3.flags, take care to preserve all 64
bits.

FossilOrigin-Name: 9c6dbcfab5952cf4e54de30cf9cee48f988b91a35dc3f04d64d6d994dd84a076
2018-12-06 16:50:55 +00:00
drh ec8fc62c42 Issue a warning whenever a double-quoted string literal is used.
FossilOrigin-Name: ac9ad5043026b30394812457e1535df2759aea0d4510029561e92e386672796f
2018-12-06 16:11:14 +00:00
drh 3e2d47d49f Invoking the sqlite3_trace() or sqlite3_trace_v2() interfaces cancels
any sqlite3_profile() that is running.

FossilOrigin-Name: ec63d3506bd429560077f82a4c5ed9d189780789fe1c134fff4f3b8733be1a3f
2018-12-06 03:59:25 +00:00
drh fc08a1aef8 Remove the unused pColHash field from the Table object.
FossilOrigin-Name: 3a2c047989facc3461c63a2f9eed412014c951035a80da47c52a70139fb552de
2018-12-06 02:01:17 +00:00
drh 974b24896a Fix a potential NULL pointer dereference that can occur in ALTER TABLE
following an OOM.  Test case in TH3.

FossilOrigin-Name: ea50815bf80ab0d36891518f209acbcd3d6d8d84529741bffd4e841874c78aff
2018-12-06 01:53:12 +00:00
drh 1f169fefca Fix a missing mutex in the sqlite3_normalized_sql() interface when it is
called on a prepared statement that did not previously have a computed
normalization of the input SQL.

FossilOrigin-Name: 1a1a59c6c570879c8f318bbc132103c0285088ba233dd8c32e049b86419347b0
2018-12-06 01:08:58 +00:00
drh 7b278f0c3d Get rid of the hash table used to track IN operators in the
sqlite3_normalized_sql() implementation.  Use simple integer variables
instead.

FossilOrigin-Name: 272dc74fd0304d6a28aaa8798d13e2f950c1a24d92d17519e3c32aef86714586
2018-12-05 23:56:02 +00:00
drh 253a6af532 The sqlite3_normalized_sql() interface should not be transforming quoted
identifier names into wildcards.  Fix this, and at the same time simplify
the code substantially.

FossilOrigin-Name: e8540377ec66fa5f9ae3c93bedb5c094057698199c37fc211f7ea95429e815e4
2018-12-05 23:45:46 +00:00
drh d4a4dd6ebc Fix an imbalanced lock problem in sqlite3Normalize() introduced by the
simplification in [94ea6379178e3ff6a].

FossilOrigin-Name: f69624373e33c4d370a9264a317ffdb0adbce967a950f243de2b41161a8c7ded
2018-12-05 21:55:39 +00:00
drh 8a65380de9 Increase the version number to 3.27.0 for the next development cycle.
FossilOrigin-Name: 8f8d682825d065bcaebda4cba63f8b67789b923d8b62eb7c576a5bc01536f577
2018-12-05 19:42:59 +00:00
drh 19efd0db41 Simplifications to the sqlite3_normalized_sql() implementation.
FossilOrigin-Name: 94ea6379178e3ff6a0d1d5819ca4ac558bdadb1ca8a3637c797079db7dc0cd61
2018-12-05 17:48:57 +00:00
dan ea41251eb0 Ensure that ALTER TABLE modifies table and column names embedded in WITH
clauses that are part of views and triggers.

FossilOrigin-Name: f44bc7a8b3fac82aa5598e9bdaf65ea4dd3c331cf90c1d5ba26ff1698e92c230
2018-12-05 13:49:04 +00:00
drh 707821ff72 Enhance the sqlite3_normalize_sql() interface so that it works even if the
prepared statement was not initially compiled using
SQLITE_PREPARE_NORMALIZED.  Enhance the ".trace" command in the CLI so that
it is able to access the full scope of functionality provided by 
sqlite3_trace_v2() and in particular so that it is able to show normalized
SQL output using the newly enhanced sqlite3_normalize_sql() interface.

FossilOrigin-Name: 7da617e97eb905cb009c47403786682b911e32a630f266e1c53ea72836fc88b5
2018-12-05 13:39:06 +00:00
drh 731dd6ebda Add the "index_usage" utility program.
FossilOrigin-Name: df95455213c9d1db7229e94217e78edc05cbf9e40f39528105494ea6ac52be94
2018-12-04 16:51:42 +00:00
drh 04c6747a80 Performance improvement in sqlite3_step() by creating a new mTrace flag
for the legacy xProfile pointer that is set by sqlite3_profile().

FossilOrigin-Name: e28584e8bc7b7405380064b60523fa6191f827f74075f6d117eb7732d752ba5e
2018-12-04 14:33:02 +00:00
drh b7de827137 Small performance increase in sqlite3_step() for the common case where
it returns SQLITE_ROW.

FossilOrigin-Name: 893448265299f4c70c32c8e92ea66f8d33c1c213b21701f73fa3815514cd5ef6
2018-12-04 13:51:26 +00:00
drh cfc45b1021 Reduce the size of the parser tables generated by Lemon by splitting the
yyRuleInfo structure into separate yyRuleInfoLhs and yyRuleInfoNRhs arrays.

FossilOrigin-Name: 70fe8ec2ae3099b8773834c7ac2e56768addbecd57956ac523e71a7dc264049c
2018-12-03 23:57:27 +00:00
drh f8c2fea195 Remove the unused sqlite3Fts5UnicodeNCat() function.
FossilOrigin-Name: 7149dacf1d440a19f62808b4591c3fa8da202b2ec742d5490a63f2ec005ff9e7
2018-12-03 17:40:46 +00:00
dan e89feee5c3 Add the "remove_diacritics=2" option to the unicode61 tokenizer in both FTS5
and FTS3/4.

FossilOrigin-Name: 06177f3f114b5d804b84c27ac843740282e2176fdf0f7a999feda0e1b624adec
2018-12-03 16:14:49 +00:00
mistachkin 8c53b4e7f6 Update the autoconf makefile for MSVC.
FossilOrigin-Name: 675aba1f8b989cfd99370704ecb09031026dc3321cccad122ea91d816e02fdba
2018-12-03 14:58:07 +00:00
drh de72d2a81a Remove two lines of unnecessary code, for a very small performance increase
and size decrease.

FossilOrigin-Name: 15824ccda0f110794a479b58fbf36082d8c383f34bae9dc0921d96547fb37869
2018-12-03 01:58:02 +00:00
drh 4a5cff73a7 Fix a parser bug in the use of parentheses around table-valued functions.
FossilOrigin-Name: 58a51123d1a6381cc67d3c64ba3468ec5a92c299ad6fd86de0b843d0ffafb846
2018-12-03 01:47:41 +00:00
drh fdc75c9f53 Omit a line of code that has no affect on the outcome.
FossilOrigin-Name: 5d933aa659eb7a13f9ab44fe7762be292a1c3c75b957a3b7e0bc6188257b62f4
2018-12-02 01:15:16 +00:00
drh 04ab586bf3 Very slightly smaller and faster.
FossilOrigin-Name: 27798f17f567ad065f8a99effcb287bc241df7b450330ef890d192c70528e62b
2018-12-01 21:13:41 +00:00
66 changed files with 1783 additions and 801 deletions
+9 -2
View File
@@ -669,7 +669,7 @@ ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.
$(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS)
sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h
$(CC) $(CFLAGS) -I. -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
$(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS)
dbfuzz$(TEXE): $(TOP)/test/dbfuzz.c sqlite3.c sqlite3.h
$(LTLINK) -o $@ $(DBFUZZ_OPT) $(TOP)/test/dbfuzz.c sqlite3.c $(TLIBS)
@@ -685,7 +685,8 @@ DBFUZZ2_OPTS = \
-DSQLITE_EANBLE_FTS5
dbfuzz2: $(TOP)/test/dbfuzz2.c sqlite3.c sqlite3.h
clang-6.0 -I. -g -O0 -fsanitize=fuzzer,undefined,address -o dbfuzz2 \
clang-6.0 $(OPT_FEATURE_FLAGS) $(OPTS) -I. -g -O0 \
-fsanitize=fuzzer,undefined,address -o dbfuzz2 \
$(DBFUZZ2_OPTS) $(TOP)/test/dbfuzz2.c sqlite3.c
mkdir -p dbfuzz2-dir
cp $(TOP)/test/dbfuzz2-seed* dbfuzz2-dir
@@ -1291,6 +1292,9 @@ dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
dbtotxt$(TEXE): $(TOP)/tool/dbtotxt.c
$(LTLINK)-o $@ $(TOP)/tool/dbtotxt.c
showdb$(TEXE): $(TOP)/tool/showdb.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showdb.c sqlite3.lo $(TLIBS)
@@ -1306,6 +1310,9 @@ showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
showshm$(TEXE): $(TOP)/tool/showshm.c
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
index_usage$(TEXE): $(TOP)/tool/index_usage.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/index_usage.c sqlite3.lo $(TLIBS)
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
+7
View File
@@ -2425,6 +2425,9 @@ testloadext.lo: $(TOP)\src\test_loadext.c $(SQLITE3H)
testloadext.dll: testloadext.lo
$(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /OUT:$@ testloadext.lo
dbtotxt.exe: $(TOP)\tool\dbtotxt.c
$(LTLINK) $(NO_WARN) $(TOP)\tool\dbtotxt.c /link $(LDFLAGS) $(LTLINKOPTS)
showdb.exe: $(TOP)\tool\showdb.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(TOP)\tool\showdb.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
@@ -2444,6 +2447,10 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
showshm.exe: $(TOP)\tool\showshm.c
$(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
index_usage.exe: $(TOP)\tool\index_usage.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(TOP)\tool\index_usage.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
+1 -1
View File
@@ -1 +1 @@
3.26.0
3.27.0
+2
View File
@@ -283,6 +283,7 @@ OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_STMTVTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DBSTAT_VTAB=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_INTROSPECTION_PRAGMAS=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
@@ -937,6 +938,7 @@ LIBRESOBJS =
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DESERIALIZE=1
!ENDIF
Vendored
+9 -9
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.26.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.27.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.26.0'
PACKAGE_STRING='sqlite 3.26.0'
PACKAGE_VERSION='3.27.0'
PACKAGE_STRING='sqlite 3.27.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -1466,7 +1466,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.26.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.27.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1531,7 +1531,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.26.0:";;
short | recursive ) echo "Configuration of sqlite 3.27.0:";;
esac
cat <<\_ACEOF
@@ -1657,7 +1657,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.26.0
sqlite configure 3.27.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2076,7 +2076,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.26.0, which was
It was created by sqlite $as_me 3.27.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -12232,7 +12232,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.26.0, which was
This file was extended by sqlite $as_me 3.27.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12298,7 +12298,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.26.0
sqlite config.status 3.27.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+8 -5
View File
@@ -82,7 +82,7 @@ typedef struct unicode_cursor unicode_cursor;
struct unicode_tokenizer {
sqlite3_tokenizer base;
int bRemoveDiacritic;
int eRemoveDiacritic;
int nException;
int *aiException;
};
@@ -227,17 +227,20 @@ static int unicodeCreate(
pNew = (unicode_tokenizer *) sqlite3_malloc(sizeof(unicode_tokenizer));
if( pNew==NULL ) return SQLITE_NOMEM;
memset(pNew, 0, sizeof(unicode_tokenizer));
pNew->bRemoveDiacritic = 1;
pNew->eRemoveDiacritic = 1;
for(i=0; rc==SQLITE_OK && i<nArg; i++){
const char *z = azArg[i];
int n = (int)strlen(z);
if( n==19 && memcmp("remove_diacritics=1", z, 19)==0 ){
pNew->bRemoveDiacritic = 1;
pNew->eRemoveDiacritic = 1;
}
else if( n==19 && memcmp("remove_diacritics=0", z, 19)==0 ){
pNew->bRemoveDiacritic = 0;
pNew->eRemoveDiacritic = 0;
}
else if( n==19 && memcmp("remove_diacritics=2", z, 19)==0 ){
pNew->eRemoveDiacritic = 2;
}
else if( n>=11 && memcmp("tokenchars=", z, 11)==0 ){
rc = unicodeAddExceptions(pNew, 1, &z[11], n-11);
@@ -350,7 +353,7 @@ static int unicodeNext(
/* Write the folded case of the last character read to the output */
zEnd = z;
iOut = sqlite3FtsUnicodeFold((int)iCode, p->bRemoveDiacritic);
iOut = sqlite3FtsUnicodeFold((int)iCode, p->eRemoveDiacritic);
if( iOut ){
WRITE_UTF8(zOut, iOut);
}
+40 -22
View File
@@ -159,32 +159,47 @@ int sqlite3FtsUnicodeIsalnum(int c){
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
static int remove_diacritic(int c){
static int remove_diacritic(int c, int bComplex){
unsigned short aDia[] = {
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
62924, 63050, 63082, 63274, 63390,
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
63182, 63242, 63274, 63310, 63368, 63390,
};
char aChar[] = {
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
'e', 'i', 'o', 'u', 'y',
'\0', 'a'|0x00, 'c'|0x00, 'e'|0x00, 'i'|0x00, 'n'|0x00,
'o'|0x00, 'u'|0x00, 'y'|0x00, 'y'|0x00, 'a'|0x00, 'c'|0x00,
'd'|0x00, 'e'|0x00, 'e'|0x00, 'g'|0x00, 'h'|0x00, 'i'|0x00,
'j'|0x00, 'k'|0x00, 'l'|0x00, 'n'|0x00, 'o'|0x00, 'r'|0x00,
's'|0x00, 't'|0x00, 'u'|0x00, 'u'|0x00, 'w'|0x00, 'y'|0x00,
'z'|0x00, 'o'|0x00, 'u'|0x00, 'a'|0x00, 'i'|0x00, 'o'|0x00,
'u'|0x00, 'u'|0x80, 'a'|0x80, 'g'|0x00, 'k'|0x00, 'o'|0x00,
'o'|0x80, 'j'|0x00, 'g'|0x00, 'n'|0x00, 'a'|0x80, 'a'|0x00,
'e'|0x00, 'i'|0x00, 'o'|0x00, 'r'|0x00, 'u'|0x00, 's'|0x00,
't'|0x00, 'h'|0x00, 'a'|0x00, 'e'|0x00, 'o'|0x80, 'o'|0x00,
'o'|0x80, 'y'|0x00, '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a'|0x00, 'b'|0x00,
'c'|0x80, 'd'|0x00, 'd'|0x00, 'e'|0x80, 'e'|0x00, 'e'|0x80,
'f'|0x00, 'g'|0x00, 'h'|0x00, 'h'|0x00, 'i'|0x00, 'i'|0x80,
'k'|0x00, 'l'|0x00, 'l'|0x80, 'l'|0x00, 'm'|0x00, 'n'|0x00,
'o'|0x80, 'p'|0x00, 'r'|0x00, 'r'|0x80, 'r'|0x00, 's'|0x00,
's'|0x80, 't'|0x00, 'u'|0x00, 'u'|0x80, 'v'|0x00, 'w'|0x00,
'w'|0x00, 'x'|0x00, 'y'|0x00, 'z'|0x00, 'h'|0x00, 't'|0x00,
'w'|0x00, 'y'|0x00, 'a'|0x00, 'a'|0x80, 'a'|0x80, 'a'|0x80,
'e'|0x00, 'e'|0x80, 'e'|0x80, 'i'|0x00, 'o'|0x00, 'o'|0x80,
'o'|0x80, 'o'|0x80, 'u'|0x00, 'u'|0x80, 'u'|0x80, 'y'|0x00,
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -201,7 +216,8 @@ static int remove_diacritic(int c){
}
}
assert( key>=aDia[iRes] );
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}
@@ -228,7 +244,7 @@ int sqlite3FtsUnicodeIsdiacritic(int c){
** The results are undefined if the value passed to this function
** is less than zero.
*/
int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
int sqlite3FtsUnicodeFold(int c, int eRemoveDiacritic){
/* Each entry in the following array defines a rule for folding a range
** of codepoints to lower case. The rule applies to a range of nRange
** codepoints starting at codepoint iCode.
@@ -351,7 +367,9 @@ int sqlite3FtsUnicodeFold(int c, int bRemoveDiacritic){
assert( ret>0 );
}
if( bRemoveDiacritic ) ret = remove_diacritic(ret);
if( eRemoveDiacritic ){
ret = remove_diacritic(ret, eRemoveDiacritic==2);
}
}
else if( c>=66560 && c<66600 ){
+24 -16
View File
@@ -9,11 +9,12 @@ proc print_rd {map} {
set nRange 1
set iFirst [lindex $map 0 0]
set cPrev [lindex $map 0 1]
set fPrev [lindex $map 0 2]
foreach m [lrange $map 1 end] {
foreach {i c} $m {}
foreach {i c f} $m {}
if {$cPrev == $c} {
if {$cPrev == $c && $fPrev==$f} {
for {set j [expr $iFirst+$nRange]} {$j<$i} {incr j} {
if {[info exists tl_lookup_table($j)]==0} break
}
@@ -29,13 +30,16 @@ proc print_rd {map} {
lappend lRange [list $iFirst $nRange]
lappend aChar $cPrev
lappend aFlag $fPrev
set iFirst $i
set cPrev $c
set fPrev $f
set nRange 1
}
lappend lRange [list $iFirst $nRange]
lappend aChar $cPrev
lappend aFlag $fPrev
puts "/*"
puts "** If the argument is a codepoint corresponding to a lowercase letter"
@@ -45,7 +49,7 @@ proc print_rd {map} {
puts "** E\"). The resuls of passing a codepoint that corresponds to an"
puts "** uppercase letter are undefined."
puts "*/"
puts "static int ${::remove_diacritic}(int c)\{"
puts "static int ${::remove_diacritic}(int c, int bComplex)\{"
puts " unsigned short aDia\[\] = \{"
puts -nonewline " 0, "
set i 1
@@ -60,13 +64,17 @@ proc print_rd {map} {
puts ""
puts " \};"
puts " char aChar\[\] = \{"
puts -nonewline " '\\0', "
puts -nonewline " '\\0', "
set i 1
foreach c $aChar {
set str "'$c', "
if {$c == ""} { set str "'\\0', " }
foreach c $aChar f $aFlag {
if { $f } {
set str "'$c'|0x80, "
} else {
set str "'$c'|0x00, "
}
if {$c == ""} { set str "'\\0', " }
if {($i % 12)==0} {puts "" ; puts -nonewline " " }
if {($i % 6)==0} {puts "" ; puts -nonewline " " }
incr i
puts -nonewline "$str"
}
@@ -87,7 +95,8 @@ proc print_rd {map} {
}
}
assert( key>=aDia[iRes] );
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);}
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);}
puts "\}"
}
@@ -95,7 +104,8 @@ proc print_isdiacritic {zFunc map} {
set lCode [list]
foreach m $map {
foreach {code char} $m {}
foreach {code char flag} $m {}
if {$flag} continue
if {$code && $char == ""} { lappend lCode $code }
}
set lCode [lsort -integer $lCode]
@@ -472,7 +482,7 @@ proc print_fold {zFunc} {
puts "** The results are undefined if the value passed to this function"
puts "** is less than zero."
puts "*/"
puts "int ${zFunc}\(int c, int bRemoveDiacritic)\{"
puts "int ${zFunc}\(int c, int eRemoveDiacritic)\{"
set liOff [tl_generate_ioff_table $lRecord]
tl_print_table_header
@@ -516,7 +526,9 @@ proc print_fold {zFunc} {
assert( ret>0 );
}
if( bRemoveDiacritic ) ret = ${::remove_diacritic}(ret);
if( eRemoveDiacritic ){
ret = ${::remove_diacritic}(ret, eRemoveDiacritic==2);
}
}
}]
@@ -605,10 +617,6 @@ proc print_categories {lMap} {
set nCat [expr [llength [array names C]] + 1]
puts [code {
int sqlite3Fts5UnicodeNCat(void) {
return $nCat;
}
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
aArray[0] = 1;
switch( zCat[0] ){
+27 -4
View File
@@ -7,12 +7,24 @@
# character that it should be replaced with, or an empty string if the
# codepoint should simply be removed from the input. Examples:
#
# { 224 a } (replace codepoint 224 to "a")
# { 769 "" } (remove codepoint 769 from input)
# { 224 a 0 } (replace codepoint 224 to "a")
# { 769 "" 0 } (remove codepoint 769 from input)
#
# Mappings are only returned for non-upper case codepoints. It is assumed
# that the input has already been folded to lower case.
#
# The third value in the list is always either 0 or 1. 0 if the
# UnicodeData.txt file maps the codepoint to a single ASCII character and
# a diacritic, or 1 if the mapping is indirect. For example, consider the
# two entries:
#
# 1ECD;LATIN SMALL LETTER O WITH DOT BELOW;Ll;0;L;006F 0323;;;;N;;;1ECC;;1ECC
# 1ED9;LATIN SMALL LETTER O WITH CIRCUMFLEX AND DOT BELOW;Ll;0;L;1ECD 0302;;;;N;;;1ED8;;1ED8
#
# The first codepoint is a direct mapping (as 006F is ASCII and 0323 is a
# diacritic). The second is an indirect mapping, as it maps to the
# first codepoint plus 0302 (a diacritic).
#
proc rd_load_unicodedata_text {zName} {
global tl_lookup_table
@@ -53,18 +65,29 @@ proc rd_load_unicodedata_text {zName} {
set iAscii [expr "0x[lindex $character_decomposition_mapping 0]"]
set iDia [expr "0x[lindex $character_decomposition_mapping 1]"]
# Filter out upper-case characters, as they will be mapped to their
# lower-case equivalents before this data is used.
if {[info exists tl_lookup_table($iCode)]} continue
# Check if this is an indirect mapping. If so, set bIndirect to true
# and change $iAscii to the indirectly mappped ASCII character.
set bIndirect 0
if {[info exists dia($iDia)] && [info exists mapping($iAscii)]} {
set iAscii $mapping($iAscii)
set bIndirect 1
}
if { ($iAscii >= 97 && $iAscii <= 122)
|| ($iAscii >= 65 && $iAscii <= 90)
} {
lappend lRet [list $iCode [string tolower [format %c $iAscii]]]
lappend lRet [list $iCode [string tolower [format %c $iAscii]] $bIndirect]
set mapping($iCode) $iAscii
set dia($iDia) 1
}
}
foreach d [array names dia] {
lappend lRet [list $d ""]
lappend lRet [list $d "" 0]
}
set lRet [lsort -integer -index 0 $lRet]
+15 -5
View File
@@ -234,13 +234,18 @@ struct Unicode61Tokenizer {
unsigned char aTokenChar[128]; /* ASCII range token characters */
char *aFold; /* Buffer to fold text into */
int nFold; /* Size of aFold[] in bytes */
int bRemoveDiacritic; /* True if remove_diacritics=1 is set */
int eRemoveDiacritic; /* True if remove_diacritics=1 is set */
int nException;
int *aiException;
unsigned char aCategory[32]; /* True for token char categories */
};
/* Values for eRemoveDiacritic (must match internals of fts5_unicode2.c) */
#define FTS5_REMOVE_DIACRITICS_NONE 0
#define FTS5_REMOVE_DIACRITICS_SIMPLE 1
#define FTS5_REMOVE_DIACRITICS_COMPLEX 2
static int fts5UnicodeAddExceptions(
Unicode61Tokenizer *p, /* Tokenizer object */
const char *z, /* Characters to treat as exceptions */
@@ -361,7 +366,7 @@ static int fts5UnicodeCreate(
int i;
memset(p, 0, sizeof(Unicode61Tokenizer));
p->bRemoveDiacritic = 1;
p->eRemoveDiacritic = FTS5_REMOVE_DIACRITICS_SIMPLE;
p->nFold = 64;
p->aFold = sqlite3_malloc(p->nFold * sizeof(char));
if( p->aFold==0 ){
@@ -382,10 +387,15 @@ static int fts5UnicodeCreate(
for(i=0; rc==SQLITE_OK && i<nArg; i+=2){
const char *zArg = azArg[i+1];
if( 0==sqlite3_stricmp(azArg[i], "remove_diacritics") ){
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1] ){
if( (zArg[0]!='0' && zArg[0]!='1' && zArg[0]!='2') || zArg[1] ){
rc = SQLITE_ERROR;
}else{
p->eRemoveDiacritic = (zArg[0] - '0');
assert( p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_NONE
|| p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_SIMPLE
|| p->eRemoveDiacritic==FTS5_REMOVE_DIACRITICS_COMPLEX
);
}
p->bRemoveDiacritic = (zArg[0]=='1');
}else
if( 0==sqlite3_stricmp(azArg[i], "tokenchars") ){
rc = fts5UnicodeAddExceptions(p, zArg, 1);
@@ -499,7 +509,7 @@ static int fts5UnicodeTokenize(
READ_UTF8(zCsr, zTerm, iCode);
if( fts5UnicodeIsAlnum(p,iCode)||sqlite3Fts5UnicodeIsdiacritic(iCode) ){
non_ascii_tokenchar:
iCode = sqlite3Fts5UnicodeFold(iCode, p->bRemoveDiacritic);
iCode = sqlite3Fts5UnicodeFold(iCode, p->eRemoveDiacritic);
if( iCode ) WRITE_UTF8(zOut, iCode);
}else{
break;
+41 -31
View File
@@ -28,32 +28,47 @@
** E"). The resuls of passing a codepoint that corresponds to an
** uppercase letter are undefined.
*/
static int fts5_remove_diacritic(int c){
static int fts5_remove_diacritic(int c, int bComplex){
unsigned short aDia[] = {
0, 1797, 1848, 1859, 1891, 1928, 1940, 1995,
2024, 2040, 2060, 2110, 2168, 2206, 2264, 2286,
2344, 2383, 2472, 2488, 2516, 2596, 2668, 2732,
2782, 2842, 2894, 2954, 2984, 3000, 3028, 3336,
3456, 3696, 3712, 3728, 3744, 3896, 3912, 3928,
3968, 4008, 4040, 4106, 4138, 4170, 4202, 4234,
4266, 4296, 4312, 4344, 4408, 4424, 4472, 4504,
6148, 6198, 6264, 6280, 6360, 6429, 6505, 6529,
61448, 61468, 61534, 61592, 61642, 61688, 61704, 61726,
61784, 61800, 61836, 61880, 61914, 61948, 61998, 62122,
62154, 62200, 62218, 62302, 62364, 62442, 62478, 62536,
62554, 62584, 62604, 62640, 62648, 62656, 62664, 62730,
62924, 63050, 63082, 63274, 63390,
3456, 3696, 3712, 3728, 3744, 3766, 3832, 3896,
3912, 3928, 3944, 3968, 4008, 4040, 4056, 4106,
4138, 4170, 4202, 4234, 4266, 4296, 4312, 4344,
4408, 4424, 4442, 4472, 4488, 4504, 6148, 6198,
6264, 6280, 6360, 6429, 6505, 6529, 61448, 61468,
61512, 61534, 61592, 61610, 61642, 61672, 61688, 61704,
61726, 61784, 61800, 61816, 61836, 61880, 61896, 61914,
61948, 61998, 62062, 62122, 62154, 62184, 62200, 62218,
62252, 62302, 62364, 62410, 62442, 62478, 62536, 62554,
62584, 62604, 62640, 62648, 62656, 62664, 62730, 62766,
62830, 62890, 62924, 62974, 63032, 63050, 63082, 63118,
63182, 63242, 63274, 63310, 63368, 63390,
};
char aChar[] = {
'\0', 'a', 'c', 'e', 'i', 'n', 'o', 'u', 'y', 'y', 'a', 'c',
'd', 'e', 'e', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'o', 'r',
's', 't', 'u', 'u', 'w', 'y', 'z', 'o', 'u', 'a', 'i', 'o',
'u', 'g', 'k', 'o', 'j', 'g', 'n', 'a', 'e', 'i', 'o', 'r',
'u', 's', 't', 'h', 'a', 'e', 'o', 'y', '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a', 'b', 'd', 'd', 'e', 'f', 'g', 'h',
'h', 'i', 'k', 'l', 'l', 'm', 'n', 'p', 'r', 'r', 's', 't',
'u', 'v', 'w', 'w', 'x', 'y', 'z', 'h', 't', 'w', 'y', 'a',
'e', 'i', 'o', 'u', 'y',
'\0', 'a'|0x00, 'c'|0x00, 'e'|0x00, 'i'|0x00, 'n'|0x00,
'o'|0x00, 'u'|0x00, 'y'|0x00, 'y'|0x00, 'a'|0x00, 'c'|0x00,
'd'|0x00, 'e'|0x00, 'e'|0x00, 'g'|0x00, 'h'|0x00, 'i'|0x00,
'j'|0x00, 'k'|0x00, 'l'|0x00, 'n'|0x00, 'o'|0x00, 'r'|0x00,
's'|0x00, 't'|0x00, 'u'|0x00, 'u'|0x00, 'w'|0x00, 'y'|0x00,
'z'|0x00, 'o'|0x00, 'u'|0x00, 'a'|0x00, 'i'|0x00, 'o'|0x00,
'u'|0x00, 'u'|0x80, 'a'|0x80, 'g'|0x00, 'k'|0x00, 'o'|0x00,
'o'|0x80, 'j'|0x00, 'g'|0x00, 'n'|0x00, 'a'|0x80, 'a'|0x00,
'e'|0x00, 'i'|0x00, 'o'|0x00, 'r'|0x00, 'u'|0x00, 's'|0x00,
't'|0x00, 'h'|0x00, 'a'|0x00, 'e'|0x00, 'o'|0x80, 'o'|0x00,
'o'|0x80, 'y'|0x00, '\0', '\0', '\0', '\0',
'\0', '\0', '\0', '\0', 'a'|0x00, 'b'|0x00,
'c'|0x80, 'd'|0x00, 'd'|0x00, 'e'|0x80, 'e'|0x00, 'e'|0x80,
'f'|0x00, 'g'|0x00, 'h'|0x00, 'h'|0x00, 'i'|0x00, 'i'|0x80,
'k'|0x00, 'l'|0x00, 'l'|0x80, 'l'|0x00, 'm'|0x00, 'n'|0x00,
'o'|0x80, 'p'|0x00, 'r'|0x00, 'r'|0x80, 'r'|0x00, 's'|0x00,
's'|0x80, 't'|0x00, 'u'|0x00, 'u'|0x80, 'v'|0x00, 'w'|0x00,
'w'|0x00, 'x'|0x00, 'y'|0x00, 'z'|0x00, 'h'|0x00, 't'|0x00,
'w'|0x00, 'y'|0x00, 'a'|0x00, 'a'|0x80, 'a'|0x80, 'a'|0x80,
'e'|0x00, 'e'|0x80, 'e'|0x80, 'i'|0x00, 'o'|0x00, 'o'|0x80,
'o'|0x80, 'o'|0x80, 'u'|0x00, 'u'|0x80, 'u'|0x80, 'y'|0x00,
};
unsigned int key = (((unsigned int)c)<<3) | 0x00000007;
@@ -70,7 +85,8 @@ static int fts5_remove_diacritic(int c){
}
}
assert( key>=aDia[iRes] );
return ((c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : (int)aChar[iRes]);
if( bComplex==0 && (aChar[iRes] & 0x80) ) return c;
return (c > (aDia[iRes]>>3) + (aDia[iRes]&0x07)) ? c : ((int)aChar[iRes] & 0x7F);
}
@@ -97,7 +113,7 @@ int sqlite3Fts5UnicodeIsdiacritic(int c){
** The results are undefined if the value passed to this function
** is less than zero.
*/
int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
int sqlite3Fts5UnicodeFold(int c, int eRemoveDiacritic){
/* Each entry in the following array defines a rule for folding a range
** of codepoints to lower case. The rule applies to a range of nRange
** codepoints starting at codepoint iCode.
@@ -220,7 +236,9 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
assert( ret>0 );
}
if( bRemoveDiacritic ) ret = fts5_remove_diacritic(ret);
if( eRemoveDiacritic ){
ret = fts5_remove_diacritic(ret, eRemoveDiacritic==2);
}
}
else if( c>=66560 && c<66600 ){
@@ -230,13 +248,6 @@ int sqlite3Fts5UnicodeFold(int c, int bRemoveDiacritic){
return ret;
}
#if 0
int sqlite3Fts5UnicodeNCat(void) {
return 32;
}
#endif
int sqlite3Fts5UnicodeCatParse(const char *zCat, u8 *aArray){
aArray[0] = 1;
switch( zCat[0] ){
@@ -756,9 +767,8 @@ void sqlite3Fts5UnicodeAscii(u8 *aArray, u8 *aAscii){
int bToken = aArray[ aFts5UnicodeData[iTbl] & 0x1F ];
int n = (aFts5UnicodeData[iTbl] >> 5) + i;
for(; i<128 && i<n; i++){
aAscii[i] = (u8)bToken;
aAscii[i] = bToken;
}
iTbl++;
}
}
+1 -1
View File
@@ -189,7 +189,7 @@ do_catchsql_test 6.2 {
} {1 {error in tokenizer constructor}}
do_catchsql_test 6.3 {
CREATE VIRTUAL TABLE a3 USING fts5(
x, y, tokenize = 'unicode61 remove_diacritics 2'
x, y, tokenize = 'unicode61 remove_diacritics 3'
);
} {1 {error in tokenizer constructor}}
do_catchsql_test 6.4 {
+65
View File
@@ -0,0 +1,65 @@
# 2014 June 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5umlaut
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
CREATE VIRTUAL TABLE t2 USING fts5(
x,
tokenize="unicode61 remove_diacritics 2"
);
}
foreach {tn q res1 res2} {
1 "Hà Nội" 0 1
2 "Hà Noi" 1 1
3 "Ha Noi" 1 1
4 "Ha N\u1ed9i" 0 1
5 "Ha N\u006fi" 1 1
6 "Ha N\u006f\u0302i" 1 1
7 "Ha N\u006f\u0323\u0302i" 1 1
} {
do_execsql_test 1.$tn.1 {
DELETE FROM t1;
INSERT INTO t1(rowid, x) VALUES (1, 'Ha Noi');
SELECT count(*) FROM t1($q)
} $res1
do_execsql_test 1.$tn.2 {
DELETE FROM t1;
INSERT INTO t1(rowid, x) VALUES (1, $q);
SELECT count(*) FROM t1('Ha Noi')
} $res1
do_execsql_test 1.$tn.2 {
DELETE FROM t2;
INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
SELECT count(*) FROM t2($q)
} $res2
do_execsql_test 1.$tn.2 {
DELETE FROM t2;
INSERT INTO t2(rowid, x) VALUES (1, $q);
SELECT count(*) FROM t2('Ha Noi')
} $res2
}
finish_test
+17 -5
View File
@@ -36,24 +36,26 @@ foreach x [an_load_unicodedata_text $UD] {
}
foreach {y} [rd_load_unicodedata_text $UD] {
foreach {code ascii} $y {}
foreach {code ascii f} $y {}
if {$ascii==""} {
set int 0
} else {
binary scan $ascii c int
}
set aDiacritic($code) $int
set aDiacritic($code,$f) $int
if {$f==0} { set aDiacritic($code,1) $int }
}
proc tcl_fold {i {bRemoveDiacritic 0}} {
global tl_lookup_table
global aDiacritic
set f [expr $bRemoveDiacritic==2]
if {[info exists tl_lookup_table($i)]} {
set i $tl_lookup_table($i)
}
if {$bRemoveDiacritic && [info exists aDiacritic($i)]} {
set i $aDiacritic($i)
if {$bRemoveDiacritic && [info exists aDiacritic($i,$f)]} {
set i $aDiacritic($i,$f)
}
expr $i
}
@@ -85,7 +87,7 @@ do_execsql_test 1.1 {
SELECT count(*), min(i) FROM ii WHERE fts5_fold(i)!=CAST(tcl_fold(i) AS int);
} {0 {}}
do_execsql_test 1.2 {
do_execsql_test 1.2.1 {
WITH ii(i) AS (
SELECT -1
UNION ALL
@@ -95,6 +97,16 @@ do_execsql_test 1.2 {
WHERE fts5_fold(i,1)!=CAST(tcl_fold(i,1) AS int);
} {0 {}}
do_execsql_test 1.2.2 {
WITH ii(i) AS (
SELECT -1
UNION ALL
SELECT i+1 FROM ii WHERE i<100000
)
SELECT count(*), min(i) FROM ii
WHERE fts5_fold(i,2)!=CAST(tcl_fold(i,2) AS int);
} {0 {}}
do_execsql_test 1.3 {
WITH ii(i) AS (
SELECT -1
+7 -6
View File
@@ -86,12 +86,13 @@ proc step_rbu_legacy {target rbu} {
set rc
}
proc do_rbu_vacuum_test {tn step} {
forcedelete state.db
uplevel [list do_test $tn.1 {
if {$step==0} { sqlite3rbu_vacuum rbu test.db state.db }
proc do_rbu_vacuum_test {tn step {statedb state.db}} {
forcedelete $statedb
if {$statedb=="" && $step==1} breakpoint
uplevel [list do_test $tn.1 [string map [list %state% $statedb] {
if {$step==0} { sqlite3rbu_vacuum rbu test.db {%state%}}
while 1 {
if {$step==1} { sqlite3rbu_vacuum rbu test.db state.db }
if {$step==1} { sqlite3rbu_vacuum rbu test.db {%state%}}
set state [rbu state]
check_prestep_state test.db $state
set rc [rbu step]
@@ -100,7 +101,7 @@ proc do_rbu_vacuum_test {tn step} {
if {$step==1} { rbu close }
}
rbu close
} {SQLITE_DONE}]
}] {SQLITE_DONE}]
uplevel [list do_execsql_test $tn.2 {
PRAGMA integrity_check
+18 -9
View File
@@ -16,8 +16,11 @@
source [file join [file dirname [info script]] rbu_common.tcl]
foreach step {0 1} {
set ::testprefix rbuvacuum2-$step
foreach {step} {0 1} {
foreach {ttt state} {
s state.db t test.db-vacuum n {}
} {
set ::testprefix rbuvacuum2-$step$ttt
#-------------------------------------------------------------------------
# Test that a database that contains fts3 tables can be vacuumed.
@@ -29,7 +32,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
do_rbu_vacuum_test 1.2 $step
do_rbu_vacuum_test 1.2 $step $state
do_execsql_test 1.3 {
SELECT * FROM t1;
@@ -46,7 +49,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('a b c', 'x y z');
}
do_rbu_vacuum_test 1.6 $step
do_rbu_vacuum_test 1.6 $step $state
do_execsql_test 1.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
@@ -67,7 +70,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('fix this issue', 'at some point');
}
do_rbu_vacuum_test 2.2 $step
do_rbu_vacuum_test 2.2 $step $state
do_execsql_test 2.3 {
SELECT * FROM t1;
@@ -84,7 +87,7 @@ foreach step {0 1} {
INSERT INTO t1 VALUES('a b c', 'x y z');
}
do_rbu_vacuum_test 2.6 $step
do_rbu_vacuum_test 2.6 $step $state
do_execsql_test 2.7 {
INSERT INTO t1(t1) VALUES('integrity-check');
SELECT * FROM t1;
@@ -107,7 +110,7 @@ foreach step {0 1} {
INSERT INTO rt VALUES(3, 55, 65);
}
do_rbu_vacuum_test 3.2 $step
do_rbu_vacuum_test 3.2 $step $state
do_execsql_test 3.3 {
SELECT * FROM rt;
@@ -120,7 +123,7 @@ foreach step {0 1} {
SELECT rowid FROM rt WHERE x2>59 AND x1 < 59
} {2 3}
do_rbu_vacuum_test 3.5 $step
do_rbu_vacuum_test 3.5 $step $state
do_execsql_test 3.6.1 {
SELECT rowid FROM rt WHERE x2>51 AND x1 < 51
@@ -147,7 +150,7 @@ foreach step {0 1} {
trigger tr1 t1 0 {CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT 1; END}
}
do_rbu_vacuum_test 4.3 $step
do_rbu_vacuum_test 4.3 $step $state
do_execsql_test 4.4 {
SELECT * FROM sqlite_master;
} {
@@ -157,6 +160,7 @@ foreach step {0 1} {
}
}
}
}
#-------------------------------------------------------------------------
# Test that passing a NULL value as the second argument to
@@ -231,4 +235,9 @@ do_test 6.3 {
execsql { PRAGMA integrity_check }
} {ok}
do_test 6.4 {
sqlite3rbu_vacuum rbu test.db test.db-vactmp
list [catch { rbu close } msg] $msg
} {1 SQLITE_MISUSE}
finish_test
+7 -1
View File
@@ -2477,7 +2477,7 @@ static void rbuOpenDatabase(sqlite3rbu *p, int *pbRetry){
if( *zExtra=='\0' ) zExtra = 0;
}
zTarget = sqlite3_mprintf("file:%s-vacuum?rbu_memory=1%s%s",
zTarget = sqlite3_mprintf("file:%s-vactmp?rbu_memory=1%s%s",
sqlite3_db_filename(p->dbRbu, "main"),
(zExtra==0 ? "" : "&"), (zExtra==0 ? "" : zExtra)
);
@@ -3743,6 +3743,12 @@ sqlite3rbu *sqlite3rbu_vacuum(
const char *zState
){
if( zTarget==0 ){ return rbuMisuseError(); }
if( zState ){
int n = strlen(zState);
if( n>=7 && 0==memcmp("-vactmp", &zState[n-7], 7) ){
return rbuMisuseError();
}
}
/* TODO: Check that both arguments are non-NULL */
return openRbuHandle(0, zTarget, zState);
}
+5 -1
View File
@@ -333,7 +333,11 @@ SQLITE_API sqlite3rbu *sqlite3rbu_open(
** name of the state database is "<database>-vacuum", where <database>
** is the name of the target database file. In this case, on UNIX, if the
** state database is not already present in the file-system, it is created
** with the same permissions as the target db is made.
** with the same permissions as the target db is made.
**
** With an RBU vacuum, it is an SQLITE_MISUSE error if the name of the
** state database ends with "-vactmp". This name is reserved for internal
** use.
**
** This function does not delete the state database after an RBU vacuum
** is completed, even if it created it. However, if the call to
+1
View File
@@ -273,6 +273,7 @@ static int SQLITE_TCLAPI test_sqlite3rbu_vacuum(
zCmd = Tcl_GetString(objv[1]);
zTarget = Tcl_GetString(objv[2]);
if( objc==4 ) zStateDb = Tcl_GetString(objv[3]);
if( zStateDb && zStateDb[0]=='\0' ) zStateDb = 0;
pRbu = sqlite3rbu_vacuum(zTarget, zStateDb);
Tcl_CreateObjCommand(interp, zCmd, test_sqlite3rbu_cmd, (ClientData)pRbu, 0);
+7
View File
@@ -976,6 +976,9 @@ $(TEST_EXTENSION): $(TOP)/src/test_loadext.c
extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
./testfixture$(EXE) $(TOP)/test/loadext.test
dbtotxt$(EXE): $(TOP)/tool/dbtotxt.c
$(TCC) -o dbtotxt$(EXE) $(TOP)/tool/dbtotxt.c
showdb$(EXE): $(TOP)/tool/showdb.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb$(EXE) \
$(TOP)/tool/showdb.c sqlite3.o $(THREADLIB)
@@ -995,6 +998,10 @@ showwal$(EXE): $(TOP)/tool/showwal.c sqlite3.o
showshm$(EXE): $(TOP)/tool/showshm.c
$(TCC) -o showshm$(EXE) $(TOP)/tool/showshm.c
index_usage$(EXE): $(TOP)/tool/index_usage.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_DEPRECATED -o index_usage$(EXE) \
$(TOP)/tool/index_usage.c sqlite3.o $(THREADLIB)
changeset$(EXE): $(TOP)/ext/session/changeset.c sqlite3.o
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o changeset$(EXE) \
$(TOP)/ext/session/changeset.c sqlite3.o $(THREADLIB)
+69 -65
View File
@@ -1,12 +1,12 @@
C Version\s3.26.0
D 2018-12-01T12:34:55.966
C Merge\sthe\sdbtotxt\senhancement\sfrom\strunk.
D 2018-12-13T15:52:31.619
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F Makefile.in a050c8670ea0d7b37b2192306cbb50d392acd9902b84e9b56f3444d006f97a6c
F Makefile.in 2f1b61ac62689ca4e9cbff9fdb359578ea37ddd9252355ec0b7b9700ad56fe90
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 0d6831ff7951b302e888d86d4c469e2ec3c22f59eba4118b8c38d5a51d9e2d4f
F Makefile.msc 2ef13d6845b899eaaa6122c69b74175656a97e26666567af795f4cfe41b7a673
F README.md 377233394b905d3b2e2b33741289e093bc93f2e7adbe00923b2c5958c9a9edee
F VERSION 654da1d4053fb09ffc33a3910e6d427182a7dcdc67e934fa83de2849ac83fccb
F VERSION 453e2f4529ca208196d5567db28d549d7151f79efd33f6e6cfe6e613e583a0be
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
F art/sqlite370.eps aa97a671332b432a54e1d74ff5e8775be34200c2
F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
@@ -14,7 +14,7 @@ F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
F autoconf/Makefile.am e14b629addaa1ce372b72043f28f40de2e32b7e211b6e0fc18dbb87989197e40
F autoconf/Makefile.fallback 22fe523eb36dfce31e0f6349f782eb084e86a5620b2b0b4f84a2d6133f53f5ac
F autoconf/Makefile.msc 9e73d9abaadb7a4951ddd0e947c5c791770f23bb1e04bfa50b43c01bee0575f2
F autoconf/Makefile.msc ee8ab2b6b5d712f68acc4c186e3fad7b831b87a2b118e0a123043ea8a2c8b016
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
F autoconf/configure.ac 308de24343e76ecfbe9a67f8fcd4c5216b790d230c5d9ce10210b7d5965d6192
@@ -33,7 +33,7 @@ F autoconf/tea/win/rules.vc c511f222b80064096b705dbeb97060ee1d6b6d63
F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
F config.h.in 6376abec766e9a0785178b1823b5a587e9f1ccbc
F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
F configure 5811ffcd4866902d1706dcf8e0527f89165ec52859659942c9649bb1d3e4cc7b x
F configure e2b4021dcb8ee6f9a91e7f4011316957868e8065019ac994f68e27363120c272 x
F configure.ac 3552d3aecade98a9d4b64bceb48ffb7726cbc85902efde956812942f060fbd0a
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
F doc/F2FS.txt c1d4a0ae9711cfe0e1d8b019d154f1c29e0d3abfe820787ba1e9ed7691160fcd
@@ -96,8 +96,8 @@ F ext/fts3/fts3_tokenize_vtab.c a47c2a33de6db00816704315ac0a9afdfa1c71fa5b99f791
F ext/fts3/fts3_tokenizer.c a22bf311a71f3efa9d7012d8cc48fc9b0f3dace7
F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 525a3bd9a7564603c5c061b7de55403a565307758a94600e8a2f6b00d1c40d9d
F ext/fts3/fts3_unicode2.c cc04fc672bfd42b1e650398cb0bf71f64f9aae032cfe75bbcfe75b9cf966029c
F ext/fts3/fts3_unicode.c b1902e9ad47a6569fbb8ecb5ce52f20fe59b590d5c5e3bbdd56b10b03bdf632b
F ext/fts3/fts3_unicode2.c 90e65f4291c8ecceee284ecc8d5d48734e95ecd4b008e06f36f14e77f93d655f
F ext/fts3/fts3_write.c a85bc4885fde7f1b44c9de013b62f7cd3332dc59e208053d878729b1d04745bc
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
@@ -105,8 +105,8 @@ F ext/fts3/tool/fts3cov.sh c331d006359456cf6f8f953e37f2b9c7d568f3863f00bb5f7eb87
F ext/fts3/tool/fts3view.c 202801a2056995b763864d60c2dee744d46f1677
F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
F ext/fts3/unicode/mkunicode.tcl 0069320b64db6ee269c5e95f1f150d070fbf0a863fc7b3549d7e52bd068fb118
F ext/fts3/unicode/parseunicode.tcl 024ae0bdd96309d7b8fc479148191e9b3001dc74017a3f65f9a27de3b3ff968b
F ext/fts3/unicode/mkunicode.tcl 2ea30d8122ccf1e33142c9cc8913d8cad9eb6668db359a228f10aeb37e2ab863
F ext/fts3/unicode/parseunicode.tcl a981bd6466d12dd17967515801c3ff23f74a281be1a03cf1e6f52a6959fc77eb
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
F ext/fts5/fts5.h 5edc74ca603d71284d475886e6e91b5c5cf2e8e93e9ba3a36ba2f2440ee97948
F ext/fts5/fts5Int.h 39f12034b598df4e0f59bbe6cf03af03a905a534b04f182d155641a04e1eb797
@@ -121,8 +121,8 @@ F ext/fts5/fts5_storage.c 4bec8a1b3905978b22a67bca5f4a3cfdb94af234cf51efb36f4f2d
F ext/fts5/fts5_tcl.c 39bcbae507f594aad778172fa914cad0f585bf92fd3b078c686e249282db0d95
F ext/fts5/fts5_test_mi.c 65864ba1e5c34a61d409c4c587e0bbe0466eb4f8f478d85dc42a92caad1338e6
F ext/fts5/fts5_test_tok.c 80de1a4b1a3caa216c3be8862440f0117a8357dd9b7cfc5a2a2ce11fe6eb64ae
F ext/fts5/fts5_tokenize.c ebd13d034f3dc7c841e1c32c364a4fca5cc2e05a0b91682a93fa1e6defcd4292
F ext/fts5/fts5_unicode2.c 543cf0987c27ad59e5a7a6222480b917b5431009b7b139027c9581a63e39e37e
F ext/fts5/fts5_tokenize.c ca2b6a033794945ac505241a86b0aa978709c23aa2e6121984d3e3ede96003c8
F ext/fts5/fts5_unicode2.c 26519f47d567c5a9b08c376edd38f1b8a773b45ff29f1ffd81d9edfe20f96e18
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
F ext/fts5/fts5_vocab.c fbe38044889b2d2d99babeeef239c620fb0332bb928a84506ac748d81500b354
F ext/fts5/fts5parse.y eb526940f892ade5693f22ffd6c4f2702543a9059942772526eac1fde256bb05
@@ -206,10 +206,11 @@ F ext/fts5/test/fts5synonym.test 1651815b8008de170e8e600dcacc17521d765482ea8f074
F ext/fts5/test/fts5synonym2.test b54cce5c34ec08ed616f646635538ae82e34a0e28f947ec60b6fadbc4b3fb17a
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/fts5tokenizer.test ac3c9112b263a639fb0508ae73a3ee886bf4866d2153771a8e8a20c721305a43
F ext/fts5/test/fts5umlaut.test a42fe2fe6387c40c49ab27ccbd070e1ae38e07f38d05926482cc0bccac9ad602
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/fts5unicode3.test 9cbc82e2b02e2e3b7504103580c90f095e07fe8230b1951a9ed7558717b5feb7
F ext/fts5/test/fts5unicode4.test 6463301d669f963c83988017aa354108be0b947d325aef58d3abddf27147b687
F ext/fts5/test/fts5unindexed.test 9021af86a0fb9fc616f7a69a996db0116e7936d0db63892db6bafabbec21af4d
F ext/fts5/test/fts5update.test 0737876e20e97a6a6abf45de19fc99315727bcee6a83fadcada1cc080b9aa8f0
@@ -329,7 +330,7 @@ F ext/rbu/rbu9.test 0e4d985e25620d61920597e8ea69c871c9e8c1f5a0be2ae9fa70bb641d74
F ext/rbu/rbuA.test b34a90cb495682c25b5fc03a9d5e7a4fc99541c29256f25e2e2a4f6542b4f5b3
F ext/rbu/rbuB.test 52b07158824c6927b7e25554ace92a695cdebfc296ae3d308ac386984aded9bc
F ext/rbu/rbuC.test 80f1cc2fb74f44b1128fd0ed8eedab3a76fefeb72a947860e2869ef76fc8dc6b
F ext/rbu/rbu_common.tcl acfb7fbbaf8d46a9f6f6a5ec795616c84d705e1565d918afe43f0ff53ea0efa5
F ext/rbu/rbu_common.tcl 4b3d033b3e3844292ae3a1aefc0e524e64b0db5a0e4310657919e4504ac3073f
F ext/rbu/rbucollate.test cac528a9a46318cba42e61258bb42660bbbf4fdb9a8c863de5a54ad0c658d197
F ext/rbu/rbucrash.test 000981a1fe8a6e4d9a684232f6a129e66a3ef595f5ed74655e2f9c68ffa613b4
F ext/rbu/rbucrash2.test efa143cc94228eb0266d3f1abfbee60a5838a84cef7cc3fcb8c145b74d96fd41
@@ -347,10 +348,10 @@ F ext/rbu/rbusave.test f4190a1a86fccf84f723af5c93813365ae33feda35845ba107b59683d
F ext/rbu/rbusplit.test b37e7b40b38760881dc9c854bd40b4744c6b6cd74990754eca3bda0f407051e8
F ext/rbu/rbutemplimit.test 7f408f49b90fa0a720d7599f3aec74a3c85e6cd78e56fdf726ce00af9147a341
F ext/rbu/rbuvacuum.test 55e101e90168c2b31df6c9638fe73dc7f7cc666b6142266d1563697d79f73534
F ext/rbu/rbuvacuum2.test 0a7669bbabdaeed915f02f59f33fe20e13d4932ba2086fe00a82064d9424c80b
F ext/rbu/sqlite3rbu.c 71f8c09948d09ec9c5a8dbe7127e8ef61ef0853e698b2650be2485ac7b9c75c8
F ext/rbu/sqlite3rbu.h b42bcd4d8357268c6c39ab2a60b29c091e89328fa8cc49c8fac5ab8d007e79b2
F ext/rbu/test_rbu.c baa23eb28457580673d2175e5f0c29ced0cd320ee819b13ad362398c53b96e90
F ext/rbu/rbuvacuum2.test b8e5b51dc8b2c0153373d024c0936be3f66f9234acbd6d0baab0869d56b14e6b
F ext/rbu/sqlite3rbu.c f722ed4177c9fb73f2f6f116240687ac7603735fa95ea63bff71827929d4c192
F ext/rbu/sqlite3rbu.h 1dc88ab7bd32d0f15890ea08d23476c4198d3da3056985403991f8c9cd389812
F ext/rbu/test_rbu.c 03f6f177096a5f822d68d8e4069ad8907fe572c62ff2d19b141f59742821828a
F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
F ext/repair/checkfreelist.c 0dbae18c1b552f58d64f8969e4fb1e7f11930c60a8c2a9a8d50b7f15bdfd54bd
F ext/repair/checkindex.c 7d28c01a2e012ac64257d230fc452b2cafb78311a91a343633d01d95220f66f3
@@ -428,7 +429,7 @@ F ext/userauth/userauth.c f81aa5a3ecacf406f170c62a144405858f6f6de51dbdc0920134e6
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
F main.mk eeaa279fa6acdcfa6555058548075569a06f891fd67f5901b1e7700d18052fda
F main.mk cca1ecdd5dfe4579ded84e5abdd38e1866bbb8b8cf58d1a24496e9b1b65580d7
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -440,37 +441,37 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c f886160da189e4e99093cd5a2aca625652cc9b027d5100b87f81c175d1056387
F src/alter.c 87c9057f5eaa012da23b8e50848eee5e99088c3c478555f9ed255485b61ab5aa
F src/analyze.c 3dc6b98cf007b005af89df165c966baaa48e8124f38c87b4d2b276fe7f0b9eb9
F src/attach.c 92b51739a885da8bd84bc9a05485f1e48148bce5c15432f059b45af98fff75cd
F src/auth.c 0fac71038875693a937e506bceb492c5f136dd7b1249fbd4ae70b4e8da14f9df
F src/backup.c 78d3cecfbe28230a3a9a1793e2ead609f469be43e8f486ca996006be551857ab
F src/bitvec.c 17ea48eff8ba979f1f5b04cc484c7bb2be632f33
F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
F src/btree.c ba7c7eef4461790f37c309936bfc5d0d6ba9b194b02d3c8ff1fd53b420ea6d3b
F src/btree.c 3d898feaeff97c934cb6ae557265e43ba1f473de6a9e64e947a364bdb6c4f563
F src/btree.h febb2e817be499570b7a2e32a9bbb4b607a9234f6b84bb9ae84916d4806e96f2
F src/btreeInt.h 620ab4c7235f43572cf3ac2ac8723cbdf68073be4d29da24897c7b77dda5fd96
F src/build.c 127d33ad57b455a9339e9fabff41284c8b030cc6247ca7a2a6c0ad7abfc1ce85
F src/callback.c 789bd33d188146f66c0dd8306472a72d1c05f71924b24a91caf6bd45cf9aba73
F src/build.c ef9d7dc73e40dd9d10c28848343e21e8bc1baaab92cfb75eda893fff4fbf6b55
F src/callback.c 25dda5e1c2334a367b94a64077b1d06b2553369f616261ca6783c48bcb6bda73
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c 109e58d00f62e8e71ee1eb5944ac18b90171c928ab2e082e058056e1137cc20b
F src/date.c ebe1dc7c8a347117bb02570f1a931c62dd78f4a2b1b516f4837d45b7d6426957
F src/dbpage.c 135eb3b5e74f9ef74bde5cec2571192c90c86984fa534c88bf4a055076fa19b7
F src/dbstat.c 3c8bd4e77f0244fd2bd7cc90acf116ad2f8e82d70e536637f35ac2bc99b726f9
F src/delete.c f7938125847e8ef485448db5fbad29acb2991381a02887dd854c1617315ab9fb
F src/expr.c 9aacc0b72348ba90010b672dcbbbe2fa56e1182043bc917a3a147b2bc57a5497
F src/expr.c b84c41530d97e28d5c43149d23d4492e26cd4e1e93abba1302d361e71a04b614
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 972a4ba14296bef2303a0abbad1e3d82bc3c61f9e6ce4e8e9528bdee68748812
F src/func.c 7c288b4ce309b5a8b8473514b88e1f8e69a80134509a8c0db8e39c858e367e7f
F src/global.c 8291eee0782b83124de14ec0389ec9fd6ae1873358a6b0d9469fe17a46ad803b
F src/hash.c 931ec82d7e070654a8facb42549bbb3a25720171d73ba94c3d3160580d01ef1f
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 6b81aae27b196925d8ff78824f4bbd435d6a40cd38dc324685e21735bb402109
F src/insert.c f12f27eb606d601825be9a229a7390a8d64d40226697883f96de8e088d620055
F src/legacy.c 134ab3e3fae00a0f67a5187981d6935b24b337bcf0f4b3e5c9fa5763da95bf4e
F src/loadext.c 9050dd153b5583804184be9c9dee9ebb554178d6db1f8ac280899e8aad9060e6
F src/main.c 4cfb3913cc9e65d3ac649b1785ac753fc225d29425d5437e012f7eac0cefe0eb
F src/loadext.c e6f10875d52aca3b7e57ce1ec174aeafc9b6c00b43000cd30d791f9cb490b7a6
F src/main.c 008f45dd39cdc7fb9e7e1f61d75a5c97397f8e07427a8879be23e27747d5f948
F src/malloc.c 07295435093ce354c6d9063ac05a2eeae28bd251d2e63c48b3d67c12c76f7e18
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c12a42539b1ba105e3707d0e628ad70e611040d8f5e38cf942cee30c867083de
@@ -495,23 +496,23 @@ F src/os_win.c 85d9e532d0444ab6c16d7431490c2e279e282aa0917b0e988996b1ae0de5c5a0
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 75e0f3cfa3962c714f519f8a3d1e67ecca1c91de0e010a036b988e40ce9e4c73
F src/pager.h 217921e81eb5fe455caa5cda96061959706bcdd29ddb57166198645ef7822ac3
F src/parse.y 6840fe7c0b5eb4dd25ee5d075213bc8255ed4c0678d71bfb6744d0520d91c179
F src/parse.y a3c0db595bc642c6ee1d72869842f7f5b0b6ebeb91c21d0a7cba631d27e7afbd
F src/pcache.c 696a01f1a6370c1b50a09c15972bc3bee3333f8fcd1f2da8e9a76b1b062c59ee
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c bf9fcea656dce1cd2cca6b77a1d1d3552050d55a31c98bf0d9f405930a83bc95
F src/pragma.c 4e056f042683b99c4ea0db395f68d051b1a95833ab40951c40d3ef7e1fee1354
F src/pcache1.c ad0ffc5b35b0280d045ac569d34d4b842e3e6a4a118f6396b320987a0957afcc
F src/pragma.c 96ce7dce4dc9cb2b7aa0e1b2ce7536870bdc00b10becc278245e775489447ea0
F src/pragma.h fdd03d78a7497f74a3f652909f945328480089189526841ae829ce7313d98d13
F src/prepare.c f81f8d707e583192c28fea0b2e19385415b7d188123b23f49b038076408d7a69
F src/prepare.c 0e8fc0deaf36da104e08d07ce7d97bc09ab57d078b399381532fec3fa1d3f2bb
F src/printf.c 0f1177cf1dd4d7827bf64d840768514ec76409abecaca9e8b577dbd065150381
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 4cfc44def0f0690ceaab8f6481f5d76284d7f9509aab6e218a679b4836a54614
F src/resolve.c abd65c518c198400193c6319a70c0d722fa30a35be89dc898917ff6489edf017
F src/rowset.c d977b011993aaea002cab3e0bb2ce50cf346000dff94e944d547b989f4b1fe93
F src/select.c 61e867a906f140b73baf4ce7a201ad6dcba30820969f5618ee40e9a0d32c6f5f
F src/shell.c.in 482e23a370cbe5b0d4c73a0f0f5fce34f7caa08a14a8d75e12f0225c4e14915c
F src/sqlite.h.in cce9feede1c1c03923c091b4bbbd081dd77aaf92024cc2cdbf65f712c2f668c3
F src/select.c 8c7317d5ee920516a56b8b4ca79fbfca70a1f8b52d67e884c808ea3a016c04e3
F src/shell.c.in 6c06ff4077ab38b30a307c058ecc650e958bfdb6da1c255ebbd8779447e0cae9
F src/sqlite.h.in 92fd656c26cc76de9fa8c5bf1a473066e3b5c6da345a447679f0f44de1aa4edd
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 960f1b86c3610fa23cb6a267572a97dcf286e77aa0dd3b9b23292ffaa1ea8683
F src/sqliteInt.h 1161f7579cdd6217737a66517ef27f4016426603eff492e9b31f45a7d7d4c61f
F src/sqliteInt.h 3dda7ba0ea00f591c18405e5061d10041e0fcd5934e2542f29f8c8cffd73c242
F src/sqliteLimit.h 1513bfb7b20378aa0041e7022d04acb73525de35b80b252f1b83fedb4de6a76b
F src/status.c 46e7aec11f79dad50965a5ca5fa9de009f7d6bde08be2156f1538a0a296d4d0e
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@@ -569,19 +570,19 @@ F src/test_windirent.h 90dfbe95442c9762357fe128dc7ae3dc199d006de93eb33ba3972e0a9
F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394ba3f
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
F src/tokenize.c 9e781e1ca80eefe7b5d6a9e2cd5c678c847da55fd6f093781fad7950934d4c83
F src/tokenize.c c8af4feebd8bf5a4d60a14018d91f61013f658ec864dfce7661bae73d86b3191
F src/treeview.c 7b12ac059de54c939b6eb0dbffc9410c29c80d2470cee5cbe07d5ff9ea2d9253
F src/trigger.c d3d78568f37fb2e6cdcc2d1e7b60156f15b0b600adec55b83c5d42f6cad250bd
F src/update.c 1816d56c1bca1ba4e0ef98cac2f49be62858e9df1dc08844c7067eb41cc44274
F src/upsert.c 0dd81b40206841814d46942a7337786932475f085716042d0cb2fc7791bf8ca4
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
F src/util.c d9eb0a6c4aae1b00a7369eadd7ca0bbe946cb4c953b6751aa20d357c2f482157
F src/vacuum.c 836cadc922de866c849e23a75f93d344cdc143d388339305d09a3fed27e8798d
F src/vdbe.c 005e691ea4c7d51e6c1a69d9389aeb34700884c85f51681817ddea3fdc2fc39b
F src/vdbe.h 5081dcc497777efe5e9ebe7330d283a044a005e4bdda2e2e984f03bf89a0d907
F src/vdbeInt.h 437e6c6af679fdf157867eb83a8adc6cf5145d6774453c2214cfd0bd01d92980
F src/vdbeapi.c ecccfce6f614c33a95952efeec969d163e8349eac314ee2b7b163eda921b5eb0
F src/vdbeaux.c f547901b1aa9e2d81c63f06893f633648e434180666a827aacb547d7d6c8a601
F src/vacuum.c 3ffe64ecfc94b7528c5d7bdb1c3a19d72fec63f2aa846e3b90f8de5dbbddf5aa
F src/vdbe.c 55bafc424748d9ed505ab2680736e51d1bb05c01e9885cbb3b287b51dc8b47ec
F src/vdbe.h 8990d668a89890a33326b0a29b992c4014b72f3b6cdcd9ee0e190593c247f9b0
F src/vdbeInt.h 73f5051923f3f29779bfc374c0c68e23b8e5e3792def2e33e51b427edb890abd
F src/vdbeapi.c 57a2d794a8833f269b878dbc24e955369bdb379af6c4e93ebc5ce1a20fa3daf4
F src/vdbeaux.c f00d9b32a250b829a3c00140255a1c37a6463d726bb87ed6bbb80a1ce76a56bd
F src/vdbeblob.c f5c70f973ea3a9e915d1693278a5f890dc78594300cf4d54e64f2b0917c94191
F src/vdbemem.c 7b3305bc4a5139f4536ac9b5f61da0f915e49d2e3fdfa87dfdfa9d7aba8bc1e9
F src/vdbesort.c 90aad5a92608f2dd771c96749beabdb562c9d881131a860a7a5bccf66dc3be7f
@@ -595,7 +596,7 @@ F src/where.c 3818e8a736a05d2cb194e64399af707e367fbcc5c251d785804d02eaf121288e
F src/whereInt.h f125f29fca80890768e0b2caa14f95db74b2dacd3a122a168f97aa7b64d6968f
F src/wherecode.c c45f03aefc2266b990df0fc4d7acc4e27f56f881f4fc0fc355b7cbc4d7189da5
F src/whereexpr.c 491f0894ad9903750cdecb7894437a0cabdffdd88f574d2b1c9ac85d14fe4b9c
F src/window.c 6550e2850ebced51100ef83d49b00a1cf03f81a482dafedafb0320df647ed8fc
F src/window.c ea81ecd031ed2cbc14b7db6fd7f4bee2471b894feae5fea0547b15b1e2dd8fb2
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
F test/affinity3.test 6a101af2fc945ce2912f6fe54dd646018551710d
@@ -614,7 +615,7 @@ F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
F test/altertab.test 17e46baa6b2234048c91891a303141afceca4da95a36ee1a0a9fec6ccef1f4da
F test/altertab2.test 0d64de5632ca5de13b023839cfe5b8952d029e4622befcea1433adaa93883220
F test/altertab2.test 814369c72a7ed777ab2acf3f17fcff5ecb724816eb7c6659f40ef87b09521c99
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 7168c8bffa5d5cbc53c05b7e9c7fcdd24b365a1bc5046ce80c45efa3c02e6b7c
F test/analyze3.test ff62d9029e6deb2c914490c6b00caf7fae47cc85cdc046e4a0d0a4d4b87c71d8
@@ -773,7 +774,7 @@ F test/date.test 9b73bbeb1b82d9c1f44dec5cf563bf7da58d2373
F test/date2.test 74c234bece1b016e94dd4ef9c8cc7a199a8806c0e2291cab7ba64bace6350b10
F test/dbfuzz.c 73047c920d6210e5912c87cdffd9a1c281d4252e
F test/dbfuzz2-seed1.db e6225c6f3d7b63f9c5b6867146a5f329d997ab105bee64644dc2b3a2f2aebaee
F test/dbfuzz2.c 652f85bac1770e927da139db513234a3eba308f72ac2f8b32f0093d7d19def70
F test/dbfuzz2.c b8ed9b32a1f287505e55970e55203bedcb9170f137ecefa2254033c9faccdfba
F test/dbpage.test 650234ba683b9d82b899c6c51439819787e7609f17a0cc40e0080a7b6443bc38
F test/dbstatus.test cd83aa623b8aab477269bc94cf8aa90c1e195a144561dd04a1620770aaa8524e
F test/dbstatus2.test f5fe0afed3fa45e57cfa70d1147606c20d2ba23feac78e9a172f2fe8ab5b78ef
@@ -956,6 +957,7 @@ F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 5553d7bb2e20bf4a06b23e849352efc022ce6309
F test/fts4onepass.test d69ddc4ee3415e40b0c5d1d0408488a87614d4f63ba9c44f3e52db541d6b7cc7
F test/fts4opt.test 0fd0cc84000743ff2a883b9b84b4a5be07249f0ba790c8848a757164cdd46b2a
F test/fts4umlaut.test 1d28e2a2dffa794e15babadebdece091431b09d740be79c08eb6aba1173a8c84
F test/fts4unicode.test ceca76422abc251818cb25dabe33d3c3970da5f7c90e1540f190824e6b3a7c95
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test 09dda479bcfc568f99f3070413e9672a8eeedc1be9c5d819bf55d4788c2583b7
@@ -968,6 +970,7 @@ F test/fuzz-oss1.test e58330d01cbbd8215ee636b17a03fe220b37dbfa
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz2.test 76dc35b32b6d6f965259508508abce75a6c4d7e1
F test/fuzz3.test 9c813e6613b837cb7a277b0383cd66bfa07042b4cf0317157c35852f30043c31
F test/fuzz4.test c229bcdb45518a89e1d208a21343e061503460ac69fae1539320a89f572eb634
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
F test/fuzz_malloc.test f348276e732e814802e39f042b1f6da6362a610af73a528d8f76898fde6b22f2
F test/fuzzcheck.c fda41c0e4e667fae96b002410bb19cece7a33314264ed6bbc6d012909ee9fd58
@@ -977,7 +980,7 @@ F test/fuzzdata3.db c6586d3e3cef0fbc18108f9bb649aa77bfc38aba
F test/fuzzdata4.db b502c7d5498261715812dd8b3c2005bad08b3a26e6489414bd13926cd3e42ed2
F test/fuzzdata5.db e35f64af17ec48926481cfaf3b3855e436bd40d1cfe2d59a9474cb4b748a52a5
F test/fuzzdata6.db 92a80e4afc172c24f662a10a612d188fb272de4a9bd19e017927c95f737de6d7
F test/fuzzdata7.db a1bf54eb455e9772942abae1b2d1cf1e3d3659f0e5dd14f00792fd01411ae8ef
F test/fuzzdata7.db c8c5ef745ce43eb24d6903bff63ddc336464b6b4f9dfae817e7ec2ea0e541dbd
F test/fuzzer1.test 3d4c4b7e547aba5e5511a2991e3e3d07166cfbb8
F test/fuzzer2.test a85ef814ce071293bce1ad8dffa217cbbaad4c14
F test/fuzzerfault.test 8792cd77fd5bce765b05d0c8e01b9edcf8af8536
@@ -1013,7 +1016,7 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
F test/index3.test 51685f39345462b84fcf77eb8537af847fdf438cc96b05c45d6aaca4e473ade0
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
F test/index6.test d07ea75b8c21f125c6f325522e8df8c05c91e9251ec923a31d0582b2ba4a617d
F test/index6.test 6b3e6cd4bef343ed4541e74c55936ed112962a6552c085242612b598e12910a4
F test/index7.test 72b59b8ddc5c13f4962886b4011eb9975014317d17ef36c6297921362fb7dd98
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
F test/index9.test 0aa3e509dddf81f93380396e40e9bb386904c1054924ba8fa9bcdfe85a8e7721
@@ -1053,7 +1056,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 b40a9f5395d8e669b0bc3eb550ad2ae9e5ada01fbce23c446c2a30a305a6d575
F test/json101.test 8f8977b00ba02f9a26c1d1f52f29f540f6d5eb162cbd5eb78bb805366d4ab26d
F test/json102.test eeb54efa221e50b74a2d6fb9259963b48d7414dca3ce2fdfdeed45cb28487bc1
F test/json103.test aff6b7a4c17d5a20b487a7bc1a274bfdc63b829413bdfb83bedac42ec7f67e3b
F test/json104.test 877d5845f6303899b7889ea5dd1bea99076e3100574d5c536082245c5805dcaa
@@ -1140,7 +1143,7 @@ F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test 437d40e6d0778b050d7750726c0cbd2c9936b81962926e8f8c48ca698f00f4d1
F test/nockpt.test 8c43b25af63b0bd620cf1b003529e37b6f1dc53bd22690e96a1bd73f78dde53a
F test/nolock.test f196cf8b8fbea4e2ca345140a2b3f3b0da45c76e
F test/normalize.test 6a80564d2000702b5919ed2c1069fef0f95762142bc96a71b4c124a845165713
F test/normalize.test 422027884ffb67ebba32bb78487c67cf67643496d19c077b07044bdba071a3f6
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test 2ecabaa1305083856b7c39cf32816b612740c161
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -1275,10 +1278,10 @@ 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 d2bf5daeb6f449f0169c9ef3094db17a16a02199c5dcf1a635a3e79b07eb0edd
F test/shell1.test 0378c4e9e800da6fbb3c86c0c8f2cf5efc9e4155b4b6447d27dc71de648fc0a1
F test/shell2.test e242a9912f44f4c23c3d1d802a83e934e84c853b
F test/shell3.test ac8c2b744014c3e9a0e26bfd829ab65f00923dc1a91ffd044863e9423cc91494
F test/shell4.test 89ad573879a745974ff2df20ff97c5d6ffffbd5d
F test/shell4.test a6881d0ae226ded0df8ebdfa574c5aa6dc28d6884ccba1089dc56ed08b9e5ef4
F test/shell5.test 23939a4c51f0421330ea61dbd3c74f9c215f5f8d3d1a94846da6ffc777a35458
F test/shell6.test 1ceb51b2678c472ba6cf1e5da96679ce8347889fe2c3bf93a0e0fa73f00b00d3
F test/shell7.test 115132f66d0463417f408562cc2cf534f6bbc6d83a6d50f0072a9eb171bae97f
@@ -1343,7 +1346,7 @@ F test/sync.test 89539f4973c010eda5638407e71ca7fddbcd8e0594f4c9980229f804d433309
F test/sync2.test 8f9f7d4f6d5be8ca8941a8dadcc4299e558cb6a1ff653a9469146c7a76ef2039
F test/syscall.test a39d9a36f852ae6e4800f861bc2f2e83f68bbc2112d9399931ecfadeabd2d69d
F test/sysfault.test c9f2b0d8d677558f74de750c75e12a5454719d04
F test/tabfunc01.test 54300134f76db817685194d2f0e63e3fbf7380b45e0d426e00a9aee752497cfb
F test/tabfunc01.test 20e98ffe55f35d8d33fd834ca8bf9d4b637e560af8fcd00464b4154d90a4db45
F test/table.test eb3463b7add9f16a5bb836badf118cf391b809d09fdccd1f79684600d07ec132
F test/tableapi.test ecbcc29c4ab62c1912c3717c48ea5c5e59f7d64e4a91034e6148bd2b82f177f4
F test/tableopts.test dba698ba97251017b7c80d738c198d39ab747930
@@ -1560,6 +1563,7 @@ F test/uri.test 3481026f00ade6dfe8adb7acb6e1e47b04369568
F test/uri2.test 9d3ba7a53ee167572d53a298ee4a5d38ec4a8fb7
F test/userauth01.test e740a2697a7b40d7c5003a7d7edaee16acd349a9
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
F test/vacuum-into.test 181a8ae8c2479d88ebc118076e8cfbc062ad8f8a51b56a139bd12870a8a84c34
F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
@@ -1653,7 +1657,7 @@ F test/win32heap.test 10fd891266bd00af68671e702317726375e5407561d859be1aa04696f2
F test/win32lock.test fbf107c91d8f5512be5a5b87c4c42ab9fdd54972
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/win32nolock.test ac4f08811a562e45a5755e661f45ca85892bdbbc
F test/window1.test 02e481ac48c445b43bab7b3cf1e4115165b5127a1aa29e14f5372922c836f1a4
F test/window1.test 1003e19bebe06be286a38139ea5fc010b30c055cc1527824b09d609f89bbd93b
F test/window2.tcl 9bfa842d8a62b0d36dc8c1b5972206393c43847433c6d75940b87fec93ce3143
F test/window2.test 8e6d2a1b9f54dfebee1cde961c8590cd87b4db45c50f44947a211e1b63c2a05e
F test/window3.tcl 577a3b1ff913208e5248c04dab9df17fd760ce159a752789e26d0cb4a5f91823
@@ -1690,6 +1694,8 @@ F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/dbhash.c a06228aa21ebc4e6ea8daa486601d938499238a5
F tool/dbtotxt.c 1655f60fd7b24a3e7a25d01cdb3a6a4785f30112213b08ff83a27ae7ef2dd13e
F tool/dbtotxt.md c9a57af8739957ef36d2cfad5c4b1443ff3688ed33e4901ee200c8b651f43f3c
F tool/extract.c 054069d81b095fbdc189a6f5d4466e40380505e2
F tool/fast_vacuum.c 5ba0d6f5963a0a63bdc42840f678bad75b2ebce1
F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
@@ -1697,9 +1703,10 @@ F tool/fuzzershell.c e1d90a03ca790d7c331c2aae08ca46ff435f1ae1faa6cb9cc48f4687c18
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test b6afd7b825d797a1e1274f519ab5695373552ecad5cd373530c63533638a5a4f
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/index_usage.c 8fd515b97522ae4b1aa6ca9847439f005d4cbaf6eb0eb416b694dba77c0263f0
F tool/kvtest-speed.sh 4761a9c4b3530907562314d7757995787f7aef8f
F tool/lemon.c 60d1e1eb0f7ebae709f68f1472d77fbf291c5345cd98ff417219da7e74fd09e9
F tool/lempar.c 452f12d40229847634a160e5666b6c4ec4392fd81941c3443861b48d497054cc
F tool/lemon.c c9ba01f6729c892ae3e0f55c8a2d694a7e6ec3dd3aa280b411a008ef69b410cd
F tool/lempar.c 61af95b8fac2bfd59c09d55330e78f3f5e352d7aa80bf37404b96ef795be3fdc
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
@@ -1779,10 +1786,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 23684cb841ac2cb0d69e5470253bd96feb733762a7553b952a08470834fe85fa
R dcc394af10af6094607f56a6086fb748
T +bgcolor * #d0c0ff
T +sym-release *
T +sym-version-3.26.0 *
P b4210d320c6426d2838d4cc08709fdfd015c1c95fcad9a5f9e8fd390c23b9fad e3bf1d3ea5f748c5142c2403813fdace5aedc1fc68f0dcd5eae40a2fe763fedb
R f29a990b635857a4ac73167c7e81e845
U drh
Z 560a5decbb241d53eb97e72267b6e6e8
Z 899a9ea598b74391d5cfbd03300f9f81
+1 -1
View File
@@ -1 +1 @@
bf8c1b2b7a5960c282e543b9c293686dccff272512d08865f4600fb58238b4f9
b386fce9a23e628dce7362dcca2904b8d0af6da58a6fe6eb7f12f058a8363e49
+24 -2
View File
@@ -780,14 +780,31 @@ static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
}
}
/*
** Iterate through the Select objects that are part of WITH clauses attached
** to select statement pSelect.
*/
static void renameWalkWith(Walker *pWalker, Select *pSelect){
if( pSelect->pWith ){
int i;
for(i=0; i<pSelect->pWith->nCte; i++){
Select *p = pSelect->pWith->a[i].pSelect;
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
sNC.pParse = pWalker->pParse;
sqlite3SelectPrep(sNC.pParse, p, &sNC);
sqlite3WalkSelect(pWalker, p);
}
}
}
/*
** This is a Walker select callback. It does nothing. It is only required
** because without a dummy callback, sqlite3WalkExpr() and similar do not
** descend into sub-select statements.
*/
static int renameColumnSelectCb(Walker *pWalker, Select *p){
UNUSED_PARAMETER(pWalker);
UNUSED_PARAMETER(p);
renameWalkWith(pWalker, p);
return WRC_Continue;
}
@@ -1358,12 +1375,17 @@ static int renameTableSelectCb(Walker *pWalker, Select *pSelect){
int i;
RenameCtx *p = pWalker->u.pRename;
SrcList *pSrc = pSelect->pSrc;
if( pSrc==0 ){
assert( pWalker->pParse->db->mallocFailed );
return WRC_Abort;
}
for(i=0; i<pSrc->nSrc; i++){
struct SrcList_item *pItem = &pSrc->a[i];
if( pItem->pTab==p->pTab ){
renameTokenFind(pWalker->pParse, p, pItem->zName);
}
}
renameWalkWith(pWalker, pSelect);
return WRC_Continue;
}
+9 -14
View File
@@ -1412,19 +1412,14 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
** reconstruct the entire page. */
if( (int)data[hdr+7]<=nMaxFrag ){
int iFree = get2byte(&data[hdr+1]);
/* If the initial freeblock offset were out of bounds, that would
** have been detected by btreeInitPage() when it was computing the
** number of free bytes on the page. */
assert( iFree<=usableSize-4 );
if( iFree ){
int iFree2 = get2byte(&data[iFree]);
/* pageFindSlot() has already verified that free blocks are sorted
** in order of offset within the page, and that no block extends
** past the end of the page. Provided the two free slots do not
** overlap, this guarantees that the memmove() calls below will not
** overwrite the usableSize byte buffer, even if the database page
** is corrupt. */
assert( iFree2==0 || iFree2>iFree );
assert( iFree+get2byte(&data[iFree+2]) <= usableSize );
assert( iFree2==0 || iFree2+get2byte(&data[iFree2+2]) <= usableSize );
if( iFree2>usableSize-4 ) return SQLITE_CORRUPT_PAGE(pPage);
if( 0==iFree2 || (data[iFree2]==0 && data[iFree2+1]==0) ){
u8 *pEnd = &data[cellOffset + nCell*2];
u8 *pAddr;
@@ -1435,9 +1430,9 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){
return SQLITE_CORRUPT_PAGE(pPage);
}
if( iFree2 ){
assert( iFree+sz<=iFree2 ); /* Verified by pageFindSlot() */
if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PAGE(pPage);
sz2 = get2byte(&data[iFree2+2]);
assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize );
if( iFree2+sz2 > usableSize ) return SQLITE_CORRUPT_PAGE(pPage);
memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz));
sz += sz2;
}
@@ -9856,7 +9851,7 @@ char *sqlite3BtreeIntegrityCheck(
}
#endif
testcase( pBt->db->flags & SQLITE_CellSizeCk );
pBt->db->flags &= ~SQLITE_CellSizeCk;
pBt->db->flags &= ~(u64)SQLITE_CellSizeCk;
for(i=0; (int)i<nRoot && sCheck.mxErr; i++){
i64 notUsed;
if( aRoot[i]==0 ) continue;
+1 -7
View File
@@ -227,7 +227,7 @@ void sqlite3FinishCoding(Parse *pParse){
if( v && pParse->nErr==0 && !db->mallocFailed ){
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
if( pParse->pAinc!=0 && pParse->nTab==0 ) pParse->nTab = 1;
assert( pParse->pAinc==0 || pParse->nTab>0 );
sqlite3VdbeMakeReady(v, pParse);
pParse->rc = SQLITE_DONE;
}else{
@@ -636,12 +636,6 @@ static void SQLITE_NOINLINE deleteTable(sqlite3 *db, Table *pTable){
/* Delete the Table structure itself.
*/
#ifdef SQLITE_ENABLE_NORMALIZE
if( pTable->pColHash ){
sqlite3HashClear(pTable->pColHash);
sqlite3_free(pTable->pColHash);
}
#endif
sqlite3DeleteColumnNames(db, pTable);
sqlite3DbFree(db, pTable->zName);
sqlite3DbFree(db, pTable->zColAff);
+3 -18
View File
@@ -283,7 +283,7 @@ static int matchQuality(
** Search a FuncDefHash for a function with the given name. Return
** a pointer to the matching FuncDef if found, or 0 if there is no match.
*/
static FuncDef *functionSearch(
FuncDef *sqlite3FunctionSearch(
int h, /* Hash of the name */
const char *zFunc /* Name of function */
){
@@ -295,21 +295,6 @@ static FuncDef *functionSearch(
}
return 0;
}
#ifdef SQLITE_ENABLE_NORMALIZE
FuncDef *sqlite3FunctionSearchN(
int h, /* Hash of the name */
const char *zFunc, /* Name of function */
int nFunc /* Length of the name */
){
FuncDef *p;
for(p=sqlite3BuiltinFunctions.a[h]; p; p=p->u.pHash){
if( sqlite3StrNICmp(p->zName, zFunc, nFunc)==0 ){
return p;
}
}
return 0;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Insert a new FuncDef into a FuncDefHash hash table.
@@ -325,7 +310,7 @@ void sqlite3InsertBuiltinFuncs(
int nName = sqlite3Strlen30(zName);
int h = SQLITE_FUNC_HASH(zName[0], nName);
assert( zName[0]>='a' && zName[0]<='z' );
pOther = functionSearch(h, zName);
pOther = sqlite3FunctionSearch(h, zName);
if( pOther ){
assert( pOther!=&aDef[i] && pOther->pNext!=&aDef[i] );
aDef[i].pNext = pOther->pNext;
@@ -403,7 +388,7 @@ FuncDef *sqlite3FindFunction(
if( !createFlag && (pBest==0 || (db->mDbFlags & DBFLAG_PreferBuiltin)!=0) ){
bestScore = 0;
h = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zName[0]], nName);
p = functionSearch(h, zName);
p = sqlite3FunctionSearch(h, zName);
while( p ){
int score = matchQuality(p, nArg, enc);
if( score>bestScore ){
+39 -14
View File
@@ -141,8 +141,8 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
while( p ){
int op = p->op;
if( p->flags & EP_Generic ) break;
if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|| op==TK_REGISTER || op==TK_TRIGGER)
if( op==TK_REGISTER ) op = p->op2;
if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_TRIGGER)
&& p->y.pTab!=0
){
/* op==TK_REGISTER && p->y.pTab!=0 happens when pExpr was originally
@@ -158,7 +158,7 @@ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
p = p->pLeft;
continue;
}
if( op==TK_COLLATE || (op==TK_REGISTER && p->op2==TK_COLLATE) ){
if( op==TK_COLLATE ){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
@@ -1330,6 +1330,35 @@ static With *withDup(sqlite3 *db, With *p){
# define withDup(x,y) 0
#endif
#ifndef SQLITE_OMIT_WINDOWFUNC
/*
** The gatherSelectWindows() procedure and its helper routine
** gatherSelectWindowsCallback() are used to scan all the expressions
** an a newly duplicated SELECT statement and gather all of the Window
** objects found there, assembling them onto the linked list at Select->pWin.
*/
static int gatherSelectWindowsCallback(Walker *pWalker, Expr *pExpr){
if( pExpr->op==TK_FUNCTION && pExpr->y.pWin!=0 ){
assert( ExprHasProperty(pExpr, EP_WinFunc) );
pExpr->y.pWin->pNextWin = pWalker->u.pSelect->pWin;
pWalker->u.pSelect->pWin = pExpr->y.pWin;
}
return WRC_Continue;
}
static int gatherSelectWindowsSelectCallback(Walker *pWalker, Select *p){
return p==pWalker->u.pSelect ? WRC_Continue : WRC_Prune;
}
static void gatherSelectWindows(Select *p){
Walker w;
w.xExprCallback = gatherSelectWindowsCallback;
w.xSelectCallback = gatherSelectWindowsSelectCallback;
w.xSelectCallback2 = 0;
w.u.pSelect = p;
sqlite3WalkSelect(&w, p);
}
#endif
/*
** The following group of routines make deep copies of expressions,
** expression lists, ID lists, and select statements. The copies can
@@ -1497,6 +1526,7 @@ Select *sqlite3SelectDup(sqlite3 *db, Select *pDup, int flags){
#ifndef SQLITE_OMIT_WINDOWFUNC
pNew->pWin = 0;
pNew->pWinDefn = sqlite3WindowListDup(db, p->pWinDefn);
if( p->pWin ) gatherSelectWindows(pNew);
#endif
pNew->selId = p->selId;
*pp = pNew;
@@ -2149,14 +2179,6 @@ int sqlite3IsRowid(const char *z){
if( sqlite3StrICmp(z, "OID")==0 ) return 1;
return 0;
}
#ifdef SQLITE_ENABLE_NORMALIZE
int sqlite3IsRowidN(const char *z, int n){
if( sqlite3StrNICmp(z, "_ROWID_", n)==0 ) return 1;
if( sqlite3StrNICmp(z, "ROWID", n)==0 ) return 1;
if( sqlite3StrNICmp(z, "OID", n)==0 ) return 1;
return 0;
}
#endif
/*
** pX is the RHS of an IN operator. If pX is a SELECT statement
@@ -2421,6 +2443,7 @@ int sqlite3FindInIndex(
Bitmask colUsed; /* Columns of the index used */
Bitmask mCol; /* Mask for the current column */
if( pIdx->nColumn<nExpr ) continue;
if( pIdx->pPartIdxWhere!=0 ) continue;
/* Maximum nColumn is BMS-2, not BMS-1, so that we can compute
** BITMASK(nExpr) without overflowing */
testcase( pIdx->nColumn==BMS-2 );
@@ -4755,14 +4778,16 @@ int sqlite3ExprCompare(Parse *pParse, Expr *pA, Expr *pB, int iTab){
}
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( (combinedFlags & EP_TokenOnly)==0 ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( (combinedFlags & EP_FixedCol)==0
&& 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;
assert( (combinedFlags & EP_Reduced)==0 );
if( pA->op!=TK_STRING && pA->op!=TK_TRUEFALSE ){
if( pA->op!=TK_STRING
&& pA->op!=TK_TRUEFALSE
&& (combinedFlags & EP_Reduced)==0
){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
-56
View File
@@ -64,20 +64,6 @@ static unsigned int strHash(const char *z){
}
return h;
}
#ifdef SQLITE_ENABLE_NORMALIZE
static unsigned int strHashN(const char *z, int n){
unsigned int h = 0;
int i;
for(i=0; i<n; i++){
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
** 0x9e3779b1 is 2654435761 which is the closest prime number to
** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
h += sqlite3UpperToLower[z[i]];
h *= 0x9e3779b1;
}
return h;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/* Link pNew element into the hash table pH. If pEntry!=0 then also
@@ -189,40 +175,6 @@ static HashElem *findElementWithHash(
}
return &nullElement;
}
#ifdef SQLITE_ENABLE_NORMALIZE
static HashElem *findElementWithHashN(
const Hash *pH, /* The pH to be searched */
const char *pKey, /* The key we are searching for */
int nKey, /* Number of key bytes to use */
unsigned int *pHash /* Write the hash value here */
){
HashElem *elem; /* Used to loop thru the element list */
int count; /* Number of elements left to test */
unsigned int h; /* The computed hash */
static HashElem nullElement = { 0, 0, 0, 0 };
if( pH->ht ){ /*OPTIMIZATION-IF-TRUE*/
struct _ht *pEntry;
h = strHashN(pKey, nKey) % pH->htsize;
pEntry = &pH->ht[h];
elem = pEntry->chain;
count = pEntry->count;
}else{
h = 0;
elem = pH->first;
count = pH->count;
}
if( pHash ) *pHash = h;
while( count-- ){
assert( elem!=0 );
if( sqlite3StrNICmp(elem->pKey,pKey,nKey)==0 ){
return elem;
}
elem = elem->next;
}
return &nullElement;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/* Remove a single entry from the hash table given a pointer to that
** element and a hash on the element's key.
@@ -267,14 +219,6 @@ void *sqlite3HashFind(const Hash *pH, const char *pKey){
assert( pKey!=0 );
return findElementWithHash(pH, pKey, 0)->data;
}
#ifdef SQLITE_ENABLE_NORMALIZE
void *sqlite3HashFindN(const Hash *pH, const char *pKey, int nKey){
assert( pH!=0 );
assert( pKey!=0 );
assert( nKey>=0 );
return findElementWithHashN(pH, pKey, nKey, 0)->data;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/* Insert an element into the hash table pH. The key is pKey
** and the data is "data".
+1
View File
@@ -319,6 +319,7 @@ void sqlite3AutoincrementBegin(Parse *pParse){
aOp[7].p2 = memId+2;
aOp[7].p1 = memId;
aOp[10].p2 = memId;
if( pParse->nTab==0 ) pParse->nTab = 1;
}
}
+1 -1
View File
@@ -650,7 +650,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
if( onoff ){
db->flags |= SQLITE_LoadExtension|SQLITE_LoadExtFunc;
}else{
db->flags &= ~(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
db->flags &= ~(u64)(SQLITE_LoadExtension|SQLITE_LoadExtFunc);
}
sqlite3_mutex_leave(db->mutex);
return SQLITE_OK;
+6 -4
View File
@@ -843,11 +843,11 @@ int sqlite3_db_config(sqlite3 *db, int op, ...){
if( aFlagOp[i].op==op ){
int onoff = va_arg(ap, int);
int *pRes = va_arg(ap, int*);
u32 oldFlags = db->flags;
u64 oldFlags = db->flags;
if( onoff>0 ){
db->flags |= aFlagOp[i].mask;
}else if( onoff==0 ){
db->flags &= ~aFlagOp[i].mask;
db->flags &= ~(u64)aFlagOp[i].mask;
}
if( oldFlags!=db->flags ){
sqlite3ExpirePreparedStatements(db, 0);
@@ -1310,7 +1310,7 @@ void sqlite3RollbackAll(sqlite3 *db, int tripCode){
/* Any deferred constraint violations have now been resolved. */
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~SQLITE_DeferFKs;
db->flags &= ~(u64)SQLITE_DeferFKs;
/* If one has been configured, invoke the rollback-hook callback */
if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
@@ -2052,6 +2052,8 @@ void *sqlite3_profile(
pOld = db->pProfileArg;
db->xProfile = xProfile;
db->pProfileArg = pArg;
db->mTrace &= SQLITE_TRACE_NONLEGACY_MASK;
if( db->xProfile ) db->mTrace |= SQLITE_TRACE_XPROFILE;
sqlite3_mutex_leave(db->mutex);
return pOld;
}
@@ -2403,7 +2405,7 @@ const char *sqlite3_errmsg(sqlite3 *db){
z = sqlite3ErrStr(SQLITE_NOMEM_BKPT);
}else{
testcase( db->pErr==0 );
z = (char*)sqlite3_value_text(db->pErr);
z = db->errCode ? (char*)sqlite3_value_text(db->pErr) : 0;
assert( !db->mallocFailed );
if( z==0 ){
z = sqlite3ErrStr(db->errCode);
+12 -2
View File
@@ -664,6 +664,12 @@ seltablist(A) ::= stl_prefix(A) nm(Y) dbnm(D) LP exprlist(E) RP as(Z)
pNew->zName = pOld->zName;
pNew->zDatabase = pOld->zDatabase;
pNew->pSelect = pOld->pSelect;
if( pOld->fg.isTabFunc ){
pNew->u1.pFuncArg = pOld->u1.pFuncArg;
pOld->u1.pFuncArg = 0;
pOld->fg.isTabFunc = 0;
pNew->fg.isTabFunc = 1;
}
pOld->zName = pOld->zDatabase = 0;
pOld->pSelect = 0;
}
@@ -1361,8 +1367,12 @@ cmd ::= DROP INDEX ifexists(E) fullname(X). {sqlite3DropIndex(pParse, X, E);}
//
%ifndef SQLITE_OMIT_VACUUM
%ifndef SQLITE_OMIT_ATTACH
cmd ::= VACUUM. {sqlite3Vacuum(pParse,0);}
cmd ::= VACUUM nm(X). {sqlite3Vacuum(pParse,&X);}
%type vinto {Expr*}
%destructor vinto {sqlite3ExprDelete(pParse->db, $$);}
cmd ::= VACUUM vinto(Y). {sqlite3Vacuum(pParse,0,Y);}
cmd ::= VACUUM nm(X) vinto(Y). {sqlite3Vacuum(pParse,&X,Y);}
vinto(A) ::= INTO expr(X). {A = X;}
vinto(A) ::= . {A = 0;}
%endif SQLITE_OMIT_ATTACH
%endif SQLITE_OMIT_VACUUM
+6 -3
View File
@@ -102,6 +102,7 @@ struct PgHdr1 {
PCache1 *pCache; /* Cache that currently owns this page */
PgHdr1 *pLruNext; /* Next in LRU list of unpinned pages */
PgHdr1 *pLruPrev; /* Previous in LRU list of unpinned pages */
/* NB: pLruPrev is only valid if pLruNext!=0 */
};
/*
@@ -570,7 +571,8 @@ static PgHdr1 *pcache1PinPage(PgHdr1 *pPage){
pPage->pLruPrev->pLruNext = pPage->pLruNext;
pPage->pLruNext->pLruPrev = pPage->pLruPrev;
pPage->pLruNext = 0;
pPage->pLruPrev = 0;
/* pPage->pLruPrev = 0;
** No need to clear pLruPrev as it is never accessed if pLruNext is 0 */
assert( pPage->isAnchor==0 );
assert( pPage->pCache->pGroup->lru.isAnchor==1 );
pPage->pCache->nRecyclable--;
@@ -908,8 +910,9 @@ static SQLITE_NOINLINE PgHdr1 *pcache1FetchStage2(
pPage->iKey = iKey;
pPage->pNext = pCache->apHash[h];
pPage->pCache = pCache;
pPage->pLruPrev = 0;
pPage->pLruNext = 0;
/* pPage->pLruPrev = 0;
** No need to clear pLruPrev since it is not accessed when pLruNext==0 */
*(void **)pPage->page.pExtra = 0;
pCache->apHash[h] = pPage;
if( iKey>pCache->iMaxKey ){
@@ -1069,7 +1072,7 @@ static void pcache1Unpin(
/* It is an error to call this function if the page is already
** part of the PGroup LRU list.
*/
assert( pPage->pLruPrev==0 && pPage->pLruNext==0 );
assert( pPage->pLruNext==0 );
assert( PAGE_IS_PINNED(pPage) );
if( reuseUnlikely || pGroup->nPurgeable>pGroup->nMaxPage ){
+1 -1
View File
@@ -816,7 +816,7 @@ void sqlite3Pragma(
if( sqlite3GetBoolean(zRight, size!=0) ){
db->flags |= SQLITE_CacheSpill;
}else{
db->flags &= ~SQLITE_CacheSpill;
db->flags &= ~(u64)SQLITE_CacheSpill;
}
setAllPagerFlags(db);
}
+1 -288
View File
@@ -293,7 +293,7 @@ int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg, u32 mFlags){
** indices that the user might have created.
*/
if( iDb==0 && meta[BTREE_FILE_FORMAT-1]>=4 ){
db->flags &= ~SQLITE_LegacyFileFmt;
db->flags &= ~(u64)SQLITE_LegacyFileFmt;
}
/* Read the schema information out of the schema tables
@@ -709,293 +709,6 @@ static int sqlite3LockAndPrepare(
return rc;
}
#ifdef SQLITE_ENABLE_NORMALIZE
/*
** Checks if the specified token is a table, column, or function name,
** based on the databases associated with the statement being prepared.
** If the function fails, zero is returned and pRc is filled with the
** error code.
*/
static int shouldTreatAsIdentifier(
sqlite3 *db, /* Database handle. */
const char *zToken, /* Pointer to start of token to be checked */
int nToken, /* Length of token to be checked */
int *pRc /* Pointer to error code upon failure */
){
int bFound = 0; /* Non-zero if token is an identifier name. */
int i, j; /* Database and column loop indexes. */
Schema *pSchema; /* Schema for current database. */
Hash *pHash; /* Hash table of tables for current database. */
HashElem *e; /* Hash element for hash table iteration. */
Table *pTab; /* Database table for columns being checked. */
if( sqlite3IsRowidN(zToken, nToken) ){
return 1;
}
if( nToken>0 ){
int hash = SQLITE_FUNC_HASH(sqlite3UpperToLower[(u8)zToken[0]], nToken);
if( sqlite3FunctionSearchN(hash, zToken, nToken) ) return 1;
}
assert( db!=0 );
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
for(i=0; i<db->nDb; i++){
pHash = &db->aFunc;
if( sqlite3HashFindN(pHash, zToken, nToken) ){
bFound = 1;
break;
}
pSchema = db->aDb[i].pSchema;
if( pSchema==0 ) continue;
pHash = &pSchema->tblHash;
if( sqlite3HashFindN(pHash, zToken, nToken) ){
bFound = 1;
break;
}
for(e=sqliteHashFirst(pHash); e; e=sqliteHashNext(e)){
pTab = sqliteHashData(e);
if( pTab==0 ) continue;
pHash = pTab->pColHash;
if( pHash==0 ){
pTab->pColHash = pHash = sqlite3_malloc(sizeof(Hash));
if( pHash ){
sqlite3HashInit(pHash);
for(j=0; j<pTab->nCol; j++){
Column *pCol = &pTab->aCol[j];
sqlite3HashInsert(pHash, pCol->zName, pCol);
}
}else{
*pRc = SQLITE_NOMEM_BKPT;
bFound = 0;
goto done;
}
}
if( pHash && sqlite3HashFindN(pHash, zToken, nToken) ){
bFound = 1;
goto done;
}
}
}
done:
sqlite3BtreeLeaveAll(db);
sqlite3_mutex_leave(db->mutex);
return bFound;
}
/*
** Attempt to estimate the final output buffer size needed for the fully
** normalized version of the specified SQL string. This should take into
** account any potential expansion that could occur (e.g. via IN clauses
** being expanded, etc). This size returned is the total number of bytes
** including the NUL terminator.
*/
static int estimateNormalizedSize(
const char *zSql, /* The original SQL string */
int nSql, /* Length of original SQL string */
u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
){
int nOut = nSql + 4;
const char *z = zSql;
while( nOut<nSql*5 ){
while( z[0]!=0 && z[0]!='I' && z[0]!='i' ){ z++; }
if( z[0]==0 ) break;
z++;
if( z[0]!='N' && z[0]!='n' ) break;
z++;
while( sqlite3Isspace(z[0]) ){ z++; }
if( z[0]!='(' ) break;
z++;
nOut += 5; /* ?,?,? */
}
return nOut;
}
/*
** Copy the current token into the output buffer while dealing with quoted
** identifiers. By default, all letters will be converted into lowercase.
** If the bUpper flag is set, uppercase will be used. The piOut argument
** will be used to update the target index into the output string.
*/
static void copyNormalizedToken(
const char *zSql, /* The original SQL string */
int iIn, /* Current index into the original SQL string */
int nToken, /* Number of bytes in the current token */
int tokenFlags, /* Flags returned by the tokenizer */
char *zOut, /* The output string */
int *piOut /* Pointer to target index into the output string */
){
int bQuoted = tokenFlags & SQLITE_TOKEN_QUOTED;
int bKeyword = tokenFlags & SQLITE_TOKEN_KEYWORD;
int j = *piOut, k = 0;
for(; k<nToken; k++){
if( bQuoted ){
if( k==0 && iIn>0 ){
zOut[j++] = '"';
continue;
}else if( k==nToken-1 ){
zOut[j++] = '"';
continue;
}
}
if( bKeyword ){
zOut[j++] = sqlite3Toupper(zSql[iIn+k]);
}else{
zOut[j++] = sqlite3Tolower(zSql[iIn+k]);
}
}
*piOut = j;
}
/*
** Perform normalization of the SQL contained in the prepared statement and
** store the result in the zNormSql field. The schema for the associated
** databases are consulted while performing the normalization in order to
** determine if a token appears to be an identifier. All identifiers are
** left intact in the normalized SQL and all literals are replaced with a
** single '?'.
*/
void sqlite3Normalize(
Vdbe *pVdbe, /* VM being reprepared */
const char *zSql, /* The original SQL string */
int nSql, /* Size of the input string in bytes */
u8 prepFlags /* The flags passed to sqlite3_prepare_v3() */
){
sqlite3 *db; /* Database handle. */
char *z; /* The output string */
int nZ; /* Size of the output string in bytes */
int i; /* Next character to read from zSql[] */
int j; /* Next character to fill in on z[] */
int tokenType = 0; /* Type of the next token */
int prevTokenType = 0; /* Type of the previous token, except spaces */
int n; /* Size of the next token */
int nParen = 0; /* Nesting level of parenthesis */
Hash inHash; /* Table of parenthesis levels to output index. */
db = sqlite3VdbeDb(pVdbe);
assert( db!=0 );
assert( pVdbe->zNormSql==0 );
if( zSql==0 ) return;
nZ = estimateNormalizedSize(zSql, nSql, prepFlags);
z = sqlite3DbMallocRawNN(db, nZ);
if( z==0 ) return;
sqlite3HashInit(&inHash);
for(i=j=0; i<nSql && zSql[i]; i+=n){
int flags = 0;
if( tokenType!=TK_SPACE ) prevTokenType = tokenType;
n = sqlite3GetTokenNormalized((unsigned char*)zSql+i, &tokenType, &flags);
switch( tokenType ){
case TK_SPACE: {
break;
}
case TK_ILLEGAL: {
sqlite3DbFree(db, z);
sqlite3HashClear(&inHash);
return;
}
case TK_STRING:
case TK_INTEGER:
case TK_FLOAT:
case TK_VARIABLE:
case TK_BLOB: {
z[j++] = '?';
break;
}
case TK_LP:
case TK_RP: {
if( tokenType==TK_LP ){
nParen++;
if( prevTokenType==TK_IN ){
assert( nParen<nSql );
sqlite3HashInsert(&inHash, zSql+nParen, SQLITE_INT_TO_PTR(j));
}
}else{
int jj;
assert( nParen<nSql );
jj = SQLITE_PTR_TO_INT(sqlite3HashFind(&inHash, zSql+nParen));
if( jj>0 ){
sqlite3HashInsert(&inHash, zSql+nParen, 0);
assert( jj+6<nZ );
memcpy(z+jj+1, "?,?,?", 5);
j = jj+6;
assert( nZ-1-j>=0 );
assert( nZ-1-j<nZ );
memset(z+j, 0, nZ-1-j);
}
nParen--;
}
assert( nParen>=0 );
/* Fall through */
}
case TK_MINUS:
case TK_SEMI:
case TK_PLUS:
case TK_STAR:
case TK_SLASH:
case TK_REM:
case TK_EQ:
case TK_LE:
case TK_NE:
case TK_LSHIFT:
case TK_LT:
case TK_RSHIFT:
case TK_GT:
case TK_GE:
case TK_BITOR:
case TK_CONCAT:
case TK_COMMA:
case TK_BITAND:
case TK_BITNOT:
case TK_DOT:
case TK_IN:
case TK_IS:
case TK_NOT:
case TK_NULL:
case TK_ID: {
if( tokenType==TK_NULL ){
if( prevTokenType==TK_IS || prevTokenType==TK_NOT ){
/* NULL is a keyword in this case, not a literal value */
}else{
/* Here the NULL is a literal value */
z[j++] = '?';
break;
}
}
if( j>0 && sqlite3IsIdChar(z[j-1]) && sqlite3IsIdChar(zSql[i]) ){
z[j++] = ' ';
}
if( tokenType==TK_ID ){
int i2 = i, n2 = n, rc = SQLITE_OK;
if( nParen>0 ){
assert( nParen<nSql );
sqlite3HashInsert(&inHash, zSql+nParen, 0);
}
if( flags&SQLITE_TOKEN_QUOTED ){ i2++; n2-=2; }
if( shouldTreatAsIdentifier(db, zSql+i2, n2, &rc)==0 ){
if( rc!=SQLITE_OK ){
sqlite3DbFree(db, z);
sqlite3HashClear(&inHash);
return;
}
if( sqlite3_keyword_check(zSql+i2, n2)==0 ){
z[j++] = '?';
break;
}
}
}
copyNormalizedToken(zSql, i, n, flags, z, &j);
break;
}
}
}
assert( j<nZ && "one" );
while( j>0 && z[j-1]==' ' ){ j--; }
if( j>0 && z[j-1]!=';' ){ z[j++] = ';'; }
z[j] = 0;
assert( j<nZ && "two" );
pVdbe->zNormSql = z;
sqlite3HashClear(&inHash);
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Rerun the compilation of a statement after a schema change.
+20 -1
View File
@@ -80,7 +80,7 @@ static void resolveAlias(
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
}
ExprSetProperty(pDup, EP_Alias);
// ExprSetProperty(pDup, EP_Alias);
/* Before calling sqlite3ExprDelete(), set the EP_Static flag. This
** prevents ExprDelete() from deleting the Expr structure itself,
@@ -474,6 +474,25 @@ static int lookupName(
if( cnt==0 && zTab==0 ){
assert( pExpr->op==TK_ID );
if( ExprHasProperty(pExpr,EP_DblQuoted) ){
/* If a double-quoted identifier does not match any known column name,
** then treat it as a string.
**
** This hack was added in the early days of SQLite in a misguided attempt
** to be compatible with MySQL 3.x, which used double-quotes for strings.
** I now sorely regret putting in this hack. The effect of this hack is
** that misspelled identifier names are silently converted into strings
** rather than causing an error, to the frustration of countless
** programmers. To all those frustrated programmers, my apologies.
**
** Someday, I hope to get rid of this hack. Unfortunately there is
** a huge amount of legacy SQL that uses it. So for now, we just
** issue a warning.
*/
sqlite3_log(SQLITE_WARNING,
"double-quoted string literal: \"%w\"", zCol);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3VdbeAddDblquoteStr(db, pParse->pVdbe, zCol);
#endif
pExpr->op = TK_STRING;
pExpr->y.pTab = 0;
return WRC_Prune;
+5 -3
View File
@@ -2077,10 +2077,10 @@ void sqlite3SelectAddColumnTypeAndCollation(
Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
Table *pTab;
sqlite3 *db = pParse->db;
int savedFlags;
u64 savedFlags;
savedFlags = db->flags;
db->flags &= ~SQLITE_FullColNames;
db->flags &= ~(u64)SQLITE_FullColNames;
db->flags |= SQLITE_ShortColNames;
sqlite3SelectPrep(pParse, pSelect, 0);
if( pParse->nErr ) return 0;
@@ -3461,6 +3461,7 @@ static Expr *substExpr(
ifNullRow.iTable = pSubst->iNewTable;
pCopy = &ifNullRow;
}
testcase( ExprHasProperty(pCopy, EP_Subquery) );
pNew = sqlite3ExprDup(db, pCopy, 0);
if( pNew && pSubst->isLeftJoin ){
ExprSetProperty(pNew, EP_CanBeNull);
@@ -4025,7 +4026,8 @@ static int flattenSubquery(
pParent->pOrderBy = pOrderBy;
pSub->pOrderBy = 0;
}
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isLeftJoin>0 ){
setJoinExpr(pWhere, iNewParent);
}
+223 -28
View File
@@ -1007,6 +1007,7 @@ struct ShellState {
u8 openMode; /* SHELL_OPEN_NORMAL, _APPENDVFS, or _ZIPFILE */
u8 doXdgOpen; /* Invoke start/open/xdg-open in output_reset() */
u8 nEqpLevel; /* Depth of the EQP output graph */
u8 eTraceType; /* SHELL_TRACE_* value for type of trace */
unsigned mEqpLines; /* Mask of veritical lines in the EQP output graph */
int outCount; /* Revert to stdout when reaching zero */
int cnt; /* Number of records displayed so far */
@@ -1065,6 +1066,13 @@ struct ShellState {
#define SHELL_OPEN_ZIPFILE 3 /* Use the zipfile virtual table */
#define SHELL_OPEN_READONLY 4 /* Open a normal database read-only */
#define SHELL_OPEN_DESERIALIZE 5 /* Open using sqlite3_deserialize() */
#define SHELL_OPEN_HEXDB 6 /* Use "dbtotxt" output as data source */
/* Allowed values for ShellState.eTraceType
*/
#define SHELL_TRACE_PLAIN 0 /* Show input SQL text */
#define SHELL_TRACE_EXPANDED 1 /* Show expanded SQL text */
#define SHELL_TRACE_NORMALIZED 2 /* Show normalized SQL text */
/*
** These are the allowed shellFlgs values
@@ -3370,6 +3378,7 @@ static const char *(azHelp[]) = {
#endif
".backup ?DB? FILE Backup DB (default \"main\") to FILE",
" --append Use the appendvfs",
" --async Write to FILE without a journal and without fsync()",
".bail on|off Stop after hitting an error. Default OFF",
".binary on|off Turn binary output on or off. Default OFF",
".cd DIRECTORY Change the working directory to DIRECTORY",
@@ -3436,6 +3445,7 @@ static const char *(azHelp[]) = {
" --append Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
" --deserialize Load into memory useing sqlite3_deserialize()",
" --hexdb Load the output of \"dbtotxt\" as an in-memory database",
#endif
" --new Initialize FILE to an empty database",
" --readonly Open FILE readonly",
@@ -3492,7 +3502,22 @@ static const char *(azHelp[]) = {
".testcase NAME Begin redirecting output to 'testcase-out.txt'",
".timeout MS Try opening locked tables for MS milliseconds",
".timer on|off Turn SQL timer on or off",
".trace FILE|off Output each SQL statement as it is run",
#ifndef SQLITE_OMIT_TRACE
".trace ?OPTIONS? Output each SQL statement as it is run",
" FILE Send output to FILE",
" stdout Send output to stdout",
" stderr Send output to stderr",
" off Disable tracing",
" --expanded Expand query parameters",
#ifdef SQLITE_ENABLE_NORMALIZE
" --normalized Normal the SQL statements",
#endif
" --plain Show SQL as it is input",
" --stmt Trace statement execution (SQLITE_TRACE_STMT)",
" --profile Profile statements (SQLITE_TRACE_PROFILE)",
" --row Trace each row (SQLITE_TRACE_ROW)",
" --close Trace connection close (SQLITE_TRACE_CLOSE)",
#endif /* SQLITE_OMIT_TRACE */
".vfsinfo ?AUX? Information about the top-level VFS",
".vfslist List all available VFSes",
".vfsname ?AUX? Print the name of the VFS stack",
@@ -3700,6 +3725,87 @@ int deduceDatabaseType(const char *zName, int dfltZip){
return rc;
}
#ifdef SQLITE_ENABLE_DESERIALIZE
/*
** Reconstruct an in-memory database using the output from the "dbtotxt"
** program. Read content from the file in p->zDbFilename. If p->zDbFilename
** is 0, then read from standard input.
*/
static unsigned char *readHexDb(ShellState *p, int *pnData){
unsigned char *a = 0;
int nLine = 1;
int n = 0;
int pgsz = 0;
int iOffset = 0;
int j, k;
int rc;
FILE *in;
unsigned char x[16];
char zLine[100];
if( p->zDbFilename ){
in = fopen(p->zDbFilename, "r");
if( in==0 ){
utf8_printf(stderr, "cannot open \"%s\" for reading\n", p->zDbFilename);
return 0;
}
}else{
in = stdin;
}
*pnData = 0;
if( fgets(zLine, sizeof(zLine), in)==0 ) goto readHexDb_error;
rc = sscanf(zLine, "| size %d pagesize %d", &n, &pgsz);
if( rc!=2 ) goto readHexDb_error;
if( n<=0 ) goto readHexDb_error;
a = sqlite3_malloc( n );
if( a==0 ){
utf8_printf(stderr, "Out of memory!\n");
goto readHexDb_error;
}
memset(a, 0, n);
if( pgsz<512 || pgsz>65536 || (pgsz & (pgsz-1))!=0 ){
utf8_printf(stderr, "invalid pagesize\n");
goto readHexDb_error;
}
for(nLine=2; fgets(zLine, sizeof(zLine), in)!=0; nLine++){
rc = sscanf(zLine, "| page %d offset %d", &j, &k);
if( rc==2 ){
iOffset = k;
continue;
}
if( strncmp(zLine, "| end ", 6)==0 ){
break;
}
rc = sscanf(zLine,"| %d: %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx"
" %hhx %hhx %hhx %hhx %hhx %hhx %hhx %hhx",
&j, &x[0], &x[1], &x[2], &x[3], &x[4], &x[5], &x[6], &x[7],
&x[8], &x[9], &x[10], &x[11], &x[12], &x[13], &x[14], &x[15]);
if( rc==17 ){
k = iOffset+j;
if( k+16>n ){
utf8_printf(stderr, "continue exceeds file size\n");
goto readHexDb_error;
}
memcpy(a+k, x, 16);
}
}
*pnData = n;
if( in!=stdin ) fclose(in);
return a;
readHexDb_error:
if( in!=stdin ){
fclose(in);
}else{
while( fgets(zLine, sizeof(zLine), in)!=0 ){
if(strncmp(zLine, "| end ", 6)==0 ) break;
}
}
sqlite3_free(a);
utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine);
return 0;
}
#endif /* SQLITE_ENABLE_DESERIALIZE */
/* Flags for open_db().
**
** The default behavior of open_db() is to exit(1) if the database fails to
@@ -3733,6 +3839,7 @@ static void open_db(ShellState *p, int openFlags){
SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "apndvfs");
break;
}
case SHELL_OPEN_HEXDB:
case SHELL_OPEN_DESERIALIZE: {
sqlite3_open(0, &p->db);
break;
@@ -3787,9 +3894,19 @@ static void open_db(ShellState *p, int openFlags){
sqlite3_free(zSql);
}
#ifdef SQLITE_ENABLE_DESERIALIZE
else if( p->openMode==SHELL_OPEN_DESERIALIZE ){
else
if( p->openMode==SHELL_OPEN_DESERIALIZE || p->openMode==SHELL_OPEN_HEXDB ){
int nData = 0;
unsigned char *aData = (unsigned char*)readFile(p->zDbFilename, &nData);
unsigned char *aData;
if( p->openMode==SHELL_OPEN_DESERIALIZE ){
aData = (unsigned char*)readFile(p->zDbFilename, &nData);
}else{
aData = readHexDb(p, &nData);
if( aData==0 ){
utf8_printf(stderr, "Error in hexdb input\n");
return;
}
}
int rc = sqlite3_deserialize(p->db, "main", aData, nData, nData,
SQLITE_DESERIALIZE_RESIZEABLE |
SQLITE_DESERIALIZE_FREEONCLOSE);
@@ -3999,24 +4116,60 @@ static FILE *output_file_open(const char *zFile, int bTextMode){
return f;
}
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
#ifndef SQLITE_OMIT_TRACE
/*
** A routine for handling output from sqlite3_trace().
*/
static int sql_trace_callback(
unsigned mType,
void *pArg,
void *pP,
void *pX
unsigned mType, /* The trace type */
void *pArg, /* The ShellState pointer */
void *pP, /* Usually a pointer to sqlite_stmt */
void *pX /* Auxiliary output */
){
FILE *f = (FILE*)pArg;
UNUSED_PARAMETER(mType);
UNUSED_PARAMETER(pP);
if( f ){
const char *z = (const char*)pX;
int i = strlen30(z);
while( i>0 && z[i-1]==';' ){ i--; }
utf8_printf(f, "%.*s;\n", i, z);
ShellState *p = (ShellState*)pArg;
sqlite3_stmt *pStmt;
const char *zSql;
int nSql;
if( p->traceOut==0 ) return 0;
if( mType==SQLITE_TRACE_CLOSE ){
utf8_printf(p->traceOut, "-- closing database connection\n");
return 0;
}
if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){
zSql = (const char*)pX;
}else{
pStmt = (sqlite3_stmt*)pP;
switch( p->eTraceType ){
case SHELL_TRACE_EXPANDED: {
zSql = sqlite3_expanded_sql(pStmt);
break;
}
#ifdef SQLITE_ENABLE_NORMALIZE
case SHELL_TRACE_NORMALIZED: {
zSql = sqlite3_normalized_sql(pStmt);
break;
}
#endif
default: {
zSql = sqlite3_sql(pStmt);
break;
}
}
}
if( zSql==0 ) return 0;
nSql = strlen30(zSql);
while( nSql>0 && zSql[nSql-1]==';' ){ nSql--; }
switch( mType ){
case SQLITE_TRACE_ROW:
case SQLITE_TRACE_STMT: {
utf8_printf(p->traceOut, "%.*s;\n", nSql, zSql);
break;
}
case SQLITE_TRACE_PROFILE: {
sqlite3_int64 nNanosec = *(sqlite3_int64*)pX;
utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", nSql, zSql, nNanosec);
break;
}
}
return 0;
}
@@ -5782,6 +5935,7 @@ static int do_meta_command(char *zLine, ShellState *p){
sqlite3 *pDest;
sqlite3_backup *pBackup;
int j;
int bAsync = 0;
const char *zVfs = 0;
for(j=1; j<nArg; j++){
const char *z = azArg[j];
@@ -5790,6 +5944,9 @@ static int do_meta_command(char *zLine, ShellState *p){
if( strcmp(z, "-append")==0 ){
zVfs = "apndvfs";
}else
if( strcmp(z, "-async")==0 ){
bAsync = 1;
}else
{
utf8_printf(stderr, "unknown option: %s\n", azArg[j]);
return 1;
@@ -5800,7 +5957,7 @@ static int do_meta_command(char *zLine, ShellState *p){
zDb = zDestFile;
zDestFile = azArg[j];
}else{
raw_printf(stderr, "Usage: .backup ?DB? ?--append? FILENAME\n");
raw_printf(stderr, "Usage: .backup ?DB? ?OPTIONS? FILENAME\n");
return 1;
}
}
@@ -5816,6 +5973,10 @@ static int do_meta_command(char *zLine, ShellState *p){
close_db(pDest);
return 1;
}
if( bAsync ){
sqlite3_exec(pDest, "PRAGMA synchronous=OFF; PRAGMA journal_mode=OFF;",
0, 0, 0);
}
open_db(p, 0);
pBackup = sqlite3_backup_init(pDest, "main", p->db, zDb);
if( pBackup==0 ){
@@ -6682,7 +6843,9 @@ static int do_meta_command(char *zLine, ShellState *p){
#ifdef SQLITE_ENABLE_DESERIALIZE
}else if( optionMatch(z, "deserialize") ){
p->openMode = SHELL_OPEN_DESERIALIZE;
#endif
}else if( optionMatch(z, "hexdb") ){
p->openMode = SHELL_OPEN_HEXDB;
#endif /* SQLITE_ENABLE_DESERIALIZE */
}else if( z[0]=='-' ){
utf8_printf(stderr, "unknown option: %s\n", z);
rc = 1;
@@ -6691,7 +6854,7 @@ static int do_meta_command(char *zLine, ShellState *p){
}
/* If a filename is specified, try to open it first */
zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
if( zNewFilename ){
if( zNewFilename || p->openMode==SHELL_OPEN_HEXDB ){
if( newFlag ) shellDeleteFile(zNewFilename);
p->zDbFilename = zNewFilename;
open_db(p, OPEN_DB_KEEPALIVE);
@@ -7838,23 +8001,55 @@ static int do_meta_command(char *zLine, ShellState *p){
}
}else
#ifndef SQLITE_OMIT_TRACE
if( c=='t' && strncmp(azArg[0], "trace", n)==0 ){
int mType = 0;
int jj;
open_db(p, 0);
if( nArg!=2 ){
raw_printf(stderr, "Usage: .trace FILE|off\n");
rc = 1;
goto meta_command_exit;
for(jj=1; jj<nArg; jj++){
const char *z = azArg[jj];
if( z[0]=='-' ){
if( optionMatch(z, "expanded") ){
p->eTraceType = SHELL_TRACE_EXPANDED;
}
#ifdef SQLITE_ENABLE_NORMALIZE
else if( optionMatch(z, "normalized") ){
p->eTraceType = SHELL_TRACE_NORMALIZED;
}
#endif
else if( optionMatch(z, "plain") ){
p->eTraceType = SHELL_TRACE_PLAIN;
}
else if( optionMatch(z, "profile") ){
mType |= SQLITE_TRACE_PROFILE;
}
else if( optionMatch(z, "row") ){
mType |= SQLITE_TRACE_ROW;
}
else if( optionMatch(z, "stmt") ){
mType |= SQLITE_TRACE_STMT;
}
else if( optionMatch(z, "close") ){
mType |= SQLITE_TRACE_CLOSE;
}
else {
raw_printf(stderr, "Unknown option \"%s\" on \".trace\"\n", z);
rc = 1;
goto meta_command_exit;
}
}else{
output_file_close(p->traceOut);
p->traceOut = output_file_open(azArg[1], 0);
}
}
output_file_close(p->traceOut);
p->traceOut = output_file_open(azArg[1], 0);
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
if( p->traceOut==0 ){
sqlite3_trace_v2(p->db, 0, 0, 0);
}else{
sqlite3_trace_v2(p->db, SQLITE_TRACE_STMT, sql_trace_callback,p->traceOut);
if( mType==0 ) mType = SQLITE_TRACE_STMT;
sqlite3_trace_v2(p->db, mType, sql_trace_callback, p);
}
#endif
}else
#endif /* !defined(SQLITE_OMIT_TRACE) */
#if SQLITE_USER_AUTHENTICATION
if( c=='u' && strncmp(azArg[0], "user", n)==0 ){
+10 -11
View File
@@ -2991,9 +2991,9 @@ int sqlite3_set_authorizer(
** time is in units of nanoseconds, however the current implementation
** is only capable of millisecond resolution so the six least significant
** digits in the time are meaningless. Future versions of SQLite
** might provide greater resolution on the profiler callback. The
** sqlite3_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
** might provide greater resolution on the profiler callback. Invoking
** either [sqlite3_trace()] or [sqlite3_trace_v2()] will cancel the
** profile callback.
*/
SQLITE_DEPRECATED void *sqlite3_trace(sqlite3*,
void(*xTrace)(void*,const char*), void*);
@@ -3629,14 +3629,13 @@ int sqlite3_limit(sqlite3*, int id, int newVal);
** deplete the limited store of lookaside memory. Future versions of
** SQLite may act on this hint differently.
**
** [[SQLITE_PREPARE_NORMALIZE]] ^(<dt>SQLITE_PREPARE_NORMALIZE</dt>
** <dd>The SQLITE_PREPARE_NORMALIZE flag indicates that a normalized
** representation of the SQL statement should be calculated and then
** associated with the prepared statement, which can be obtained via
** the [sqlite3_normalized_sql()] interface.)^ The semantics used to
** normalize a SQL statement are unspecified and subject to change.
** At a minimum, literal values will be replaced with suitable
** placeholders.
** [[SQLITE_PREPARE_NORMALIZE]] <dt>SQLITE_PREPARE_NORMALIZE</dt>
** <dd>The SQLITE_PREPARE_NORMALIZE flag is a no-op. This flag used
** to be required for any prepared statement that wanted to use the
** [sqlite3_normalized_sql()] interface. However, the
** [sqlite3_normalized_sql()] interface is now available to all
** prepared statements, regardless of whether or not they use this
** flag.
** </dl>
*/
#define SQLITE_PREPARE_PERSISTENT 0x01
+11 -17
View File
@@ -1356,10 +1356,13 @@ void sqlite3CryptFunc(sqlite3_context*,int,sqlite3_value**);
/* This is an extra SQLITE_TRACE macro that indicates "legacy" tracing
** in the style of sqlite3_trace()
*/
#define SQLITE_TRACE_LEGACY 0x80
#define SQLITE_TRACE_LEGACY 0x40 /* Use the legacy xTrace */
#define SQLITE_TRACE_XPROFILE 0x80 /* Use the legacy xProfile */
#else
#define SQLITE_TRACE_LEGACY 0
#define SQLITE_TRACE_LEGACY 0
#define SQLITE_TRACE_XPROFILE 0
#endif /* SQLITE_OMIT_DEPRECATED */
#define SQLITE_TRACE_NONLEGACY_MASK 0x0f /* Normal flags */
/*
@@ -1418,8 +1421,10 @@ struct sqlite3 {
void **aExtension; /* Array of shared library handles */
int (*xTrace)(u32,void*,void*,void*); /* Trace function */
void *pTraceArg; /* Argument to the trace function */
#ifndef SQLITE_OMIT_DEPRECATED
void (*xProfile)(void*,const char*,u64); /* Profiling function */
void *pProfileArg; /* Argument to profile function */
#endif
void *pCommitArg; /* Argument to xCommitCallback() */
int (*xCommitCallback)(void*); /* Invoked at every commit. */
void *pRollbackArg; /* Argument to xRollbackCallback() */
@@ -1952,9 +1957,6 @@ struct VTable {
struct Table {
char *zName; /* Name of the table or view */
Column *aCol; /* Information about each column */
#ifdef SQLITE_ENABLE_NORMALIZE
Hash *pColHash; /* All columns indexed by name */
#endif
Index *pIndex; /* List of SQL indexes on this table. */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
FKey *pFKey; /* Linked list of all foreign keys in this table */
@@ -3983,8 +3985,8 @@ Table *sqlite3LocateTableItem(Parse*,u32 flags,struct SrcList_item *);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);
void sqlite3UnlinkAndDeleteTable(sqlite3*,int,const char*);
void sqlite3UnlinkAndDeleteIndex(sqlite3*,int,const char*);
void sqlite3Vacuum(Parse*,Token*);
int sqlite3RunVacuum(char**, sqlite3*, int);
void sqlite3Vacuum(Parse*,Token*,Expr*);
int sqlite3RunVacuum(char**, sqlite3*, int, sqlite3_value*);
char *sqlite3NameFromToken(sqlite3*, Token*);
int sqlite3ExprCompare(Parse*,Expr*, Expr*, int);
int sqlite3ExprCompareSkip(Expr*, Expr*, int);
@@ -4022,9 +4024,6 @@ int sqlite3ExprIsInteger(Expr*, int*);
int sqlite3ExprCanBeNull(const Expr*);
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
int sqlite3IsRowid(const char*);
#ifdef SQLITE_ENABLE_NORMALIZE
int sqlite3IsRowidN(const char*, int);
#endif
void sqlite3GenerateRowDelete(
Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int);
@@ -4051,9 +4050,7 @@ ExprList *sqlite3ExprListDup(sqlite3*,ExprList*,int);
SrcList *sqlite3SrcListDup(sqlite3*,SrcList*,int);
IdList *sqlite3IdListDup(sqlite3*,IdList*);
Select *sqlite3SelectDup(sqlite3*,Select*,int);
#ifdef SQLITE_ENABLE_NORMALIZE
FuncDef *sqlite3FunctionSearchN(int,const char*,int);
#endif
FuncDef *sqlite3FunctionSearch(int,const char*);
void sqlite3InsertBuiltinFuncs(FuncDef*,int);
FuncDef *sqlite3FindFunction(sqlite3*,const char*,int,u8,u8);
void sqlite3RegisterBuiltinFunctions(void);
@@ -4258,9 +4255,6 @@ void sqlite3AlterFunctions(void);
void sqlite3AlterRenameTable(Parse*, SrcList*, Token*);
void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
int sqlite3GetToken(const unsigned char *, int *);
#ifdef SQLITE_ENABLE_NORMALIZE
int sqlite3GetTokenNormalized(const unsigned char *, int *, int *);
#endif
void sqlite3NestedParse(Parse*, const char*, ...);
void sqlite3ExpirePreparedStatements(sqlite3*, int);
int sqlite3CodeSubselect(Parse*, Expr *, int, int);
@@ -4419,7 +4413,7 @@ int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
#ifdef SQLITE_ENABLE_NORMALIZE
void sqlite3Normalize(Vdbe*, const char*, int, u8);
char *sqlite3Normalize(Vdbe*, const char*);
#endif
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
+135 -67
View File
@@ -545,73 +545,6 @@ int sqlite3GetToken(const unsigned char *z, int *tokenType){
return i;
}
#ifdef SQLITE_ENABLE_NORMALIZE
/*
** Return the length (in bytes) of the token that begins at z[0].
** Store the token type in *tokenType before returning. If flags has
** SQLITE_TOKEN_NORMALIZE flag enabled, use the identifier token type
** for keywords. Add SQLITE_TOKEN_QUOTED to flags if the token was
** actually a quoted identifier. Add SQLITE_TOKEN_KEYWORD to flags
** if the token was recognized as a keyword; this is useful when the
** SQLITE_TOKEN_NORMALIZE flag is used, because it enables the caller
** to differentiate between a keyword being treated as an identifier
** (for normalization purposes) and an actual identifier.
*/
int sqlite3GetTokenNormalized(
const unsigned char *z,
int *tokenType,
int *flags
){
int n;
unsigned char iClass = aiClass[*z];
if( iClass==CC_KYWD ){
int i;
for(i=1; aiClass[z[i]]<=CC_KYWD; i++){}
if( IdChar(z[i]) ){
/* This token started out using characters that can appear in keywords,
** but z[i] is a character not allowed within keywords, so this must
** be an identifier instead */
i++;
while( IdChar(z[i]) ){ i++; }
*tokenType = TK_ID;
return i;
}
*tokenType = TK_ID;
n = keywordCode((char*)z, i, tokenType);
/* If the token is no longer considered to be an identifier, then it is a
** keyword of some kind. Make the token back into an identifier and then
** set the SQLITE_TOKEN_KEYWORD flag. Several non-identifier tokens are
** used verbatim, including IN, IS, NOT, and NULL. */
switch( *tokenType ){
case TK_ID: {
/* do nothing, handled by caller */
break;
}
case TK_IN:
case TK_IS:
case TK_NOT:
case TK_NULL: {
*flags |= SQLITE_TOKEN_KEYWORD;
break;
}
default: {
*tokenType = TK_ID;
*flags |= SQLITE_TOKEN_KEYWORD;
break;
}
}
}else{
n = sqlite3GetToken(z, tokenType);
/* If the token is considered to be an identifier and the character class
** of the first character is a quote, set the SQLITE_TOKEN_QUOTED flag. */
if( *tokenType==TK_ID && (iClass==CC_QUOTE || iClass==CC_QUOTE2) ){
*flags |= SQLITE_TOKEN_QUOTED;
}
}
return n;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
/*
** Run the parser on the given SQL string. The parser structure is
** passed in. An SQLITE_ status code is returned. If an error occurs
@@ -781,3 +714,138 @@ int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){
assert( nErr==0 || pParse->rc!=SQLITE_OK );
return nErr;
}
#ifdef SQLITE_ENABLE_NORMALIZE
/*
** Insert a single space character into pStr if the current string
** ends with an identifier
*/
static void addSpaceSeparator(sqlite3_str *pStr){
if( pStr->nChar && sqlite3IsIdChar(pStr->zText[pStr->nChar-1]) ){
sqlite3_str_append(pStr, " ", 1);
}
}
/*
** Compute a normalization of the SQL given by zSql[0..nSql-1]. Return
** the normalization in space obtained from sqlite3DbMalloc(). Or return
** NULL if anything goes wrong or if zSql is NULL.
*/
char *sqlite3Normalize(
Vdbe *pVdbe, /* VM being reprepared */
const char *zSql /* The original SQL string */
){
sqlite3 *db; /* The database connection */
int i; /* Next unread byte of zSql[] */
int n; /* length of current token */
int tokenType; /* type of current token */
int prevType; /* Previous non-whitespace token */
int nParen; /* Number of nested levels of parentheses */
int iStartIN; /* Start of RHS of IN operator in z[] */
int nParenAtIN; /* Value of nParent at start of RHS of IN operator */
int j; /* Bytes of normalized SQL generated so far */
sqlite3_str *pStr; /* The normalized SQL string under construction */
db = sqlite3VdbeDb(pVdbe);
tokenType = -1;
nParen = iStartIN = nParenAtIN = 0;
pStr = sqlite3_str_new(db);
assert( pStr!=0 ); /* sqlite3_str_new() never returns NULL */
for(i=0; zSql[i] && pStr->accError==0; i+=n){
if( tokenType!=TK_SPACE ){
prevType = tokenType;
}
n = sqlite3GetToken((unsigned char*)zSql+i, &tokenType);
if( NEVER(n<=0) ) break;
switch( tokenType ){
case TK_SPACE: {
break;
}
case TK_NULL: {
if( prevType==TK_IS || prevType==TK_NOT ){
sqlite3_str_append(pStr, " NULL", 5);
break;
}
/* Fall through */
}
case TK_STRING:
case TK_INTEGER:
case TK_FLOAT:
case TK_VARIABLE:
case TK_BLOB: {
sqlite3_str_append(pStr, "?", 1);
break;
}
case TK_LP: {
nParen++;
if( prevType==TK_IN ){
iStartIN = pStr->nChar;
nParenAtIN = nParen;
}
sqlite3_str_append(pStr, "(", 1);
break;
}
case TK_RP: {
if( iStartIN>0 && nParen==nParenAtIN ){
assert( pStr->nChar>=iStartIN );
pStr->nChar = iStartIN+1;
sqlite3_str_append(pStr, "?,?,?", 5);
iStartIN = 0;
}
nParen--;
sqlite3_str_append(pStr, ")", 1);
break;
}
case TK_ID: {
iStartIN = 0;
j = pStr->nChar;
if( sqlite3Isquote(zSql[i]) ){
char *zId = sqlite3DbStrNDup(db, zSql+i, n);
int nId;
int eType = 0;
if( zId==0 ) break;
sqlite3Dequote(zId);
if( zSql[i]=='"' && sqlite3VdbeUsesDoubleQuotedString(pVdbe, zId) ){
sqlite3_str_append(pStr, "?", 1);
sqlite3DbFree(db, zId);
break;
}
nId = sqlite3Strlen30(zId);
if( sqlite3GetToken((u8*)zId, &eType)==nId && eType==TK_ID ){
addSpaceSeparator(pStr);
sqlite3_str_append(pStr, zId, nId);
}else{
sqlite3_str_appendf(pStr, "\"%w\"", zId);
}
sqlite3DbFree(db, zId);
}else{
addSpaceSeparator(pStr);
sqlite3_str_append(pStr, zSql+i, n);
}
while( j<pStr->nChar ){
pStr->zText[j] = sqlite3Tolower(pStr->zText[j]);
j++;
}
break;
}
case TK_SELECT: {
iStartIN = 0;
/* fall through */
}
default: {
if( sqlite3IsIdChar(zSql[i]) ) addSpaceSeparator(pStr);
j = pStr->nChar;
sqlite3_str_append(pStr, zSql+i, n);
while( j<pStr->nChar ){
pStr->zText[j] = sqlite3Toupper(pStr->zText[j]);
j++;
}
break;
}
}
}
if( tokenType!=TK_SEMI ) sqlite3_str_append(pStr, ";", 1);
return sqlite3_str_finish(pStr);
}
#endif /* SQLITE_ENABLE_NORMALIZE */
+51 -21
View File
@@ -102,16 +102,16 @@ static int execSqlF(sqlite3 *db, char **pzErrMsg, const char *zSql, ...){
** transient would cause the database file to appear to be deleted
** following reboot.
*/
void sqlite3Vacuum(Parse *pParse, Token *pNm){
void sqlite3Vacuum(Parse *pParse, Token *pNm, Expr *pInto){
Vdbe *v = sqlite3GetVdbe(pParse);
int iDb = 0;
if( v==0 ) return;
if( v==0 ) goto build_vacuum_end;
if( pNm ){
#ifndef SQLITE_BUG_COMPATIBLE_20160819
/* Default behavior: Report an error if the argument to VACUUM is
** not recognized */
iDb = sqlite3TwoPartName(pParse, pNm, pNm, &pNm);
if( iDb<0 ) return;
if( iDb<0 ) goto build_vacuum_end;
#else
/* When SQLITE_BUG_COMPATIBLE_20160819 is defined, unrecognized arguments
** to VACUUM are silently ignored. This is a back-out of a bug fix that
@@ -123,21 +123,33 @@ void sqlite3Vacuum(Parse *pParse, Token *pNm){
#endif
}
if( iDb!=1 ){
sqlite3VdbeAddOp1(v, OP_Vacuum, iDb);
int iIntoReg = 0;
if( pInto ){
iIntoReg = ++pParse->nMem;
sqlite3ExprCode(pParse, pInto, iIntoReg);
}
sqlite3VdbeAddOp2(v, OP_Vacuum, iDb, iIntoReg);
sqlite3VdbeUsesBtree(v, iDb);
}
build_vacuum_end:
sqlite3ExprDelete(pParse->db, pInto);
return;
}
/*
** This routine implements the OP_Vacuum opcode of the VDBE.
*/
int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
int sqlite3RunVacuum(
char **pzErrMsg, /* Write error message here */
sqlite3 *db, /* Database connection */
int iDb, /* Which attached DB to vacuum */
sqlite3_value *pOut /* Write results here, if not NULL */
){
int rc = SQLITE_OK; /* Return code from service routines */
Btree *pMain; /* The database being vacuumed */
Btree *pTemp; /* The temporary database we vacuum into */
u16 saved_mDbFlags; /* Saved value of db->mDbFlags */
u32 saved_flags; /* Saved value of db->flags */
u32 saved_mDbFlags; /* Saved value of db->mDbFlags */
u64 saved_flags; /* Saved value of db->flags */
int saved_nChange; /* Saved value of db->nChange */
int saved_nTotalChange; /* Saved value of db->nTotalChange */
u8 saved_mTrace; /* Saved trace settings */
@@ -146,6 +158,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
int nRes; /* Bytes of reserved space at the end of each page */
int nDb; /* Number of attached databases */
const char *zDbMain; /* Schema name of database to vacuum */
const char *zOut; /* Name of output file */
if( !db->autoCommit ){
sqlite3SetString(pzErrMsg, db, "cannot VACUUM from within a transaction");
@@ -155,6 +168,15 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
sqlite3SetString(pzErrMsg, db,"cannot VACUUM - SQL statements in progress");
return SQLITE_ERROR;
}
if( pOut ){
if( sqlite3_value_type(pOut)!=SQLITE_TEXT ){
sqlite3SetString(pzErrMsg, db, "non-text filename");
return SQLITE_ERROR;
}
zOut = (const char*)sqlite3_value_text(pOut);
}else{
zOut = "";
}
/* Save the current value of the database flags so that it can be
** restored before returning. Then set the writable-schema flag, and
@@ -166,7 +188,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
saved_mTrace = db->mTrace;
db->flags |= SQLITE_WriteSchema | SQLITE_IgnoreChecks;
db->mDbFlags |= DBFLAG_PreferBuiltin | DBFLAG_Vacuum;
db->flags &= ~(SQLITE_ForeignKeys | SQLITE_ReverseOrder
db->flags &= ~(u64)(SQLITE_ForeignKeys | SQLITE_ReverseOrder
| SQLITE_Defensive | SQLITE_CountRows);
db->mTrace = 0;
@@ -189,19 +211,21 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
** to write the journal header file.
*/
nDb = db->nDb;
rc = execSql(db, pzErrMsg, "ATTACH''AS vacuum_db");
rc = execSqlF(db, pzErrMsg, "ATTACH %Q AS vacuum_db", zOut);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
assert( (db->nDb-1)==nDb );
pDb = &db->aDb[nDb];
assert( strcmp(pDb->zDbSName,"vacuum_db")==0 );
pTemp = pDb->pBt;
/* The call to execSql() to attach the temp database has left the file
** locked (as there was more than one active statement when the transaction
** to read the schema was concluded. Unlock it here so that this doesn't
** cause problems for the call to BtreeSetPageSize() below. */
sqlite3BtreeCommit(pTemp);
if( pOut ){
sqlite3_file *id = sqlite3PagerFile(sqlite3BtreePager(pTemp));
i64 sz = 0;
if( id->pMethods!=0 && (sqlite3OsFileSize(id, &sz)!=SQLITE_OK || sz>0) ){
rc = SQLITE_ERROR;
sqlite3SetString(pzErrMsg, db, "output file already exists");
goto end_of_vacuum;
}
}
nRes = sqlite3BtreeGetOptimalReserve(pMain);
/* A VACUUM cannot change the pagesize of an encrypted database. */
@@ -225,7 +249,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
*/
rc = execSql(db, pzErrMsg, "BEGIN");
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeBeginTrans(pMain, 2, 0);
rc = sqlite3BtreeBeginTrans(pMain, pOut==0 ? 2 : 0, 0);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Do not attempt to change the page size for a WAL database */
@@ -320,7 +344,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
};
assert( 1==sqlite3BtreeIsInTrans(pTemp) );
assert( 1==sqlite3BtreeIsInTrans(pMain) );
assert( pOut!=0 || 1==sqlite3BtreeIsInTrans(pMain) );
/* Copy Btree meta values */
for(i=0; i<ArraySize(aCopy); i+=2){
@@ -331,17 +355,23 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db, int iDb){
if( NEVER(rc!=SQLITE_OK) ) goto end_of_vacuum;
}
rc = sqlite3BtreeCopyFile(pMain, pTemp);
if( pOut==0 ){
rc = sqlite3BtreeCopyFile(pMain, pTemp);
}
if( rc!=SQLITE_OK ) goto end_of_vacuum;
rc = sqlite3BtreeCommit(pTemp);
if( rc!=SQLITE_OK ) goto end_of_vacuum;
#ifndef SQLITE_OMIT_AUTOVACUUM
sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
if( pOut==0 ){
sqlite3BtreeSetAutoVacuum(pMain, sqlite3BtreeGetAutoVacuum(pTemp));
}
#endif
}
assert( rc==SQLITE_OK );
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
if( pOut==0 ){
rc = sqlite3BtreeSetPageSize(pMain, sqlite3BtreeGetPageSize(pTemp), nRes,1);
}
end_of_vacuum:
/* Restore the original value of db->flags */
+8 -3
View File
@@ -6684,14 +6684,19 @@ case OP_JournalMode: { /* out2 */
#endif /* SQLITE_OMIT_PRAGMA */
#if !defined(SQLITE_OMIT_VACUUM) && !defined(SQLITE_OMIT_ATTACH)
/* Opcode: Vacuum P1 * * * *
/* Opcode: Vacuum P1 P2 * * *
**
** Vacuum the entire database P1. P1 is 0 for "main", and 2 or more
** for an attached database. The "temp" database may not be vacuumed.
**
** If P2 is not zero, then it is a register holding a string which is
** the file into which the result of vacuum should be written. When
** P2 is zero, the vacuum overwrites the original database.
*/
case OP_Vacuum: {
assert( p->readOnly==0 );
rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1);
rc = sqlite3RunVacuum(&p->zErrMsg, db, pOp->p1,
pOp->p2 ? &aMem[pOp->p2] : 0);
if( rc ) goto abort_due_to_error;
break;
}
@@ -7086,7 +7091,7 @@ case OP_VRename: {
rc = sqlite3VdbeChangeEncoding(pName, SQLITE_UTF8);
if( rc ) goto abort_due_to_error;
rc = pVtab->pModule->xRename(pVtab, pName->z);
if( isLegacy==0 ) db->flags &= ~SQLITE_LegacyAlter;
if( isLegacy==0 ) db->flags &= ~(u64)SQLITE_LegacyAlter;
sqlite3VtabImportErrmsg(p, pVtab);
p->expired = 0;
if( rc ) goto abort_due_to_error;
+4
View File
@@ -251,6 +251,10 @@ void sqlite3VdbeCountChanges(Vdbe*);
sqlite3 *sqlite3VdbeDb(Vdbe*);
u8 sqlite3VdbePrepareFlags(Vdbe*);
void sqlite3VdbeSetSql(Vdbe*, const char *z, int n, u8);
#ifdef SQLITE_ENABLE_NORMALIZE
void sqlite3VdbeAddDblquoteStr(sqlite3*,Vdbe*,const char*);
int sqlite3VdbeUsesDoubleQuotedString(Vdbe*,const char*);
#endif
void sqlite3VdbeSwap(Vdbe*,Vdbe*);
VdbeOp *sqlite3VdbeTakeOpArray(Vdbe*, int*, int*);
sqlite3_value *sqlite3VdbeGetBoundValue(Vdbe*, int, u8);
+18 -1
View File
@@ -335,6 +335,9 @@ struct sqlite3_context {
*/
typedef unsigned bft; /* Bit Field Type */
/* The ScanStatus object holds a single value for the
** sqlite3_stmt_scanstatus() interface.
*/
typedef struct ScanStatus ScanStatus;
struct ScanStatus {
int addrExplain; /* OP_Explain for loop */
@@ -345,6 +348,19 @@ struct ScanStatus {
char *zName; /* Name of table or index */
};
/* The DblquoteStr object holds the text of a double-quoted
** string for a prepared statement. A linked list of these objects
** is constructed during statement parsing and is held on Vdbe.pDblStr.
** When computing a normalized SQL statement for an SQL statement, that
** list is consulted for each double-quoted identifier to see if the
** identifier should really be a string literal.
*/
typedef struct DblquoteStr DblquoteStr;
struct DblquoteStr {
DblquoteStr *pNextStr; /* Next string literal in the list */
char z[8]; /* Dequoted value for the string */
};
/*
** An instance of the virtual machine. This structure contains the complete
** state of the virtual machine.
@@ -364,7 +380,7 @@ struct Vdbe {
int pc; /* The program counter */
int rc; /* Value to return */
int nChange; /* Number of db changes made since last reset */
int iStatement; /* Statement number (or 0 if has not opened stmt) */
int iStatement; /* Statement number (or 0 if has no opened stmt) */
i64 iCurrentTime; /* Value of julianday('now') for this statement */
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
@@ -408,6 +424,7 @@ struct Vdbe {
char *zSql; /* Text of the SQL statement that generated this */
#ifdef SQLITE_ENABLE_NORMALIZE
char *zNormSql; /* Normalization of the associated SQL statement */
DblquoteStr *pDblStr; /* List of double-quoted string literals */
#endif
void *pFree; /* Free this when deleting the vdbe */
VdbeFrame *pFrame; /* Parent frame */
+25 -15
View File
@@ -62,14 +62,16 @@ static SQLITE_NOINLINE void invokeProfileCallback(sqlite3 *db, Vdbe *p){
sqlite3_int64 iNow;
sqlite3_int64 iElapse;
assert( p->startTime>0 );
assert( db->xProfile!=0 || (db->mTrace & SQLITE_TRACE_PROFILE)!=0 );
assert( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0 );
assert( db->init.busy==0 );
assert( p->zSql!=0 );
sqlite3OsCurrentTimeInt64(db->pVfs, &iNow);
iElapse = (iNow - p->startTime)*1000000;
#ifndef SQLITE_OMIT_DEPRECATED
if( db->xProfile ){
db->xProfile(db->pProfileArg, p->zSql, iElapse);
}
#endif
if( db->mTrace & SQLITE_TRACE_PROFILE ){
db->xTrace(SQLITE_TRACE_PROFILE, db->pTraceArg, p, (void*)&iElapse);
}
@@ -583,7 +585,7 @@ static int sqlite3Step(Vdbe *p){
return SQLITE_NOMEM_BKPT;
}
if( p->pc<=0 && p->expired ){
if( p->pc<0 && p->expired ){
p->rc = SQLITE_SCHEMA;
rc = SQLITE_ERROR;
goto end_of_step;
@@ -602,7 +604,7 @@ static int sqlite3Step(Vdbe *p){
);
#ifndef SQLITE_OMIT_TRACE
if( (db->xProfile || (db->mTrace & SQLITE_TRACE_PROFILE)!=0)
if( (db->mTrace & (SQLITE_TRACE_PROFILE|SQLITE_TRACE_XPROFILE))!=0
&& !db->init.busy && p->zSql ){
sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime);
}else{
@@ -629,16 +631,18 @@ static int sqlite3Step(Vdbe *p){
db->nVdbeExec--;
}
if( rc!=SQLITE_ROW ){
#ifndef SQLITE_OMIT_TRACE
/* If the statement completed successfully, invoke the profile callback */
if( rc!=SQLITE_ROW ) checkProfileCallback(db, p);
/* If the statement completed successfully, invoke the profile callback */
checkProfileCallback(db, p);
#endif
if( rc==SQLITE_DONE && db->autoCommit ){
assert( p->rc==SQLITE_OK );
p->rc = doWalCallbacks(db);
if( p->rc!=SQLITE_OK ){
rc = SQLITE_ERROR;
if( rc==SQLITE_DONE && db->autoCommit ){
assert( p->rc==SQLITE_OK );
p->rc = doWalCallbacks(db);
if( p->rc!=SQLITE_OK ){
rc = SQLITE_ERROR;
}
}
}
@@ -658,9 +662,9 @@ end_of_step:
|| (rc&0xff)==SQLITE_BUSY || rc==SQLITE_MISUSE
);
assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
if( (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
&& rc!=SQLITE_ROW
&& rc!=SQLITE_DONE
if( rc!=SQLITE_ROW
&& rc!=SQLITE_DONE
&& (p->prepFlags & SQLITE_PREPARE_SAVESQL)!=0
){
/* If this statement was prepared using saved SQL and an
** error has occurred, then return the error code in p->rc to the
@@ -1282,7 +1286,7 @@ static int vdbeUnbind(Vdbe *p, int i){
pVar = &p->aVar[i];
sqlite3VdbeMemRelease(pVar);
pVar->flags = MEM_Null;
sqlite3Error(p->db, SQLITE_OK);
p->db->errCode = SQLITE_OK;
/* If the bit corresponding to this variable in Vdbe.expmask is set, then
** binding a new value to this variable invalidates the current query plan.
@@ -1708,7 +1712,13 @@ char *sqlite3_expanded_sql(sqlite3_stmt *pStmt){
*/
const char *sqlite3_normalized_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
return p ? p->zNormSql : 0;
if( p==0 ) return 0;
if( p->zNormSql==0 && ALWAYS(p->zSql!=0) ){
sqlite3_mutex_enter(p->db->mutex);
p->zNormSql = sqlite3Normalize(p, p->zSql);
sqlite3_mutex_leave(p->db->mutex);
}
return p->zNormSql;
}
#endif /* SQLITE_ENABLE_NORMALIZE */
+46 -9
View File
@@ -64,15 +64,45 @@ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, u8 prepFlags){
}
assert( p->zSql==0 );
p->zSql = sqlite3DbStrNDup(p->db, z, n);
#ifdef SQLITE_ENABLE_NORMALIZE
assert( p->zNormSql==0 );
if( p->zSql && (prepFlags & SQLITE_PREPARE_NORMALIZE)!=0 ){
sqlite3Normalize(p, p->zSql, n, prepFlags);
assert( p->zNormSql!=0 || p->db->mallocFailed );
}
#endif
}
#ifdef SQLITE_ENABLE_NORMALIZE
/*
** Add a new element to the Vdbe->pDblStr list.
*/
void sqlite3VdbeAddDblquoteStr(sqlite3 *db, Vdbe *p, const char *z){
if( p ){
int n = sqlite3Strlen30(z);
DblquoteStr *pStr = sqlite3DbMallocRawNN(db,
sizeof(*pStr)+n+1-sizeof(pStr->z));
if( pStr ){
pStr->pNextStr = p->pDblStr;
p->pDblStr = pStr;
memcpy(pStr->z, z, n+1);
}
}
}
#endif
#ifdef SQLITE_ENABLE_NORMALIZE
/*
** zId of length nId is a double-quoted identifier. Check to see if
** that identifier is really used as a string literal.
*/
int sqlite3VdbeUsesDoubleQuotedString(
Vdbe *pVdbe, /* The prepared statement */
const char *zId /* The double-quoted identifier, already dequoted */
){
DblquoteStr *pStr;
assert( zId!=0 );
if( pVdbe->pDblStr==0 ) return 0;
for(pStr=pVdbe->pDblStr; pStr; pStr=pStr->pNextStr){
if( strcmp(zId, pStr->z)==0 ) return 1;
}
return 0;
}
#endif
/*
** Swap all content between two VDBE structures.
*/
@@ -92,7 +122,7 @@ void sqlite3VdbeSwap(Vdbe *pA, Vdbe *pB){
zTmp = pA->zSql;
pA->zSql = pB->zSql;
pB->zSql = zTmp;
#ifdef SQLITE_ENABLE_NORMALIZE
#if 0
zTmp = pA->zNormSql;
pA->zNormSql = pB->zNormSql;
pB->zNormSql = zTmp;
@@ -2855,7 +2885,7 @@ int sqlite3VdbeHalt(Vdbe *p){
}else{
db->nDeferredCons = 0;
db->nDeferredImmCons = 0;
db->flags &= ~SQLITE_DeferFKs;
db->flags &= ~(u64)SQLITE_DeferFKs;
sqlite3CommitInternalChanges(db);
}
}else{
@@ -3170,6 +3200,13 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
sqlite3DbFree(db, p->zSql);
#ifdef SQLITE_ENABLE_NORMALIZE
sqlite3DbFree(db, p->zNormSql);
{
DblquoteStr *pThis, *pNext;
for(pThis=p->pDblStr; pThis; pThis=pNext){
pNext = pThis->pNextStr;
sqlite3DbFree(db, pThis);
}
}
#endif
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
{
+1
View File
@@ -2133,6 +2133,7 @@ Window *sqlite3WindowDup(sqlite3 *db, Expr *pOwner, Window *p){
if( pNew ){
pNew->zName = sqlite3DbStrDup(db, p->zName);
pNew->pFilter = sqlite3ExprDup(db, p->pFilter, 0);
pNew->pFunc = p->pFunc;
pNew->pPartition = sqlite3ExprListDup(db, p->pPartition, 0);
pNew->pOrderBy = sqlite3ExprListDup(db, p->pOrderBy, 0);
pNew->eType = p->eType;
+57 -1
View File
@@ -12,7 +12,7 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix altertab
set testprefix altertab2
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
ifcapable !altertable {
@@ -85,5 +85,61 @@ do_execsql_test 2.3 {
{CREATE TABLE c3(x, FOREIGN KEY (x) REFERENCES "p3"(a))}
}
#-------------------------------------------------------------------------
# Table name in WITH clauses that are part of views or triggers.
#
foreach {tn schema} {
1 {
CREATE TABLE log_entry(col1, y);
CREATE INDEX i1 ON log_entry(col1);
}
2 {
CREATE TABLE t1(a, b, c);
CREATE TABLE t2(x);
CREATE TABLE log_entry(col1);
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
INSERT INTO t2 SELECT col1 FROM log_entry;
END;
}
3 {
CREATE TABLE t1(a, b, c);
CREATE TABLE t2(x);
CREATE TABLE log_entry(col1);
CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN
INSERT INTO t2
WITH xyz(x) AS (SELECT col1 FROM log_entry)
SELECT x FROM xyz;
END;
}
4 {
CREATE TABLE log_entry(col1);
CREATE VIEW ttt AS
WITH xyz(x) AS (SELECT col1 FROM log_entry)
SELECT x FROM xyz;
}
} {
reset_db
do_execsql_test 3.$tn.1 $schema
set expect [db eval "SELECT sql FROM sqlite_master"]
set expect [string map {log_entry {"newname"}} $expect]
do_execsql_test 3.$tn.2 {
ALTER TABLE log_entry RENAME TO newname;
SELECT sql FROM sqlite_master;
} $expect
reset_db
do_execsql_test 3.$tn.3 $schema
set expect [db eval "SELECT sql FROM sqlite_master"]
set expect [string map {col1 newname} $expect]
do_execsql_test 3.$tn.4 {
ALTER TABLE log_entry RENAME col1 TO newname;
SELECT sql FROM sqlite_master;
} $expect
}
finish_test
+1
View File
@@ -78,6 +78,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
printf("************** nByte=%d ***************\n", (int)nByte);
fflush(stdout);
}
if( sqlite3_initialize() ) return 0;
rc = sqlite3_open(0, &db);
if( rc ) return 1;
a = sqlite3_malloc64(nByte+1);
+65
View File
@@ -0,0 +1,65 @@
# 2018 December 3
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4umlaut
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(x);
CREATE VIRTUAL TABLE t2 USING fts4(
x,
tokenize=unicode61 "remove_diacritics=2"
);
}
foreach {tn q res1 res2} {
1 "Hà Nội" 0 1
2 "Hà Noi" 1 1
3 "Ha Noi" 1 1
4 "Ha N\u1ed9i" 0 1
5 "Ha N\u006fi" 1 1
6 "Ha N\u006f\u0302i" 1 1
7 "Ha N\u006f\u0323\u0302i" 1 1
} {
do_execsql_test 1.$tn.1 {
DELETE FROM t1;
INSERT INTO t1(rowid, x) VALUES (1, 'Ha Noi');
SELECT count(*) FROM t1 WHERE t1 MATCH $q
} $res1
do_execsql_test 1.$tn.2 {
DELETE FROM t1;
INSERT INTO t1(rowid, x) VALUES (1, $q);
SELECT count(*) FROM t1 WHERE t1 MATCH 'Ha Noi'
} $res1
do_execsql_test 1.$tn.2 {
DELETE FROM t2;
INSERT INTO t2(rowid, x) VALUES (1, 'Ha Noi');
SELECT count(*) FROM t2 WHERE t2 MATCH $q
} $res2
do_execsql_test 1.$tn.2 {
DELETE FROM t2;
INSERT INTO t2(rowid, x) VALUES (1, $q);
SELECT count(*) FROM t2 WHERE t2 MATCH 'Ha Noi'
} $res2
}
finish_test
+82
View File
@@ -0,0 +1,82 @@
# 2018-12-12
#
# 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.
#
#***********************************************************************
#
# Test cases found by Matthew Denton's fuzzer at Chrome.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_execsql_test fuzz4-100 {
CREATE TABLE Table0 (Col0 NOT NULL DEFAULT (CURRENT_TIME IS 1 > 1));
INSERT OR REPLACE INTO Table0 DEFAULT VALUES ;
SELECT * FROM Table0;
} {0}
do_execsql_test fuzz4-110 {
CREATE TABLE Table1(
Col0 TEXT DEFAULT (CASE WHEN 1 IS 3530822107858468864
THEN 1 ELSE quote(1) IS 3530822107858468864 END)
);
INSERT INTO Table1 DEFAULT VALUES;
SELECT * FROM Table1;
} {0}
do_execsql_test fuzz4-200 {
CREATE TABLE Table2a(
Col0 NOT NULL DEFAULT (CURRENT_TIME IS 1 IS NOT 1 > 1)
);
INSERT OR REPLACE INTO Table2a DEFAULT VALUES;
SELECT * FROM Table2a;
} {0}
do_execsql_test fuzz4-210 {
CREATE TABLE Table2b (Col0 NOT NULL DEFAULT (CURRENT_TIME IS NOT FALSE)) ;
INSERT OR REPLACE INTO Table2b DEFAULT VALUES ;
SELECT * FROM Table2b;
} {1}
do_execsql_test fuzz4-300 {
CREATE TABLE Table3 (Col0 DEFAULT (CURRENT_TIMESTAMP BETWEEN 1 AND 1));
INSERT INTO Table3 DEFAULT VALUES;
SELECT * FROM Table3;
} {0}
do_execsql_test fuzz4-400 {
CREATE TABLE Table4 (Col0 DEFAULT (1 BETWEEN CURRENT_TIMESTAMP AND 1));
INSERT INTO Table4 DEFAULT VALUES;
SELECT * FROM Table4;
} {0}
do_execsql_test fuzz4-500 {
CREATE TABLE Table5 (Col0 DEFAULT (1 BETWEEN 1 AND CURRENT_TIMESTAMP));
INSERT INTO Table5 DEFAULT VALUES;
SELECT * FROM Table5;
} {1}
do_execsql_test fuzz4-600 {
CREATE TEMPORARY TABLE Table6(
Col0 DEFAULT (CASE x'5d' WHEN 1 THEN
CASE CURRENT_TIMESTAMP WHEN 1 THEN 1 ELSE 1 END
ELSE CASE WHEN 1 THEN FALSE END END )
);
INSERT INTO temp.Table6 DEFAULT VALUES ;
SELECT * FROM Table6;
} {0}
do_execsql_test fuzz4-610 {
WITH TableX AS (SELECT DISTINCT * ORDER BY 1 , 1 COLLATE RTRIM)
DELETE FROM Table6 WHERE Col0 || +8388608 ;
SELECT * FROM Table6;
} {}
finish_test
BIN
View File
Binary file not shown.
+20 -1
View File
@@ -389,6 +389,25 @@ do_execsql_test index6-11.1 {
do_execsql_test index6-11.2 {
EXPLAIN QUERY PLAN SELECT a FROM t11 WHERE b<>99 AND c<>98;
} {/USING INDEX t11x/}
# 2018-12-08
# Ticket https://www.sqlite.org/src/info/1d958d90596593a7
# NOT IN operator fails when using a partial index.
#
do_execsql_test index6-12.1 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES(1,1);
INSERT INTO t1 VALUES(2,2);
CREATE TABLE t2(x);
INSERT INTO t2 VALUES(1);
INSERT INTO t2 VALUES(2);
SELECT 'one', * FROM t2 WHERE x NOT IN (SELECT a FROM t1);
CREATE INDEX t1a ON t1(a) WHERE b=1;
SELECT 'two', * FROM t2 WHERE x NOT IN (SELECT a FROM t1);
} {}
do_execsql_test index6-12.2 {
SELECT x FROM t2 WHERE x IN (SELECT a FROM t1) ORDER BY +x;
} {1 2}
finish_test
+18 -1
View File
@@ -813,6 +813,23 @@ do_execsql_test json-14.170 {
SELECT fullkey FROM json_tree('null');
} {$}
# 2018-12-03
# Make sure the table-valued functions contained within parentheses
# work correctly.
#
# Bug reported via private email. See TH3 for more information.
#
do_execsql_test json-15.100 {
SELECT * FROM JSON_EACH('{"a":1, "b":2}');
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.110 {
SELECT xyz.* FROM JSON_EACH('{"a":1, "b":2}') AS xyz;
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.120 {
SELECT * FROM (JSON_EACH('{"a":1, "b":2}'));
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
do_execsql_test json-15.130 {
SELECT xyz.* FROM (JSON_EACH('{"a":1, "b":2}')) AS xyz;
} {a 1 integer 1 2 {} {$.a} {$} b 2 integer 2 4 {} {$.b} {$}}
finish_test
+9 -9
View File
@@ -86,7 +86,7 @@ do_test 201 {
} {}
do_test 202 {
sqlite3_normalized_sql $STMT
} {}
} {SELECT a,b FROM t1 WHERE b=?ORDER BY a;}
do_test 203 {
sqlite3_finalize $STMT
} {SQLITE_OK}
@@ -207,7 +207,7 @@ foreach {tnum sql flags norm} {
430
{SELECT "a" FROM t1 WHERE "x" IN ("1","2",'3');}
0x2
{0 {SELECT"a"FROM t1 WHERE"x"IN(?,?,?);}}
{0 {SELECT a FROM t1 WHERE x IN(?,?,?);}}
440
{SELECT 'a' FROM t1 WHERE 'x';}
@@ -217,7 +217,7 @@ foreach {tnum sql flags norm} {
450
{SELECT [a] FROM t1 WHERE [x];}
0x2
{0 {SELECT"a"FROM t1 WHERE"x";}}
{0 {SELECT a FROM t1 WHERE x;}}
460
{SELECT * FROM t1 WHERE x IN (x);}
@@ -232,12 +232,12 @@ foreach {tnum sql flags norm} {
480
{SELECT * FROM t1 WHERE x IN ([x],"a");}
0x2
{0 {SELECT*FROM t1 WHERE x IN("x","a");}}
{0 {SELECT*FROM t1 WHERE x IN(x,a);}}
500
{SELECT * FROM t1 WHERE x IN ([x],"a",'b',sqlite_version());}
0x2
{0 {SELECT*FROM t1 WHERE x IN("x","a",?,sqlite_version());}}
{0 {SELECT*FROM t1 WHERE x IN(x,a,?,sqlite_version());}}
520
{SELECT * FROM t1 WHERE x IN (SELECT x FROM t1);}
@@ -247,12 +247,12 @@ foreach {tnum sql flags norm} {
540
{SELECT * FROM t1 WHERE x IN ((SELECT x FROM t1));}
0x2
{0 {SELECT*FROM t1 WHERE x IN(?,?,?);}}
{0 {SELECT*FROM t1 WHERE x IN((SELECT x FROM t1));}}
550
{SELECT a, a+1, a||'b', a+"b" FROM t1;}
0x2
{0 {SELECT a,a+?,a||?,a+"b"FROM t1;}}
{0 {SELECT a,a+?,a||?,a+b FROM t1;}}
570
{SELECT * FROM t1 WHERE x IN (1);}
@@ -316,7 +316,7 @@ foreach {tnum sql flags norm} {
680
{SELECT a, "col f" FROM t1 LEFT OUTER JOIN t2 ON [t1].[col f] == [t2].[col y];}
0x2
{0 {SELECT a,"col f"FROM t1 LEFT OUTER JOIN t2 ON"t1"."col f"=="t2"."col y";}}
{0 {SELECT a,"col f"FROM t1 LEFT OUTER JOIN t2 ON t1."col f"==t2."col y";}}
690
{SELECT * FROM ( WITH x AS ( SELECT * FROM t1 WHERE x IN ( 1)) SELECT 10);}
@@ -346,7 +346,7 @@ foreach {tnum sql flags norm} {
760
{SELECT x FROM t1 WHERE x IN ([x] IS NOT NULL, NULL, 1, 'a', "b", x'00');}
0x2
{0 {SELECT x FROM t1 WHERE x IN("x"IS NOT NULL,?,?,?,"b",?);}}
{0 {SELECT x FROM t1 WHERE x IN(x IS NOT NULL,?,?,?,b,?);}}
} {
do_test $tnum {
set code [catch {
+1 -1
View File
@@ -256,7 +256,7 @@ do_test shell1-3.1.3 {
do_test shell1-3.1.4 {
# too many arguments
catchcmd "test.db" ".backup FOO BAR BAD"
} {1 {Usage: .backup ?DB? ?--append? FILENAME}}
} {1 {Usage: .backup ?DB? ?OPTIONS? FILENAME}}
# .bail ON|OFF Stop after hitting an error. Default OFF
do_test shell1-3.2.1 {
+4 -4
View File
@@ -107,14 +107,14 @@ SELECT 1;
} {1 1 1}
do_test shell4-2.1 {
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace"
} {1 {Usage: .trace FILE|off}}
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace --unknown"
} {1 {Unknown option "--unknown" on ".trace"}}
do_test shell4-2.2 {
catchcmd ":memory:" "CREATE TABLE t1(x);\n.trace off\n.trace off\n"
} {0 {}}
do_test shell4-2.3 {
catchcmd ":memory:" ".trace stdout\n.trace\n.trace off\n.dump\n"
} {/^1 {PRAGMA.*Usage:.*}$/}
catchcmd ":memory:" ".trace stdout\n.dump\n.trace off\n"
} {/^0 {PRAGMA.*}$/}
ifcapable trace {
do_test shell4-2.4 {
catchcmd ":memory:" ".trace stdout\nCREATE TABLE t1(x);SELECT * FROM t1;"
+5
View File
@@ -125,6 +125,11 @@ do_execsql_test tabfunc01-4.3 {
SELECT * FROM aux1.generate_series(1,4)
} {1 2 3 4}
# 2018-12-03: Fix bug reported by by private email.
do_execsql_test tabfunc01-4.4 {
SELECT * FROM (generate_series(1,5,2)) AS x LIMIT 10;
} {1 3 5}
# The next series of tests is verifying that virtual table are able
# to optimize the IN operator, even on terms that are not marked "omit".
# When the generate_series virtual table is compiled for the testfixture,
+69
View File
@@ -0,0 +1,69 @@
# 2018-12-07
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The
# focus of this file is testing the VACUUM INTO statement.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# If the VACUUM statement is disabled in the current build, skip all
# the tests in this file.
#
ifcapable {!vacuum} {
omit_test vacuum.test {Compiled with SQLITE_OMIT_VACUUM}
finish_test
return
}
forcedelete out.db
do_execsql_test vacuum-into-100 {
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<100)
INSERT INTO t1(a,b) SELECT x, randomblob(600) FROM c;
CREATE INDEX t1b ON t1(b);
DELETE FROM t1 WHERE a%2;
SELECT count(*), sum(a), sum(length(b)) FROM t1;
} {50 2550 30000}
do_execsql_test vacuum-into-110 {
VACUUM main INTO 'out.db';
} {}
sqlite3 db2 out.db
do_test vacuum-into-120 {
db2 eval {SELECT count(*), sum(a), sum(length(b)) FROM t1}
} {50 2550 30000}
do_catchsql_test vacuum-into-130 {
VACUUM INTO 'out.db';
} {1 {output file already exists}}
forcedelete out2.db
do_catchsql_test vacuum-into-140 {
VACUUM INTO 'out2.db';
} {0 {}}
do_catchsql_test vacuum-into-150 {
VACUUM INTO 'out2.db';
} {1 {output file already exists}}
do_catchsql_test vacuum-into-200 {
VACUUM main INTO ':memory:';
} {0 {}}
# The INTO argument can be an arbitrary expression.
#
do_execsql_test vacuum-into-300 {
CREATE TABLE t2(name TEXT);
INSERT INTO t2 VALUES(':memory:');
VACUUM main INTO (SELECT name FROM t2);
} {}
do_catchsql_test vacuum-into-310 {
VACUUM INTO null;
} {1 {non-text filename}}
finish_test
+27
View File
@@ -594,4 +594,31 @@ do_execsql_test 13.5 {
} {
}
# 2018-12-06
# https://www.sqlite.org/src/info/f09fcd17810f65f7
# Assertion fault when window functions are used.
#
# Root cause is the query flattener invoking sqlite3ExprDup() on
# expressions that contain subqueries with window functions. The
# sqlite3ExprDup() routine is not making correctly initializing
# Select.pWin field of the subqueries.
#
sqlite3 db :memory:
do_execsql_test 14.0 {
SELECT * FROM(
SELECT * FROM (SELECT 1 AS c) WHERE c IN (
SELECT (row_number() OVER()) FROM (VALUES (0))
)
);
} {1}
do_execsql_test 14.1 {
CREATE TABLE t1(x); INSERT INTO t1(x) VALUES(12345);
CREATE TABLE t2(c); INSERT INTO t2(c) VALUES(1);
SELECT y, y+1, y+2 FROM (
SELECT c IN (
SELECT (row_number() OVER()) FROM t1
) AS y FROM t2
);
} {1 2 3}
finish_test
+140
View File
@@ -0,0 +1,140 @@
/*
** Copyright 2008 D. Richard Hipp and Hipp, Wyrick & Company, Inc.
** All Rights Reserved
**
******************************************************************************
**
** This file implements a stand-alone utility program that converts
** a binary file (usually an SQLite database) into a text format that
** is compact and friendly to human-readers.
**
** Usage:
**
** dbtotxt [--pagesize N] FILENAME
**
** The translation of the database appears on standard output. If the
** --pagesize command-line option is omitted, then the page size is taken
** from the database header.
**
** Compactness is achieved by suppressing lines of all zero bytes. This
** works well at compressing test databases that are mostly empty. But
** the output will probably be lengthy for a real database containing lots
** of real content. For maximum compactness, it is suggested that test
** databases be constructed with "zeroblob()" rather than "randomblob()"
** used for filler content and with "PRAGMA secure_delete=ON" selected to
** zero-out deleted content.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Return true if the line is all zeros */
static int allZero(unsigned char *aLine){
int i;
for(i=0; i<16 && aLine[i]==0; i++){}
return i==16;
}
int main(int argc, char **argv){
int pgsz = 0; /* page size */
long szFile; /* Size of the input file in bytes */
FILE *in; /* Input file */
int i, j; /* Loop counters */
int nErr = 0; /* Number of errors */
const char *zInputFile = 0; /* Name of the input file */
const char *zBaseName = 0; /* Base name of the file */
int lastPage = 0; /* Last page number shown */
int iPage; /* Current page number */
unsigned char aLine[16]; /* A single line of the file */
unsigned char aHdr[100]; /* File header */
for(i=1; i<argc; i++){
if( argv[i][0]=='-' ){
const char *z = argv[i];
z++;
if( z[0]=='-' ) z++;
if( strcmp(z,"pagesize")==0 ){
i++;
pgsz = atoi(argv[i]);
if( pgsz<512 || pgsz>65536 || (pgsz&(pgsz-1))!=0 ){
fprintf(stderr, "Page size must be a power of two between"
" 512 and 65536.\n");
nErr++;
}
continue;
}
fprintf(stderr, "Unknown option: %s\n", argv[i]);
nErr++;
}else if( zInputFile ){
fprintf(stderr, "Already using a different input file: [%s]\n", argv[i]);
nErr++;
}else{
zInputFile = argv[i];
}
}
if( zInputFile==0 ){
fprintf(stderr, "No input file specified.\n");
nErr++;
}
if( nErr ){
fprintf(stderr, "Usage: %s [--pagesize N] FILENAME\n", argv[0]);
exit(1);
}
in = fopen(zInputFile, "rb");
if( in==0 ){
fprintf(stderr, "Cannot open input file [%s]\n", zInputFile);
exit(1);
}
fseek(in, 0, SEEK_END);
szFile = ftell(in);
rewind(in);
if( szFile<512 ){
fprintf(stderr, "File too short. Minimum size is 512 bytes.\n");
exit(1);
}
if( fread(aHdr, 100, 1, in)!=1 ){
fprintf(stderr, "Cannot read file header\n");
exit(1);
}
rewind(in);
if( pgsz==0 ){
pgsz = (aHdr[16]<<8) | aHdr[17];
if( pgsz==1 ) pgsz = 65536;
if( pgsz<512 || (pgsz&(pgsz-1))!=0 ){
fprintf(stderr, "Invalid page size in header: %d\n", pgsz);
exit(1);
}
}
zBaseName = zInputFile;
for(i=0; zInputFile[i]; i++){
if( zInputFile[i]=='/' && zInputFile[i+1]!=0 ) zBaseName = zInputFile+1;
}
printf("| size %d pagesize %d filename %s\n",(int)szFile,pgsz,zBaseName);
for(i=0; i<szFile; i+=16){
int got = (int)fread(aLine, 1, 16, in);
if( got!=16 ){
static int once = 1;
if( once ){
fprintf(stderr, "Could not read input file starting at byte %d\n",
i+got);
}
memset(aLine+got, 0, 16-got);
}
if( allZero(aLine) ) continue;
iPage = i/pgsz + 1;
if( lastPage!=iPage ){
printf("| page %d offset %d\n", iPage, (iPage-1)*pgsz);
lastPage = iPage;
}
printf("| %5d:", i-(iPage-1)*pgsz);
for(j=0; j<16; j++) printf(" %02x", aLine[j]);
printf(" ");
for(j=0; j<16; j++){
char c = aLine[j];
fputc(c>=0x20 && c<=0x7e ? c : '.', stdout);
}
fputc('\n', stdout);
}
fclose(in);
printf("| end %s\n", zBaseName);
return 0;
}
+56
View File
@@ -0,0 +1,56 @@
<h1 align="center">The dbtotxt Tool</h1>
The dbtotxt utility program reads an SQLite database file and writes its
raw binary content to screen as a hex dump for testing and debugging
purposes.
The hex-dump output is formatted in such a way as to be easily readable
both by humans and by software. The dbtotxt utility has long been a part
of the TH3 test suite. The output of dbtotxt can be embedded in TH3 test
scripts and used to generate very specific database files, perhaps with
deliberately introduced corruption. The cov1/corrupt*.test modules in
TH3 make extensive use of dbtotxt.
More recently (2018-12-13) the dbtotxt utility has been added to the SQLite
core and the command-line shell (CLI) has been augmented to be able to read
dbtotxt output. The CLI dot-command is:
> .open --hexdb ?OPTIONAL-FILENAME?
If the OPTIONAL-FILENAME is included, then content is read from that file.
If OPTIONAL-FILENAME is omitted, then the text is taken from the input stream,
terminated by the "| end" line of the dbtotxt text. This allows small test
databases to be embedded directly in scripts. Consider this example:
>
.open --hexdb
| size 8192 pagesize 4096 filename x9.db
| page 1 offset 0
| 0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00 SQLite format 3.
| 16: 10 00 01 01 00 40 20 20 00 00 00 04 00 00 00 02 .....@ ........
| 32: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 04 ................
| 48: 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 ................
| 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 ................
| 96: 00 2e 30 38 0d 00 00 00 01 0f c0 00 0f c0 00 00 ..08............
| 4032: 3e 01 06 17 11 11 01 69 74 61 62 6c 65 74 31 74 >......itablet1t
| 4048: 31 02 43 52 45 41 54 45 20 54 41 42 4c 45 20 74 1.CREATE TABLE t
| 4064: 31 28 78 2c 79 20 44 45 46 41 55 4c 54 20 78 27 1(x,y DEFAULT x'
| 4080: 66 66 27 2c 7a 20 44 45 46 41 55 4c 54 20 30 29 ff',z DEFAULT 0)
| page 2 offset 4096
| 0: 0d 08 14 00 04 00 10 00 0e 05 0a 0f 04 15 00 10 ................
| 16: 88 02 03 05 90 04 0e 08 00 00 00 00 00 00 00 00 ................
| 1040: 00 00 00 00 ff 87 7c 02 05 8f 78 0e 08 00 00 00 ......|...x.....
| 2064: 00 00 00 ff 0c 0a 01 fb 00 00 00 00 00 00 00 00 ................
| 2560: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 83 ................
| 2576: 78 01 05 87 70 0e 08 00 00 00 00 00 00 00 00 00 x...p...........
| 3072: 00 00 00 00 00 00 00 00 00 ff 00 00 01 fb 00 00 ................
| 3584: 00 00 00 00 00 83 78 00 05 87 70 0e 08 00 00 00 ......x...p.....
| 4080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ................
| end x9.db
SELECT rowid FROM t1;
PRAGMA integrity_check;
You can run this script to see that the database file is correctly decoded
and loaded. Furthermore, you can make subtle corruptions to the input
database simply by editing the hexadecimal description, then rerun the
script to verify that SQLite correctly handles the corruption.
+164
View File
@@ -0,0 +1,164 @@
/*
** 2018-12-04
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
**
** This file implements a utility program used to help determine which
** indexes in a database schema are used and unused, and how often specific
** indexes are used.
*/
#include "sqlite3.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
static void usage(const char *argv0){
printf("Usage: %s DATABASE LOG\n\n", argv0);
printf(
"DATABASE is an SQLite database against which various statements\n"
"have been run. The SQL text is stored in LOG. LOG is an SQLite\n"
"database with this schema:\n"
"\n"
" CREATE TABLE sqllog(sql TEXT);\n"
"\n"
"This utility program analyzes statements contained in LOG and prints\n"
"a report showing how many times each index in DATABASE is used by the\n"
"statements in LOG.\n"
"\n"
"DATABASE only needs to contain the schema used by the statements in\n"
"LOG. The content can be removed from DATABASE.\n"
);
printf("\nAnalysis will be done by SQLite version %s dated %.20s\n"
"checkin number %.40s. Different versions\n"
"of SQLite might use different indexes.\n",
sqlite3_libversion(), sqlite3_sourceid(), sqlite3_sourceid()+21);
exit(1);
}
int main(int argc, char **argv){
sqlite3 *db = 0; /* The main database */
sqlite3_stmt *pStmt = 0; /* a query */
char *zSql;
int nErr = 0;
int rc;
if( argc!=3 ) usage(argv[0]);
rc = sqlite3_open_v2(argv[1], &db, SQLITE_OPEN_READONLY, 0);
if( rc ){
printf("Cannot open \"%s\" for reading: %s\n", argv[1], sqlite3_errmsg(db));
goto errorOut;
}
rc = sqlite3_prepare_v2(db, "SELECT * FROM sqlite_master", -1, &pStmt, 0);
if( rc ){
printf("Cannot read the schema from \"%s\" - %s\n", argv[1],
sqlite3_errmsg(db));
goto errorOut;
}
sqlite3_finalize(pStmt);
pStmt = 0;
rc = sqlite3_exec(db,
"CREATE TABLE temp.idxu(\n"
" tbl TEXT,\n"
" idx TEXT,\n"
" cnt INT,\n"
" PRIMARY KEY(idx)\n"
") WITHOUT ROWID;", 0, 0, 0);
if( rc ){
printf("Cannot create the result table - %s\n",
sqlite3_errmsg(db));
goto errorOut;
}
rc = sqlite3_exec(db,
"INSERT INTO temp.idxu(tbl,idx,cnt)"
" SELECT tbl_name, name, 0 FROM sqlite_master"
" WHERE type='index' AND sql IS NOT NULL", 0, 0, 0);
/* Open the LOG database */
zSql = sqlite3_mprintf("ATTACH %Q AS log", argv[2]);
rc = sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
if( rc ){
printf("Cannot open the LOG database \"%s\" - %s\n",
argv[2], sqlite3_errmsg(db));
goto errorOut;
}
rc = sqlite3_prepare_v2(db, "SELECT sql, rowid FROM log.sqllog",
-1, &pStmt, 0);
if( rc ){
printf("Cannot read the SQLLOG table in the LOG database \"%s\" - %s\n",
argv[2], sqlite3_errmsg(db));
goto errorOut;
}
/* Update the counts based on LOG */
while( sqlite3_step(pStmt)==SQLITE_ROW ){
const char *zLog = (const char*)sqlite3_column_text(pStmt, 0);
sqlite3_stmt *pS2;
if( zLog==0 ) continue;
zSql = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zLog);
rc = sqlite3_prepare_v2(db, zSql, -1, &pS2, 0);
sqlite3_free(zSql);
if( rc ){
printf("Cannot compile LOG entry %d (%s): %s\n",
sqlite3_column_int(pStmt, 1), zLog, sqlite3_errmsg(db));
nErr++;
}else{
while( sqlite3_step(pS2)==SQLITE_ROW ){
const char *zExplain = (const char*)sqlite3_column_text(pS2,3);
const char *z1, *z2;
int n;
/* printf("EXPLAIN: %s\n", zExplain); */
z1 = strstr(zExplain, " USING INDEX ");
if( z1==0 ) continue;
z1 += 13;
for(z2=z1+1; z2[1] && z2[1]!='('; z2++){}
n = z2 - z1;
zSql = sqlite3_mprintf(
"UPDATE temp.idxu SET cnt=cnt+1 WHERE idx='%.*q'", n, z1
);
/* printf("sql: %s\n", zSql); */
sqlite3_exec(db, zSql, 0, 0, 0);
sqlite3_free(zSql);
}
}
sqlite3_finalize(pS2);
}
sqlite3_finalize(pStmt);
/* Generate the report */
rc = sqlite3_prepare_v2(db,
"SELECT tbl, idx, cnt, "
" (SELECT group_concat(name,',') FROM pragma_index_info(idx))"
" FROM temp.idxu, main.sqlite_master"
" WHERE temp.idxu.tbl=main.sqlite_master.tbl_name"
" AND temp.idxu.idx=main.sqlite_master.name"
" ORDER BY cnt DESC, tbl, idx",
-1, &pStmt, 0);
if( rc ){
printf("Cannot query the result table - %s\n",
sqlite3_errmsg(db));
goto errorOut;
}
while( sqlite3_step(pStmt)==SQLITE_ROW ){
printf("%10d %s on %s(%s)\n",
sqlite3_column_int(pStmt, 2),
sqlite3_column_text(pStmt, 1),
sqlite3_column_text(pStmt, 0),
sqlite3_column_text(pStmt, 3));
}
sqlite3_finalize(pStmt);
pStmt = 0;
errorOut:
sqlite3_finalize(pStmt);
sqlite3_close(db);
return nErr;
}
+9 -2
View File
@@ -4590,13 +4590,20 @@ void ReportTable(
tplt_print(out,lemp,lemp->overflow,&lineno);
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate the table of rule information
/* Generate the tables of rule information. yyRuleInfoLhs[] and
** yyRuleInfoNRhs[].
**
** Note: This code depends on the fact that rules are number
** sequentually beginning with 0.
*/
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
fprintf(out," { %4d, %4d }, /* (%d) ",rp->lhs->index,-rp->nrhs,i);
fprintf(out," %4d, /* (%d) ", rp->lhs->index, i);
rule_print(out, rp);
fprintf(out," */\n"); lineno++;
}
tplt_xfer(lemp->name,in,out,&lineno);
for(i=0, rp=lemp->rule; rp; rp=rp->next, i++){
fprintf(out," %3d, /* (%d) ", -rp->nrhs, i);
rule_print(out, rp);
fprintf(out," */\n"); lineno++;
}
+14 -12
View File
@@ -686,13 +686,15 @@ static void yy_shift(
yyTraceShift(yypParser, yyNewState, "Shift");
}
/* The following table contains information about every rule that
** is used during the reduce.
*/
static const struct {
YYCODETYPE lhs; /* Symbol on the left-hand side of the rule */
signed char nrhs; /* Negative of the number of RHS symbols in the rule */
} yyRuleInfo[] = {
/* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
** of that rule */
static const YYCODETYPE yyRuleInfoLhs[] = {
%%
};
/* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
** of symbols on the right-hand side of that rule. */
static const signed char yyRuleInfoNRhs[] = {
%%
};
@@ -725,7 +727,7 @@ static YYACTIONTYPE yy_reduce(
yymsp = yypParser->yytos;
#ifndef NDEBUG
if( yyTraceFILE && yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) ){
yysize = yyRuleInfo[yyruleno].nrhs;
yysize = yyRuleInfoNRhs[yyruleno];
if( yysize ){
fprintf(yyTraceFILE, "%sReduce %d [%s], go to state %d.\n",
yyTracePrompt,
@@ -740,7 +742,7 @@ static YYACTIONTYPE yy_reduce(
/* Check that the stack is large enough to grow by a single entry
** if the RHS of the rule is empty. This ensures that there is room
** enough on the stack to push the LHS value */
if( yyRuleInfo[yyruleno].nrhs==0 ){
if( yyRuleInfoNRhs[yyruleno]==0 ){
#ifdef YYTRACKMAXSTACKDEPTH
if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
yypParser->yyhwm++;
@@ -782,9 +784,9 @@ static YYACTIONTYPE yy_reduce(
%%
/********** End reduce actions ************************************************/
};
assert( yyruleno<sizeof(yyRuleInfo)/sizeof(yyRuleInfo[0]) );
yygoto = yyRuleInfo[yyruleno].lhs;
yysize = yyRuleInfo[yyruleno].nrhs;
assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
yygoto = yyRuleInfoLhs[yyruleno];
yysize = yyRuleInfoNRhs[yyruleno];
yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
/* There are no SHIFTREDUCE actions on nonterminals because the table