Compare commits

...

78 Commits

Author SHA1 Message Date
mistachkin ff9fcd5a14 Add extra checking of the database extended error code.
FossilOrigin-Name: f2906c44519d76db5bc36013369ae498b80655a8
2014-05-30 16:54:09 +00:00
mistachkin 6b98d67b2b Add tests for the invalid file handle detection logic in the winLock() function.
FossilOrigin-Name: ed5a9eb4f30a395bc641e79254217c7d7cf0aa5d
2014-05-30 16:42:35 +00:00
mistachkin 8e86b6a3df Revise locking retry semantics in Win32 VFS to abort early if the file handle is reported as invalid.
FossilOrigin-Name: d43e2e59b5647655595fd953febf2beefa480006
2014-05-28 03:27:42 +00:00
mistachkin ff0bc8f9f7 Revise how OSTRACE reports logically boolean results in the Win32 VFS.
FossilOrigin-Name: c405f971cf03e29110019ff863cbfb026d97e1e6
2014-05-28 03:23:55 +00:00
drh e9afc3f279 Remove an incorrect assert() in the sorter.
FossilOrigin-Name: b8b66103de8c554cb87df40bf040760ec29f2ae1
2014-05-27 20:19:06 +00:00
drh 3c559a8d3c Fix harmless compiler warnings.
FossilOrigin-Name: 20b75460c0661b5dc071177b4a0791aceccda029
2014-05-27 19:18:36 +00:00
drh 48dd1d8e28 Change the name of the Index.autoIndex field to Index.idxType and provide
symbolic names for the various values of that field rather than using
magic numbers.

FossilOrigin-Name: d16e575dacc811de0f7b58a0d1cd243678dce6c5
2014-05-27 18:18:58 +00:00
drh a3bc66a3f5 Avoid unnecessary cursor opens and seeks when running the OR-optimization
on a WITHOUT ROWID table.

FossilOrigin-Name: 9c785c58327e08dad94a278a643a5443f94aec36
2014-05-27 17:57:32 +00:00
drh 3fb6730699 Improved comments on the OR-optimization logic in the query planner.
FossilOrigin-Name: 77fef5a3987fc16f84a8e755283ca6ec1363013c
2014-05-27 16:41:39 +00:00
drh f53b4ad0f9 Remove unused code (previously #ifdef-ed out) from btree.c.
FossilOrigin-Name: 8bc9737112e2700f337ff377cda040c8ba9d729f
2014-05-27 15:21:42 +00:00
drh b7231a8cf0 Fix a harmless compiler warning in the FTS4 logic.
FossilOrigin-Name: 64a869ad2388d9d62601b93d5139f2dc57f260f7
2014-05-27 11:54:48 +00:00
dan c2070c7d96 Add a test to whereI.test that uses a multi-column PK.
FossilOrigin-Name: aa183e60929bdbbcea3c436dd8cc674fc44ad09a
2014-05-27 11:42:23 +00:00
drh 1529908001 Fix for (unsupported) SQLITE_USE_FCNTL_TRACE code.
FossilOrigin-Name: 994b2b7a591f08609140eb504253c141aec6206a
2014-05-27 10:57:37 +00:00
drh 736932c1eb Add the OR-optimization to WITHOUT ROWID tables.
FossilOrigin-Name: 06a23b8b32f0439b22936dc4107890481e4a1327
2014-05-26 22:05:46 +00:00
drh 5609baf35e Minor enhancements to comments and clarification of the code.
FossilOrigin-Name: cbec30d0c49a3f618c3df3ae0ca3d651b48841c2
2014-05-26 22:01:00 +00:00
drh 68c121534c Add a missing VdbeCoverage() macro on an OP_Found opcode added in the previous
check-in.

FossilOrigin-Name: b4980a07e287480beddb2c6633c733520e05d074
2014-05-26 20:25:34 +00:00
dan f97dad8849 Enable the OR optimization for WITHOUT ROWID tables. Use a temp table instead of the RowSet object to track the rows that have already been included in the result set.
FossilOrigin-Name: 2c7e277bbebd5c93dec53d381d9737909d40d846
2014-05-26 20:06:45 +00:00
dan 6a8ac852aa Fix a problem in the shell when importing CSV files. If the leftmost field of the first row in the CSV file was both zero bytes in size and unquoted, no data was imported.
FossilOrigin-Name: 856d44a206d82e96265103556dedda39ca3602b1
2014-05-26 18:27:12 +00:00
dan cde81d5fd0 Fix a problem in FTS4 where columns with names that are prefixes of any notindexed column were also being (incorrectly) marked as not indexed. For example in "CREATE ... t1(abc, bc, abcd, notindexed=abcd)", both abc and abcd were being treated as notindexed.
FossilOrigin-Name: d90c4964fcf46b0b043dbfd58267098582267001
2014-05-26 16:40:02 +00:00
drh 935850ef75 Remove references in comments to VDBE opcodes that no longer exist. This
is a documentation change only; no changes to code.

FossilOrigin-Name: ebfb51fe40756713d269b4c0ade752666910bb6e
2014-05-24 17:15:15 +00:00
dan e96f2df3dd Changes to the output of EXPLAIN QUERY PLAN to make it clearer when a query uses the PRIMARY KEY index of a WITHOUT ROWID table.
FossilOrigin-Name: 9268df305b90ac11e44b3107bbab5becf38860b7
2014-05-23 17:17:06 +00:00
drh 43ae8f6f4d In the command-line shell, if three or more interrupt signals (control-c)
are received in a row without a response from sqlite3_interrupt() then
call exit(1) immediately.  This allows control-C to interrupt the shell
even if it is stuck in a computation or loop that does not involve the
VDBE.

FossilOrigin-Name: b5cde57166fd874d00dec23d3a59bf3a23979fc5
2014-05-23 12:03:47 +00:00
drh e48ae7157a Make sure sufficient VDBE registers are allocated for an INSERT...SELECT
when there is an idlist on the insert table that includes an explicit
rowid.  Ticket [9654505cfda93610585fde5a9bbf2e730c8a8d5]

FossilOrigin-Name: 9a2dd18776cc7003752980be0a0920a8799e5f35
2014-05-23 11:48:57 +00:00
dan 6044f31d13 Add a test for the EQP output of a skip-scan query that uses the PK index of a WITHOUT ROWID table.
FossilOrigin-Name: 10238fad94a198c0639461645227b6c5ebe16eee
2014-05-22 09:58:45 +00:00
drh c9bbb01180 Do not burn memory remembering CHECK constraints in a read-only database.
FossilOrigin-Name: 34ddf02d3d21151b8099c0c25706530a03d93887
2014-05-21 08:48:18 +00:00
drh 781597feca Fix the sqlite3_db_readonly() API so that it reports true if the database
is readonly because the file format write version (byte 18 of the header)
is too large.

FossilOrigin-Name: 8d8af114dac301335ec10671c1e9a5a6d8266a60
2014-05-21 08:21:07 +00:00
dan 27f2468422 Internally, use a 64-bit integers for segment level numbers.
FossilOrigin-Name: 8180e320ee4090e41511836678e49a98c0b228e8
2014-05-17 16:56:52 +00:00
dan 83e05b814e Fix a broken test case in fts4growth2.test.
FossilOrigin-Name: 9fde5b960af39b187474e5b2909ff0e56d5e0bf9
2014-05-17 15:10:37 +00:00
mistachkin 02c1e264a9 Fix harmless compiler warnings.
FossilOrigin-Name: 7e60347e21a7473974061965a8d1f2eadde987e2
2014-05-16 23:38:59 +00:00
mistachkin 77a90ce811 Work around compilation issue with MSVC.
FossilOrigin-Name: 9623a29c11e3a90513016ea3306c085d2bf91b62
2014-05-16 23:15:50 +00:00
dan 4bd855fae5 Fixes to prevent an FTS index from growing indefinitely as the corresponding table is updated. Change the FTS 'automerge' option to allow the user to specify the number of segments that should be merged simultaneously by auto-merges.
FossilOrigin-Name: a75f1800021d30b712053373440041b7b355a36a
2014-05-16 16:16:59 +00:00
dan e82384817d Add extra test to backcompat.test to ensure that old and new versions of FTS may work together on the same incremental merge operation.
FossilOrigin-Name: 3997d47bb9c8593a2cd30317ea65163b99db1832
2014-05-16 15:48:17 +00:00
drh c007f61bb0 Repurpose the SQLITE_TESTCTRL_FAULT_INSTALL test-control to register a
callback to be invoked by sqlite3FaultSim().  That test-control has been
unused since 2008-06-20 and was never used in any official release.

FossilOrigin-Name: 0d43a7ad9abe821e33e0bf83a997aa4461b1e3f2
2014-05-16 14:17:01 +00:00
dan a7b9e7d2d9 Fix a bug causing an incorrect segment size value to be stored if both an old and new FTS version performed work on the same incremental merge operation.
FossilOrigin-Name: a9a2aeab298ba2ac0b8835e61406e2d83bf7e39b
2014-05-16 10:30:44 +00:00
dan df2c52f728 Merge latest trunk changes with this branch.
FossilOrigin-Name: 5809986ffcc5d9cbab64760f8d7fbfbb6b626ee7
2014-05-15 19:05:55 +00:00
dan 157c957a65 Fix a problem with the handling of delete markers by automerge on large databases.
FossilOrigin-Name: 2b09bd17eb85ea3c682e930d2aabc6441f2265e0
2014-05-15 18:36:39 +00:00
dan 5b34f15a82 Do not search for promotable segments following an FTS 'optimize' operation or creation of a new segment on the oldest existing level.
FossilOrigin-Name: 34f6b4b8e4cb8ea45fd518672dc96335d1ce06ab
2014-05-14 19:49:17 +00:00
dan a0b7ca90b7 Fix a problem to do with loading the value of the FTS automerge setting from the database.
FossilOrigin-Name: 7268119f74602929b372b88eca7b3c3b4964f7d5
2014-05-14 18:45:27 +00:00
dan 9e83e465eb Fix various problems to do with segment promotion. Add test file fts4growth2.test, containing tests to check that the FTS index does not grow indefinitely as the table is updated.
FossilOrigin-Name: 21491a9bc686e63bec32f1a67103622f1160a2f9
2014-05-14 15:58:47 +00:00
dan c0caea21de Fix a problem preventing delete markers from ever being removed from the FTS index.
FossilOrigin-Name: 7f47ae5c5ddb1227484ddae7c6960183932a052a
2014-05-13 20:11:37 +00:00
mistachkin a5e2b50d0a Improve a comment in the MSVC makefile. No changes to code.
FossilOrigin-Name: 0901dccedaf5679691ba803ec76d113de170185d
2014-05-12 22:36:50 +00:00
mistachkin 548ff8f491 Add VSIX packaging support for Windows Phone 8.1 using Visual Studio 2013 Update 2.
FossilOrigin-Name: 013738f3d531078fb47f9992c18a0d630e771a32
2014-05-12 21:12:04 +00:00
dan 6bb9889ef0 Experimental code to prevent FTS indexes from growing indefinitely as the table is updated.
FossilOrigin-Name: b3b505a4dd0c679437a4272109f1188175088cd1
2014-05-12 20:04:48 +00:00
mistachkin 0f710546e7 In mutex_w32.c, make inclusion of the Windows header file dependent on SQLITE_OS_WIN, not SQLITE_MUTEX_W32.
FossilOrigin-Name: 93ffbcc0b1d207950851dbb16a8c101afb949d5f
2014-05-12 15:37:03 +00:00
mistachkin 796407395e Merge updates from trunk. Emit the AppliesTo and DependsOn SDK manifest attributes when building the VSIX for Windows Phone 8.1.
FossilOrigin-Name: f6237a5f190bd5693ceed0ca1f048c3ec2a4da67
2014-05-10 17:33:11 +00:00
mistachkin 1273614191 When using Visual Studio 2013, add the appropriate MaxPlatformVersion attribute to the VSIX SDK manifest.
FossilOrigin-Name: 0a4f59676bd0ab33b2c86c9a35a2ebbdbaf09ee7
2014-05-10 17:28:45 +00:00
mistachkin d9b3c549b3 Further MSVC makefile changes to support Windows Phone 8.1.
FossilOrigin-Name: a9c81815e1b7a9c05da61f75edac45cb1a954135
2014-05-09 23:31:55 +00:00
mistachkin 52c40a89bb Merge updates from trunk.
FossilOrigin-Name: f4fea7bb8a4b118bdceff400a6c49c6291c0d58e
2014-05-09 20:54:07 +00:00
mistachkin 4712c21287 When cross-compiling with the MSVC makefile, make sure the correct library path is used. Also, keep track of the required compilation options separately.
FossilOrigin-Name: c3dce2e7390eec3a337be1b99f80ad5f721cc647
2014-05-09 20:51:17 +00:00
drh 2e7be08152 Include sqlite3rtree.h in the tsrc/ pile of source files during
target_source in the main.mk makefile.

FossilOrigin-Name: 116bed5af664899a73b46dca528ac0c021fc50c3
2014-05-07 21:16:56 +00:00
drh 9ee8810be2 Remove a superfluous variable initialization.
FossilOrigin-Name: 68766f837491cb89c2103f2627eb9e23ab326a68
2014-05-07 20:33:17 +00:00
drh 8009c9b439 A better fix for the group_concat() problem.
FossilOrigin-Name: 1c086deebd0eb442918972e4b9185a5a0db3b8c3
2014-05-07 20:24:00 +00:00
dan d2d8ca600e Fix the way parenthesis in MATCH expressions are handled by FTS if the tokenizer considers them to be token characters.
FossilOrigin-Name: e21bf7a2ade6373e94ea403c665f78e1ad22143f
2014-05-07 19:59:36 +00:00
drh faecf50504 Make sure the group_concat() function returns an empty string, not a NULL,
if it has at least one input row. Fix for ticket [55746f9e65f8587].

FossilOrigin-Name: d01cedaa73d8f9e5502502a1068a9509d1de295c
2014-05-07 18:23:04 +00:00
drh 86a1119133 Ensure that the sqlite3StrAccumAppend() routine is never called with a NULL
second argument.  Doing so is harmless when N==0, but it causes an assert()
to fail that was placed to quiet static analyzers.

FossilOrigin-Name: f03fbf3700d9d4a654e3aa2e5caa810a8416bed9
2014-05-07 18:21:56 +00:00
drh eacc050f30 Make sure the group_concat() function returns an empty string, not a NULL,
if it has at least one input row.  Fix for ticket [55746f9e65f8587].

FossilOrigin-Name: 0deac8737545a020d344be96fff16660a7977ab8
2014-05-07 17:19:31 +00:00
drh 731dc0cb0e Add the SQLITE_IOCAP_IMMUTABLE bit as a possible return value from
the xDeviceCharacteristics method in the VFS.  Add the "nolock" and
"immutable" query parameters to URI filenames.

FossilOrigin-Name: 1a0d7d3d9dd54b783e3a805961287dd01f94770c
2014-05-07 15:46:04 +00:00
drh 6451c2b04e Fix nolock and immutable so that they work even if READONLY is requested.
FossilOrigin-Name: e193aced2942e7405d0f45f90d4954b5663b4ba5
2014-05-07 15:32:03 +00:00
drh 62e603a904 Add test cases and documentation for the nolock and immutable query
parameters.

FossilOrigin-Name: 19d56cbaca222b32e2e354063149cccd89441d73
2014-05-07 15:09:24 +00:00
mistachkin f253813b40 Merge updates from trunk.
FossilOrigin-Name: 69698ae90c415cb32d2c144725853483da65f0ff
2014-05-06 21:37:52 +00:00
mistachkin 6117272e03 Update the template VSIX package file as well.
FossilOrigin-Name: 99d96765cc378fde7b285f4577ea2b5d130d9a61
2014-05-06 21:37:10 +00:00
mistachkin f574259a64 Merge updates from trunk.
FossilOrigin-Name: 7579c44ac1865133c37b16f2acc074d1eed4fdfd
2014-05-06 21:30:25 +00:00
mistachkin 441aa095ed Enhance the VSIX package creation tool to better support Visual Studio 2013.
FossilOrigin-Name: c1fb04f61eb74d80d1b7607ae6904fe2e1717988
2014-05-06 21:26:34 +00:00
mistachkin 897f6833fc Refactor VSIX package creation tool to better support Visual Studio 2013.
FossilOrigin-Name: 8be166af239cbdaff3937c4003a6dc6e8a96e53a
2014-05-06 00:09:46 +00:00
mistachkin 75cc2f7a14 Merge updates from trunk.
FossilOrigin-Name: 668ed76ac6cfd5810aea7319c752d77fafaab319
2014-05-05 22:50:19 +00:00
mistachkin 7dd9fb65e2 When building for Windows 8.0 using Visual Studio 2013, make sure the cross-compilation native library path is set correctly.
FossilOrigin-Name: c1ab9092e29bc9d172c1f1a3becbcc83b79f2080
2014-05-05 22:43:17 +00:00
mistachkin 220942b757 More modularization work on the MSVC batch build tool.
FossilOrigin-Name: 9a06773acc181e981f61f476a8e56417b98beba9
2014-05-05 21:08:47 +00:00
mistachkin 2347e3b1bb Merge updates from trunk.
FossilOrigin-Name: eaa8fc810fcff8171b6c5cff8c661a6faf0e023b
2014-05-05 20:35:44 +00:00
mistachkin bd6e51c0f9 Merge updates from trunk.
FossilOrigin-Name: 6f07f20e41446212a86989a5e6ce7f12998a3ae3
2014-05-05 17:49:16 +00:00
drh 57fe136b23 Take out the special handling of nolock=true in os_win.c and add it to
pager.c, so that it works for all VFSes.  Add the pPager->noLock boolean
for clarity.

FossilOrigin-Name: 725c1c14be331bce9bf074960dbfa7b6d4c1ba87
2014-05-01 01:49:22 +00:00
drh 48cdabcb1a Avoid unnecessary xUnlock operations on temp file.
FossilOrigin-Name: 1829c38c3233c8cb194fae6d560d35a8916b1348
2014-05-01 01:20:05 +00:00
drh d1ae96d39e Add the immutable=TRUE query parameter and SQLITE_IOCAP_IMMUTABLE, either
of which prevents locking of the database and omits tests for existance
of journal files.

FossilOrigin-Name: 71f152c85d79ebd9ca48bc9c4c71fc4debaf2437
2014-05-01 01:13:08 +00:00
drh fb4c9242a5 Merge in all recent changes and enhancements from trunk.
FossilOrigin-Name: 84243f844417f888ab731841f7dbf95749f6e034
2014-04-30 20:32:41 +00:00
drh f34a9fef4c Change from using the win32-none VFS to just a query parameter.
FossilOrigin-Name: ffceacf61905dc3553978ba5f68e133947eca2fa
2014-04-22 19:42:22 +00:00
mistachkin 9df245b073 Add some OSTRACE calls for consistency.
FossilOrigin-Name: be292d559748a24ff012266a1f58ce6c027e0411
2014-04-22 19:34:16 +00:00
drh 0bf8277196 Add the win32-none VFS which omits rollback-journal locking.
FossilOrigin-Name: 03e3c5a8b17a219a49bfbe79b7debd27ace8ad85
2014-04-22 19:30:00 +00:00
mistachkin e756bfb363 Preliminary changes to support building VSIX packages for Windows 8.0 and Windows Phone 8.0 using Visual Studio 2013.
FossilOrigin-Name: 3bf97c811a25babf760f256245c756ed6710f8ba
2014-04-21 18:00:11 +00:00
mistachkin 00b638bb6f Preliminary changes to support building VSIX packages for Windows Phone 8.1.
FossilOrigin-Name: a1b2f28ba85b043df68875f5d3446140db4f2cb0
2014-04-18 00:08:13 +00:00
58 changed files with 2535 additions and 436 deletions
+95 -27
View File
@@ -1,6 +1,9 @@
#
# nmake Makefile for SQLite
#
###############################################################################
############################## START OF OPTIONS ###############################
###############################################################################
# The toplevel directory of the source tree. This is the directory
# that contains this "Makefile.msc".
@@ -13,6 +16,13 @@ TOP = .
USE_AMALGAMATION = 1
!ENDIF
# Set this non-0 to use the library paths and other options necessary for
# Windows Phone 8.1.
#
!IFNDEF USE_WP81_OPTS
USE_WP81_OPTS = 0
!ENDIF
# Set this non-0 to split the SQLite amalgamation file into chunks to
# be used for debugging with Visual Studio.
#
@@ -116,6 +126,25 @@ DEBUG = 0
OPTIMIZATIONS = 2
!ENDIF
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
###############################################################################
############################### END OF OPTIONS ################################
###############################################################################
# This assumes that MSVC is always installed in 32-bit Program Files directory
# and sets the variable for use in locating other 32-bit installs accordingly.
#
PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\..
PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\)
# Check for the predefined command macro CC. This should point to the compiler
# binary for the target platform. If it is not defined, simply define it to
# the legacy default value 'cl.exe'.
@@ -140,6 +169,15 @@ LD = link.exe
RC = rc.exe
!ENDIF
# Check for the MSVC runtime library path macro. Othertise, this value will
# default to the 'lib' directory underneath the MSVC installation directory.
#
!IFNDEF CRTLIBPATH
CRTLIBPATH = $(VCINSTALLDIR)\lib
!ENDIF
CRTLIBPATH = $(CRTLIBPATH:\\=\)
# Check for the command macro NCC. This should point to the compiler binary
# for the platform the compilation process is taking place on. If it is not
# defined, simply define it to have the same value as the CC macro. When
@@ -168,8 +206,8 @@ NCC = $(NCC:\\=\)
NCC = $(CC)
!ENDIF
# Check for the MSVC runtime library path macro. Othertise, this
# value will default to the 'lib' directory underneath the MSVC
# Check for the MSVC native runtime library path macro. Othertise,
# this value will default to the 'lib' directory underneath the MSVC
# installation directory.
#
!IFNDEF NCRTLIBPATH
@@ -306,7 +344,6 @@ TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF
#
# Prevent warnings about "insecure" MSVC runtime library functions
# being used.
#
@@ -314,28 +351,24 @@ TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
#
# Prevent warnings about "deprecated" POSIX functions being used.
#
TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
#
# Use the SQLite debugging heap subsystem?
#
!IF $(MEMDEBUG)!=0
TCC = $(TCC) -DSQLITE_MEMDEBUG=1
RCC = $(RCC) -DSQLITE_MEMDEBUG=1
#
# Use native Win32 heap subsystem instead of malloc/free?
#
!ELSEIF $(WIN32HEAP)!=0
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
#
# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>2
@@ -430,25 +463,25 @@ RCC = $(RCC) -DSQLITE_TEMP_STORE=1
# The same set of OMIT and ENABLE flags should be passed to the
# LEMON parser generator and the mkkeywordhash tool as well.
# BEGIN standard options
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
# END standard options
# These are the required SQLite compilation options used when compiling for
# the Windows platform.
#
REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
# BEGIN required Windows option
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
# END required Windows option
# Add the required and optional SQLite compilation options into the command
# lines used to invoke the MSVC code and resource compilers.
#
TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS)
RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS)
TCC = $(TCC) $(OPT_FEATURE_FLAGS)
RCC = $(RCC) $(OPT_FEATURE_FLAGS)
# Add in any optional parameters specified on the make commane line
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
# Add in any optional parameters specified on the commane line, e.g.
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
#
TCC = $(TCC) $(OPTS)
RCC = $(RCC) $(OPTS)
# If compiling for debugging, add some defines.
#
!IF $(DEBUG)>0
TCC = $(TCC) -D_DEBUG
BCC = $(BCC) -D_DEBUG
@@ -457,6 +490,7 @@ RCC = $(RCC) -D_DEBUG
# If optimizations are enabled or disabled (either implicitly or
# explicitly), add the necessary flags.
#
!IF $(DEBUG)>0 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
@@ -472,12 +506,14 @@ BCC = $(BCC) -O1
!ENDIF
# If symbols are enabled (or compiling for debugging), enable PDBs.
#
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
BCC = $(BCC) -Zi
!ENDIF
# If ICU support is enabled, add the compiler options for it.
#
!IF $(USE_ICU)!=0
TCC = $(TCC) -DSQLITE_ENABLE_ICU=1
RCC = $(RCC) -DSQLITE_ENABLE_ICU=1
@@ -489,6 +525,7 @@ RCC = $(RCC) -I$(ICUINCDIR)
# Command line prefixes for compiling code, compiling resources,
# linking, etc.
#
LTCOMPILE = $(TCC) -Fo$@
LTRCOMPILE = $(RCC) -r
LTLIB = lib.exe
@@ -512,13 +549,13 @@ LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
!IF "$(VISUALSTUDIOVERSION)"=="12.0"
!IFNDEF STORELIBPATH
!IF "$(PLATFORM)"=="x86"
STORELIBPATH = $(NCRTLIBPATH)\store
STORELIBPATH = $(CRTLIBPATH)\store
!ELSEIF "$(PLATFORM)"=="x64"
STORELIBPATH = $(NCRTLIBPATH)\store\amd64
STORELIBPATH = $(CRTLIBPATH)\store\amd64
!ELSEIF "$(PLATFORM)"=="ARM"
STORELIBPATH = $(NCRTLIBPATH)\store\arm
STORELIBPATH = $(CRTLIBPATH)\store\arm
!ELSE
STORELIBPATH = $(NCRTLIBPATH)\store
STORELIBPATH = $(CRTLIBPATH)\store
!ENDIF
!ENDIF
STORELIBPATH = $(STORELIBPATH:\\=\)
@@ -526,24 +563,55 @@ LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)"
!ENDIF
!ENDIF
# When compiling for Windows Phone 8.1, an extra library path is
# required.
#
!IF $(USE_WP81_OPTS)!=0
!IFNDEF WP81LIBPATH
!IF "$(PLATFORM)"=="x86"
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
!ELSEIF "$(PLATFORM)"=="ARM"
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM
!ELSE
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
!ENDIF
!ENDIF
!ENDIF
# When compiling for Windows Phone 8.1, some extra linker options
# are also required.
#
!IF $(USE_WP81_OPTS)!=0
!IFDEF WP81LIBPATH
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)"
!ENDIF
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
!ENDIF
# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG
!ENDIF
# Start with the Tcl related linker options.
#
!IF $(NO_TCL)==0
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)
LTLIBS = $(LIBTCL)
!ENDIF
# If ICU support is enabled, add the linker options for it.
#
!IF $(USE_ICU)!=0
LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
LTLIBS = $(LTLIBS) $(LIBICU)
!ENDIF
# nawk compatible awk.
#
!IFNDEF NAWK
NAWK = gawk.exe
!ENDIF
@@ -962,7 +1030,7 @@ lempar.c: $(TOP)\src\lempar.c
copy $(TOP)\src\lempar.c .
lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLIBPATHS)
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
# Rules to build individual *.lo files from generated *.c files. This
# applies to:
@@ -1222,7 +1290,7 @@ parse.h: parse.c
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
del /Q parse.y parse.h parse.h.temp
copy $(TOP)\src\parse.y .
.\lemon.exe $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
move parse.h parse.h.temp
$(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h
@@ -1230,7 +1298,7 @@ sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) -Fe$@ $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLIBPATHS)
$(BCC) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
.\mkkeywordhash.exe > keywordhash.h
+9 -4
View File
@@ -1333,7 +1333,7 @@ static int fts3InitVtab(
p->bHasStat = isFts4;
p->bFts4 = isFts4;
p->bDescIdx = bDescIdx;
p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->zContentTbl = zContent;
p->zLanguageid = zLanguageid;
zContent = 0;
@@ -1376,7 +1376,9 @@ static int fts3InitVtab(
int n = (int)strlen(p->azColumn[iCol]);
for(i=0; i<nNotindexed; i++){
char *zNot = azNotindexed[i];
if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
if( zNot && n==(int)strlen(zNot)
&& 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
){
p->abNotindexed[iCol] = 1;
sqlite3_free(zNot);
azNotindexed[i] = 0;
@@ -3302,7 +3304,10 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
int rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
){
int mxLevel = 0; /* Maximum relative level value in db */
int A; /* Incr-merge parameter A */
@@ -3310,7 +3315,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
assert( rc==SQLITE_OK || mxLevel==0 );
A = p->nLeafAdd * mxLevel;
A += (A/2);
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
}
sqlite3Fts3SegmentsClose(p);
return rc;
+2 -2
View File
@@ -210,13 +210,13 @@ struct Fts3Table {
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
char *zContentTbl; /* content=xxx option, or NULL */
char *zLanguageid; /* languageid=xxx option, or NULL */
u8 bAutoincrmerge; /* True if automerge=1 */
int nAutoincrmerge; /* Value configured by 'automerge' */
u32 nLeafAdd; /* Number of leaf blocks added this trans */
/* Precompiled statements used by the implementation. Each of these
** statements is run and reset within a single virtual table API call.
*/
sqlite3_stmt *aStmt[37];
sqlite3_stmt *aStmt[40];
char *zReadExprlist;
char *zWriteExprlist;
+104 -101
View File
@@ -185,40 +185,23 @@ static int getNextToken(
int rc;
sqlite3_tokenizer_cursor *pCursor;
Fts3Expr *pRet = 0;
int nConsumed = 0;
int i = 0;
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
/* Set variable i to the maximum number of bytes of input to tokenize. */
for(i=0; i<n; i++){
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
if( z[i]=='*' || z[i]=='"' ) break;
}
*pnConsumed = i;
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
int nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( (rc==SQLITE_OK || rc==SQLITE_DONE) && sqlite3_fts3_enable_parentheses ){
int i;
if( rc==SQLITE_DONE ) iStart = n;
for(i=0; i<iStart; i++){
if( z[i]=='(' ){
pParse->nNest++;
rc = fts3ExprParse(pParse, &z[i+1], n-i-1, &pRet, &nConsumed);
if( rc==SQLITE_OK && !pRet ){
rc = SQLITE_DONE;
}
nConsumed = (int)(i + 1 + nConsumed);
break;
}
if( z[i]==')' ){
rc = SQLITE_DONE;
pParse->nNest--;
nConsumed = i+1;
break;
}
}
}
if( nConsumed==0 && rc==SQLITE_OK ){
if( rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
pRet = (Fts3Expr *)fts3MallocZero(nByte);
if( !pRet ){
@@ -252,13 +235,14 @@ static int getNextToken(
}
}
nConsumed = iEnd;
*pnConsumed = iEnd;
}else if( i && rc==SQLITE_DONE ){
rc = SQLITE_OK;
}
pModule->xClose(pCursor);
}
*pnConsumed = nConsumed;
*ppExpr = pRet;
return rc;
}
@@ -508,6 +492,21 @@ static int getNextNode(
return getNextString(pParse, &zInput[1], ii-1, ppExpr);
}
if( sqlite3_fts3_enable_parentheses ){
if( *zInput=='(' ){
int nConsumed = 0;
pParse->nNest++;
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
}else if( *zInput==')' ){
pParse->nNest--;
*pnConsumed = (int)((zInput - z) + 1);
*ppExpr = 0;
return SQLITE_DONE;
}
}
/* If control flows to this point, this must be a regular token, or
** the end of the input. Read a regular token using the sqlite3_tokenizer
@@ -626,96 +625,100 @@ static int fts3ExprParse(
while( rc==SQLITE_OK ){
Fts3Expr *p = 0;
int nByte = 0;
rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
assert( nByte>0 || (rc!=SQLITE_OK && p==0) );
if( rc==SQLITE_OK ){
int isPhrase;
if( p ){
int isPhrase;
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
if( !pNot ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pNot->eType = FTSQUERY_NOT;
pNot->pRight = p;
p->pParent = pNot;
if( pNotBranch ){
pNot->pLeft = pNotBranch;
pNotBranch->pParent = pNot;
}
pNotBranch = pNot;
p = pPrev;
}else{
int eType = p->eType;
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
/* The isRequirePhrase variable is set to true if a phrase or
** an expression contained in parenthesis is required. If a
** binary operator (AND, OR, NOT or NEAR) is encounted when
** isRequirePhrase is set, this is a syntax error.
*/
if( !isPhrase && isRequirePhrase ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
pAnd = fts3MallocZero(sizeof(Fts3Expr));
if( !pAnd ){
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
if( !pNot ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pAnd->eType = FTSQUERY_AND;
insertBinaryOperator(&pRet, pPrev, pAnd);
pPrev = pAnd;
}
pNot->eType = FTSQUERY_NOT;
pNot->pRight = p;
p->pParent = pNot;
if( pNotBranch ){
pNot->pLeft = pNotBranch;
pNotBranch->pParent = pNot;
}
pNotBranch = pNot;
p = pPrev;
}else{
int eType = p->eType;
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
/* This test catches attempts to make either operand of a NEAR
** operator something other than a phrase. For example, either of
** the following:
**
** (bracketed expression) NEAR phrase
** phrase NEAR (bracketed expression)
**
** Return an error in either case.
*/
if( pPrev && (
/* The isRequirePhrase variable is set to true if a phrase or
** an expression contained in parenthesis is required. If a
** binary operator (AND, OR, NOT or NEAR) is encounted when
** isRequirePhrase is set, this is a syntax error.
*/
if( !isPhrase && isRequirePhrase ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
pAnd = fts3MallocZero(sizeof(Fts3Expr));
if( !pAnd ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pAnd->eType = FTSQUERY_AND;
insertBinaryOperator(&pRet, pPrev, pAnd);
pPrev = pAnd;
}
/* This test catches attempts to make either operand of a NEAR
** operator something other than a phrase. For example, either of
** the following:
**
** (bracketed expression) NEAR phrase
** phrase NEAR (bracketed expression)
**
** Return an error in either case.
*/
if( pPrev && (
(eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE)
|| (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR)
)){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
if( isPhrase ){
if( pRet ){
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
pPrev->pRight = p;
p->pParent = pPrev;
}else{
pRet = p;
)){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
}else{
insertBinaryOperator(&pRet, pPrev, p);
if( isPhrase ){
if( pRet ){
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
pPrev->pRight = p;
p->pParent = pPrev;
}else{
pRet = p;
}
}else{
insertBinaryOperator(&pRet, pPrev, p);
}
isRequirePhrase = !isPhrase;
}
isRequirePhrase = !isPhrase;
pPrev = p;
}
assert( nByte>0 );
}
assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) );
nIn -= nByte;
zIn += nByte;
pPrev = p;
}
if( rc==SQLITE_DONE && pRet && isRequirePhrase ){
+270 -35
View File
@@ -193,6 +193,7 @@ struct SegmentWriter {
int nSize; /* Size of allocation at aData */
int nData; /* Bytes of data in aData */
char *aData; /* Pointer to block from malloc() */
i64 nLeafData; /* Number of bytes of leaf data written */
};
/*
@@ -268,6 +269,10 @@ struct SegmentNode {
#define SQL_SELECT_INDEXES 35
#define SQL_SELECT_MXLEVEL 36
#define SQL_SELECT_LEVEL_RANGE2 37
#define SQL_UPDATE_LEVEL_IDX 38
#define SQL_UPDATE_LEVEL 39
/*
** This function is used to obtain an SQLite prepared statement handle
** for the statement identified by the second argument. If successful,
@@ -369,7 +374,18 @@ static int fts3SqlStmt(
/* SQL_SELECT_MXLEVEL
** Return the largest relative level in the FTS index or indexes. */
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'",
/* Return segments in order from oldest to newest.*/
/* 37 */ "SELECT level, idx, end_block "
"FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? "
"ORDER BY level DESC, idx ASC",
/* Update statements used while promoting segments */
/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? "
"WHERE level=? AND idx=?",
/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1"
};
int rc = SQLITE_OK;
sqlite3_stmt *pStmt;
@@ -1910,6 +1926,7 @@ static int fts3WriteSegdir(
sqlite3_int64 iStartBlock, /* Value for "start_block" field */
sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
sqlite3_int64 iEndBlock, /* Value for "end_block" field */
sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */
char *zRoot, /* Blob value for "root" field */
int nRoot /* Number of bytes in buffer zRoot */
){
@@ -1920,7 +1937,13 @@ static int fts3WriteSegdir(
sqlite3_bind_int(pStmt, 2, iIdx);
sqlite3_bind_int64(pStmt, 3, iStartBlock);
sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
sqlite3_bind_int64(pStmt, 5, iEndBlock);
if( nLeafData==0 ){
sqlite3_bind_int64(pStmt, 5, iEndBlock);
}else{
char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData);
if( !zEnd ) return SQLITE_NOMEM;
sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free);
}
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
@@ -2246,6 +2269,9 @@ static int fts3SegWriterAdd(
nDoclist; /* Doclist data */
}
/* Increase the total number of bytes written to account for the new entry. */
pWriter->nLeafData += nReq;
/* If the buffer currently allocated is too small for this entry, realloc
** the buffer to make it large enough.
*/
@@ -2317,13 +2343,13 @@ static int fts3SegWriterFlush(
pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
}
if( rc==SQLITE_OK ){
rc = fts3WriteSegdir(
p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot);
rc = fts3WriteSegdir(p, iLevel, iIdx,
pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot);
}
}else{
/* The entire tree fits on the root node. Write it to the segdir table. */
rc = fts3WriteSegdir(
p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
rc = fts3WriteSegdir(p, iLevel, iIdx,
0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData);
}
p->nLeafAdd++;
return rc;
@@ -2407,6 +2433,37 @@ static int fts3SegmentMaxLevel(
return sqlite3_reset(pStmt);
}
/*
** iAbsLevel is an absolute level that may be assumed to exist within
** the database. This function checks if it is the largest level number
** within its index. Assuming no error occurs, *pbMax is set to 1 if
** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK
** is returned. If an error occurs, an error code is returned and the
** final value of *pbMax is undefined.
*/
static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
/* Set pStmt to the compiled version of:
**
** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
**
** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
*/
sqlite3_stmt *pStmt;
int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
sqlite3_bind_int64(pStmt, 2,
((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
);
*pbMax = 0;
if( SQLITE_ROW==sqlite3_step(pStmt) ){
*pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL;
}
return sqlite3_reset(pStmt);
}
/*
** Delete all entries in the %_segments table associated with the segment
** opened with seg-reader pSeg. This function does not affect the contents
@@ -2942,6 +2999,140 @@ void sqlite3Fts3SegReaderFinish(
}
}
/*
** Decode the "end_block" field, selected by column iCol of the SELECT
** statement passed as the first argument.
**
** The "end_block" field may contain either an integer, or a text field
** containing the text representation of two non-negative integers separated
** by one or more space (0x20) characters. In the first case, set *piEndBlock
** to the integer value and *pnByte to zero before returning. In the second,
** set *piEndBlock to the first value and *pnByte to the second.
*/
static void fts3ReadEndBlockField(
sqlite3_stmt *pStmt,
int iCol,
i64 *piEndBlock,
i64 *pnByte
){
const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
if( zText ){
int i;
int iMul = 1;
i64 iVal = 0;
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
*piEndBlock = iVal;
while( zText[i]==' ' ) i++;
iVal = 0;
if( zText[i]=='-' ){
i++;
iMul = -1;
}
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
*pnByte = (iVal * (i64)iMul);
}
}
/*
** A segment of size nByte bytes has just been written to absolute level
** iAbsLevel. Promote any segments that should be promoted as a result.
*/
static int fts3PromoteSegments(
Fts3Table *p, /* FTS table handle */
sqlite3_int64 iAbsLevel, /* Absolute level just updated */
sqlite3_int64 nByte /* Size of new segment at iAbsLevel */
){
int rc = SQLITE_OK;
sqlite3_stmt *pRange;
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0);
if( rc==SQLITE_OK ){
int bOk = 0;
i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1;
i64 nLimit = (nByte*3)/2;
/* Loop through all entries in the %_segdir table corresponding to
** segments in this index on levels greater than iAbsLevel. If there is
** at least one such segment, and it is possible to determine that all
** such segments are smaller than nLimit bytes in size, they will be
** promoted to level iAbsLevel. */
sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
sqlite3_bind_int64(pRange, 2, iLast);
while( SQLITE_ROW==sqlite3_step(pRange) ){
i64 nSize = 0, dummy;
fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
if( nSize<=0 || nSize>nLimit ){
/* If nSize==0, then the %_segdir.end_block field does not not
** contain a size value. This happens if it was written by an
** old version of FTS. In this case it is not possible to determine
** the size of the segment, and so segment promotion does not
** take place. */
bOk = 0;
break;
}
bOk = 1;
}
rc = sqlite3_reset(pRange);
if( bOk ){
int iIdx = 0;
sqlite3_stmt *pUpdate1;
sqlite3_stmt *pUpdate2;
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
}
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0);
}
if( rc==SQLITE_OK ){
/* Loop through all %_segdir entries for segments in this index with
** levels equal to or greater than iAbsLevel. As each entry is visited,
** updated it to set (level = -1) and (idx = N), where N is 0 for the
** oldest segment in the range, 1 for the next oldest, and so on.
**
** In other words, move all segments being promoted to level -1,
** setting the "idx" fields as appropriate to keep them in the same
** order. The contents of level -1 (which is never used, except
** transiently here), will be moved back to level iAbsLevel below. */
sqlite3_bind_int64(pRange, 1, iAbsLevel);
while( SQLITE_ROW==sqlite3_step(pRange) ){
sqlite3_bind_int(pUpdate1, 1, iIdx++);
sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0));
sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1));
sqlite3_step(pUpdate1);
rc = sqlite3_reset(pUpdate1);
if( rc!=SQLITE_OK ){
sqlite3_reset(pRange);
break;
}
}
}
if( rc==SQLITE_OK ){
rc = sqlite3_reset(pRange);
}
/* Move level -1 to level iAbsLevel */
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pUpdate2, 1, iAbsLevel);
sqlite3_step(pUpdate2);
rc = sqlite3_reset(pUpdate2);
}
}
}
return rc;
}
/*
** Merge all level iLevel segments in the database into a single
** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
@@ -2966,6 +3157,7 @@ static int fts3SegmentMerge(
Fts3SegFilter filter; /* Segment term filter condition */
Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
int bIgnoreEmpty = 0; /* True to ignore empty segments */
i64 iMaxLevel = 0; /* Max level number for this index/langid */
assert( iLevel==FTS3_SEGCURSOR_ALL
|| iLevel==FTS3_SEGCURSOR_PENDING
@@ -2977,6 +3169,11 @@ static int fts3SegmentMerge(
rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel);
if( rc!=SQLITE_OK ) goto finished;
}
if( iLevel==FTS3_SEGCURSOR_ALL ){
/* This call is to merge all segments in the database to a single
** segment. The level of the new segment is equal to the numerically
@@ -2986,21 +3183,21 @@ static int fts3SegmentMerge(
rc = SQLITE_DONE;
goto finished;
}
rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
iNewLevel = iMaxLevel;
bIgnoreEmpty = 1;
}else if( iLevel==FTS3_SEGCURSOR_PENDING ){
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
}else{
/* This call is to merge all segments at level iLevel. find the next
** available segment index at level iLevel+1. The call to
** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
** a single iLevel+2 segment if necessary. */
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
assert( FTS3_SEGCURSOR_PENDING==-1 );
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
}
if( rc!=SQLITE_OK ) goto finished;
assert( csr.nSegment>0 );
assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
@@ -3017,7 +3214,7 @@ static int fts3SegmentMerge(
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
assert( pWriter );
assert( pWriter || bIgnoreEmpty );
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3DeleteSegdir(
@@ -3025,7 +3222,14 @@ static int fts3SegmentMerge(
);
if( rc!=SQLITE_OK ) goto finished;
}
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
if( pWriter ){
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
if( rc==SQLITE_OK ){
if( iLevel==FTS3_SEGCURSOR_PENDING || iNewLevel<iMaxLevel ){
rc = fts3PromoteSegments(p, iNewLevel, pWriter->nLeafData);
}
}
}
finished:
fts3SegWriterFree(pWriter);
@@ -3035,7 +3239,7 @@ static int fts3SegmentMerge(
/*
** Flush the contents of pendingTerms to level 0 segments.
** Flush the contents of pendingTerms to level 0 segments.
*/
int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
int rc = SQLITE_OK;
@@ -3051,14 +3255,19 @@ int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
** estimate the number of leaf blocks of content to be written
*/
if( rc==SQLITE_OK && p->bHasStat
&& p->bAutoincrmerge==0xff && p->nLeafAdd>0
&& p->nAutoincrmerge==0xff && p->nLeafAdd>0
){
sqlite3_stmt *pStmt = 0;
rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
rc = sqlite3_step(pStmt);
p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
if( rc==SQLITE_ROW ){
p->nAutoincrmerge = sqlite3_column_int(pStmt, 0);
if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8;
}else if( rc==SQLITE_DONE ){
p->nAutoincrmerge = 0;
}
rc = sqlite3_reset(pStmt);
}
}
@@ -3426,6 +3635,8 @@ struct IncrmergeWriter {
int iIdx; /* Index of *output* segment in iAbsLevel+1 */
sqlite3_int64 iStart; /* Block number of first allocated block */
sqlite3_int64 iEnd; /* Block number of last allocated block */
sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */
u8 bNoLeafData; /* If true, store 0 for segment size */
NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
};
@@ -3764,8 +3975,8 @@ static int fts3IncrmergeAppend(
nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
}
pWriter->nLeafData += nSpace;
blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
if( rc==SQLITE_OK ){
if( pLeaf->block.n==0 ){
pLeaf->block.n = 1;
@@ -3864,6 +4075,7 @@ static void fts3IncrmergeRelease(
pWriter->iStart, /* start_block */
pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
pWriter->iEnd, /* end_block */
(pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */
pRoot->block.a, pRoot->block.n /* root */
);
}
@@ -3965,7 +4177,11 @@ static int fts3IncrmergeLoad(
if( sqlite3_step(pSelect)==SQLITE_ROW ){
iStart = sqlite3_column_int64(pSelect, 1);
iLeafEnd = sqlite3_column_int64(pSelect, 2);
iEnd = sqlite3_column_int64(pSelect, 3);
fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData);
if( pWriter->nLeafData<0 ){
pWriter->nLeafData = pWriter->nLeafData * -1;
}
pWriter->bNoLeafData = (pWriter->nLeafData==0);
nRoot = sqlite3_column_bytes(pSelect, 4);
aRoot = sqlite3_column_blob(pSelect, 4);
}else{
@@ -4566,11 +4782,11 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
/*
** Attempt an incremental merge that writes nMerge leaf blocks.
**
** Incremental merges happen nMin segments at a time. The two
** segments to be merged are the nMin oldest segments (the ones with
** the smallest indexes) in the highest level that contains at least
** nMin segments. Multiple merges might occur in an attempt to write the
** quota of nMerge leaf blocks.
** Incremental merges happen nMin segments at a time. The segments
** to be merged are the nMin oldest segments (the ones with the smallest
** values for the _segdir.idx field) in the highest level that contains
** at least nMin segments. Multiple merges might occur in an attempt to
** write the quota of nMerge leaf blocks.
*/
int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
int rc; /* Return code */
@@ -4595,6 +4811,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
int bUseHint = 0; /* True if attempting to append */
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
/* Search the %_segdir table for the absolute level with the smallest
** relative level number that contains at least nMin segments, if any.
@@ -4648,6 +4865,19 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** to start work on some other level. */
memset(pWriter, 0, nAlloc);
pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
if( rc==SQLITE_OK ){
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
assert( bUseHint==1 || bUseHint==0 );
if( iIdx==0 || (bUseHint && iIdx==1) ){
int bIgnore = 0;
rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
if( bIgnore ){
pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
}
}
}
if( rc==SQLITE_OK ){
rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
}
@@ -4655,16 +4885,12 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
){
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
if( rc==SQLITE_OK ){
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
}else{
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
}
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
}else{
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
}
if( rc==SQLITE_OK && pWriter->nLeafEst ){
@@ -4686,7 +4912,13 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
}
}
if( nSeg!=0 ){
pWriter->nLeafData = pWriter->nLeafData * -1;
}
fts3IncrmergeRelease(p, pWriter, &rc);
if( nSeg==0 && pWriter->bNoLeafData==0 ){
fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData);
}
}
sqlite3Fts3SegReaderFinish(pCsr);
@@ -4773,7 +5005,10 @@ static int fts3DoAutoincrmerge(
){
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
p->bAutoincrmerge = fts3Getint(&zParam)!=0;
p->nAutoincrmerge = fts3Getint(&zParam);
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
p->nAutoincrmerge = 8;
}
if( !p->bHasStat ){
assert( p->bFts4==0 );
sqlite3Fts3CreateStatTable(&rc, p);
@@ -4782,7 +5017,7 @@ static int fts3DoAutoincrmerge(
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
if( rc ) return rc;
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
return rc;
+1
View File
@@ -210,6 +210,7 @@ SRC += \
$(TOP)/ext/icu/sqliteicu.h \
$(TOP)/ext/icu/icu.c
SRC += \
$(TOP)/ext/rtree/sqlite3rtree.h \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
+62 -57
View File
@@ -1,9 +1,9 @@
C Create\snew\sheader\sfile\s"os_setup.h"\sused\sto\sdetect\sthe\soperating\ssystem\nat\scompile-time,\sand\s"os_win.h"\sthat\scontains\swindows-specific\sheader\sin\nformation.
D 2014-05-05T20:32:15.817
C Add\sextra\schecking\sof\sthe\sdatabase\sextended\serror\scode.
D 2014-05-30T16:54:09.869
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc cf9737350840c56f1e46204aa310227b8183c221
F Makefile.msc 52911c6bfeaf9b40f47ef4615ab66d98ab0f2b3d
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
F VERSION 9f823c026c6a32fc5f84d212a8aae0a221dba45c
@@ -78,11 +78,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 41b1920b9a8657963f09cb93b208c2671c5568db
F ext/fts3/fts3.c 20bc65862cfcea0a39bb64a819f8fe92a8e144c1
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h bdeb9015405e8facffb8fc7e09174521a2a780f4
F ext/fts3/fts3Int.h 16cddf2d7b0e5f3681615ae1d8ca0e45fca44918
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
F ext/fts3/fts3_expr.c 351395fad6fcb16ecfc61db0861008a70101330c
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
@@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9
F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d
F ext/fts3/fts3_write.c 74c00329006c3ed6325ba4e5ab7c9b5fc99c8934
F ext/fts3/fts3_write.c 5ee9d894da74a5d15a3c317414fb8c84f1694fa4
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
@@ -144,7 +144,7 @@ F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
F main.mk 601f43d91e6c7043127ec192bf85c9a1ae940621
F main.mk cfa185eed4e0f7e9d28a2e3167cecaa9d6cb39f3
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -159,16 +159,16 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
F src/analyze.c 3596f863bb80126fe56ba217df5932749271efc8
F src/analyze.c e8c8a9d20beb2ad156321330e8f4fea002d8deee
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 6c9b51abd404ce5b78b173b6f2248e8cb824758c
F src/btree.h d79306df4ed9181b48916737fe8871a4392c4594
F src/btree.c 70c60a3807b2072982f184d9614e020d2953f89c
F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
F src/build.c 02665ca158431a0926b10cbd7d8178a4c9fc4a22
F src/build.c 927e39b6aaf872c7b28f154f6acfeb9a05a72442
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
@@ -176,18 +176,18 @@ F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/fkey.c a549cff9fe8b736cdae21650ea0af6de29b77619
F src/func.c 2e16316ec3a6365a0dc3e553c586f91b20f7f6c8
F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c ab34bea5af4fee9f956a0805a32463fb7f674d00
F src/insert.c a038daeadfb818aaadafa854f40f5623b6929d84
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c 0a8cfb6b2899649880e5874ac9bfd1c6f7c6a4a3
F src/main.c 40d0837e5d0597eadc47c3acc2fc95bdbd9250b8
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
@@ -199,16 +199,16 @@ F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
F src/mutex_w32.c ab08c0fc54b71979370ca7c8f42fc64a9f211ebb
F src/mutex_w32.c 9bcab6e699fdb20eae784237c36b299830fb3316
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
F src/os_win.c 485d06a93965f306c7281fca0937829292367234
F src/os_win.c 8dbf6c11780fe2eb96c1f289e664d0c7b2911d37
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
F src/pager.c ab62a24218d87dda1be641f6c5ad291bff78fd94
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
@@ -220,18 +220,18 @@ F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
F src/select.c 089c4d46f067a5cccae93524c6377f981ba99bd9
F src/shell.c 2afe7a7154e97be0c74c5feacf09626bda8493be
F src/sqlite.h.in bde98816e1ba0c9ffef50afe7b32f4e5a8f54fe0
F src/select.c 7df17ec5506c2427576d412bee0e6ea740e12563
F src/shell.c bfac06fb15f3cd0d447e2e72ab3a283fac301813
F src/sqlite.h.in a98eb3e8c86c934ea6f5bcfc6b69653dde2f4ed4
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h b2947801eccefd7ba3e5f14e1353289351a83cf3
F src/sqliteInt.h fccdc735c27b3dc12322fec7cdad8bc76be8d00b
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
F src/test1.c 899bddeb0c7fb2b8062de6f03af4a4e4f48f9df5
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test1.c 4edf8810c86d77ae7ac6d56d563965a9beeea2ce
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
@@ -272,29 +272,29 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
F src/update.c 01564b3c430f6c7b0a35afaf7aba7987206fa3a5
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
F src/util.c 2b5fb283a190aacdb286f7835a447c45b345b83c
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 7f359193bf2366cc914a9ece093ebf284e56acdc
F src/vdbe.c 9bfe6becfc094382ae213656fbe511055ad83a54
F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94
F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7
F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
F src/vdbeaux.c e493f38758c4b8f4ca2007cf6a700bd405d192f3
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
F src/vdbesort.c 4abb7c0f8f19b7d7d82f4558d5da1a30fdf9ea38
F src/vdbesort.c 44441d73b08b3a638dcdb725afffb87c6574ad27
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c 91dfd382273c3f67fcdc0ac4728f9140f91c6ab3
F src/where.c b3be5eb4193b6327c4a02fe91411df503fe770e8
F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -336,7 +336,7 @@ F test/autoindex1.test 762ff3f8e25d852aae55c6462ca166a80c0cde61
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 5f8ad58b3eaebc78cd2c66c65476a42e6f32b2ad
F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
@@ -456,7 +456,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 90b56d03a93a2e7bb90f88be6083a8ea53f11a0e
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
@@ -539,15 +539,16 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test 597b0b76e41f0d672e2731c4d7b631d628efd13f
F test/fts3d.test 95c17d1b67b33a5eac0bf5a0d11116a0c0ac7a3a
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479
F test/fts3defer2.test e880e3b65bdf999f4746cdaefa65f14a98b9b724
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 06f1a96facc8f3e4b1ad5cc001dc5c8e83e68b9f
F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
F test/fts3expr4.test 0713d94ab951ed88a8c3629a4889a48c55c4067c
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
@@ -569,16 +570,18 @@ F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
F test/fts4incr.test 361960ed3550e781f3f313e17e2182ef9cefc0e9
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 9695c7c6c32480ea9fc20a2b38ed1de0640bcaec
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test c2cbfc23d554c5bf8678d0fb271aa4f8ef94839c
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
@@ -619,7 +622,7 @@ F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test acf909b067b838eb55338d619e800e148c17f1f5
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3
@@ -697,7 +700,7 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
F test/misc1.test 441a0fafc7087f841db09fbfca54e7aea9f5a84c
F test/misc1.test 1201a037c24f982cc0e956cdaa34fcaf6439c417
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
@@ -715,6 +718,7 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -742,7 +746,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04
F test/permutations.test d8946218493c77806ec1029df473d8ed4ad9aef6
F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@@ -757,7 +761,7 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
@@ -813,13 +817,13 @@ F test/shell1.test f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1
F test/shell5.test fa5583230c0aea5c9ff33f0ac1e26b1e3f03d153
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f
F test/skipscan2.test d77f79cdbba25f0f6f35298136cff21a7d7a553a
F test/skipscan1.test 28c7faa41a0d7265040ecb0a0abd90c0904270b2
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
@@ -1004,7 +1008,7 @@ F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
F test/trace2.test e7a988fdd982cdec62f1f1f34b0360e6476d01a0
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
@@ -1102,10 +1106,11 @@ F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test 0ac23e5e8311b69d87245f4a85112de321031658
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
@@ -1118,7 +1123,7 @@ F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
F tool/build-all-msvc.bat 3ffc57eadcf6229ee8b940dde2cb2eac03813bf3 x
F tool/build-all-msvc.bat a0534c971b86fe95f1983f445db5b896d3394818 x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
@@ -1140,7 +1145,7 @@ F tool/mksqlite3c-noext.tcl 1712d3d71256ca1f297046619c89e77a4d7c8f6d
F tool/mksqlite3c.tcl ba274df71f5e6534b0a913c7c48eabfcbd0934b6
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
F tool/mksqlite3internalh.tcl b6514145a7d5321b47e64e19b8116cc44f973eb1
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@@ -1166,9 +1171,9 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P b5a72dfd59fba6a9938ac1afdec06a2e6809fd2d 3ac75725a66730566105ad184a988a8f80f51055
R 8d3da72aab741dd9279195207e6c8bd7
U drh
Z 892b3ce35265d0d6387ad7a7c3c1d88b
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P ed5a9eb4f30a395bc641e79254217c7d7cf0aa5d
R 35776e018c929a9d3407d29571ba8a8f
U mistachkin
Z b80ed398d4e8aaa5357d010e1790f177
+1 -1
View File
@@ -1 +1 @@
bd92e0f80c1158d810b0d47e38f2fe06ff24bb8c
f2906c44519d76db5bc36013369ae498b80655a8
+1 -1
View File
@@ -1002,7 +1002,7 @@ static void analyzeOneTable(
if( aGotoChng==0 ) continue;
/* Populate the register containing the index name. */
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
zIdxName = pTab->zName;
}else{
zIdxName = pIdx->zName;
+7 -6
View File
@@ -4218,12 +4218,6 @@ static const void *fetchPayload(
assert( cursorHoldsMutex(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 );
#if 0
if( pCur->info.nSize==0 ){
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
&pCur->info);
}
#endif
*pAmt = pCur->info.nLocal;
return (void*)(pCur->info.pCell + pCur->info.nHeader);
}
@@ -8526,3 +8520,10 @@ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
assert( mask==BTREE_BULKLOAD || mask==0 );
pCsr->hints = mask;
}
/*
** Return true if the given Btree is read-only.
*/
int sqlite3BtreeIsReadonly(Btree *p){
return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}
+1
View File
@@ -194,6 +194,7 @@ void sqlite3BtreeIncrblobCursor(BtCursor *);
void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
int sqlite3BtreeIsReadonly(Btree *pBt);
#ifndef NDEBUG
int sqlite3BtreeCursorIsValid(BtCursor*);
+14 -10
View File
@@ -757,7 +757,7 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){
*/
Index *sqlite3PrimaryKeyIndex(Table *pTab){
Index *p;
for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){}
for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
return p;
}
@@ -1286,7 +1286,7 @@ void sqlite3AddPrimaryKey(
p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
0, sortOrder, 0);
if( p ){
p->autoIndex = 2;
p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
}
pList = 0;
@@ -1306,7 +1306,10 @@ void sqlite3AddCheckConstraint(
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
if( pTab && !IN_DECLARE_VTAB ){
sqlite3 *db = pParse->db;
if( pTab && !IN_DECLARE_VTAB
&& !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
){
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
if( pParse->constraintName.n ){
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
@@ -1658,7 +1661,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
assert( pParse->pNewTable==pTab );
pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
if( pPk==0 ) return;
pPk->autoIndex = 2;
pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
pTab->iPKey = -1;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -1681,7 +1684,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int n;
if( pIdx->autoIndex==2 ) continue;
if( IsPrimaryKeyIndex(pIdx) ) continue;
for(i=n=0; i<nPk; i++){
if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
}
@@ -2761,7 +2764,7 @@ Index *sqlite3AllocateIndexObject(
**
** If the index is created successfully, return a pointer to the new Index
** structure. This is used by sqlite3AddPrimaryKey() to mark the index
** as the tables primary key (Index.autoIndex==2).
** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY)
*/
Index *sqlite3CreateIndex(
Parse *pParse, /* All information about this parse */
@@ -2976,7 +2979,7 @@ Index *sqlite3CreateIndex(
pIndex->pTable = pTab;
pIndex->onError = (u8)onError;
pIndex->uniqNotNull = onError!=OE_None;
pIndex->autoIndex = (u8)(pName==0);
pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE;
pIndex->pSchema = db->aDb[iDb].pSchema;
pIndex->nKeyCol = pList->nExpr;
if( pPIWhere ){
@@ -3088,7 +3091,7 @@ Index *sqlite3CreateIndex(
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int k;
assert( pIdx->onError!=OE_None );
assert( pIdx->autoIndex );
assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
assert( pIndex->onError!=OE_None );
if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
@@ -3311,7 +3314,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
pParse->checkSchema = 1;
goto exit_drop_index;
}
if( pIndex->autoIndex ){
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
"or PRIMARY KEY constraint cannot be dropped", 0);
goto exit_drop_index;
@@ -3970,7 +3973,8 @@ void sqlite3UniqueConstraint(
}
zErr = sqlite3StrAccumFinish(&errMsg);
sqlite3HaltConstraint(pParse,
(pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE,
IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
: SQLITE_CONSTRAINT_UNIQUE,
onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
}
+2 -2
View File
@@ -233,8 +233,8 @@ int sqlite3FkLocateIndex(
if( zKey==0 ){
/* If zKey is NULL, then this foreign key is implicitly mapped to
** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
** identified by the test (Index.autoIndex==2). */
if( pIdx->autoIndex==2 ){
** identified by the test. */
if( IsPrimaryKeyIndex(pIdx) ){
if( aiCol ){
int i;
for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
+1 -1
View File
@@ -1541,7 +1541,7 @@ static void groupConcatStep(
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
}
}
static void groupConcatFinalize(sqlite3_context *context){
+10 -3
View File
@@ -173,15 +173,22 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* isMutexInit */
0, /* isMallocInit */
0, /* isPCacheInit */
0, /* pInitMutex */
0, /* nRefInitMutex */
0, /* pInitMutex */
0, /* xLog */
0, /* pLogArg */
0, /* bLocaltimeFault */
#ifdef SQLITE_ENABLE_SQLLOG
0, /* xSqllog */
0 /* pSqllogArg */
0, /* pSqllogArg */
#endif
#ifdef SQLITE_VDBE_COVERAGE
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
#ifndef SQLITE_OMIT_BUILTIN_TEST
0, /* xTestCallback */
#endif
0 /* bLocaltimeFault */
};
/*
+4 -3
View File
@@ -614,6 +614,7 @@ void sqlite3Insert(
if( j>=pTab->nCol ){
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
ipkColumn = i;
bIdListInOrder = 0;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
pTabList, 0, pColumn->a[i].zName);
@@ -1462,7 +1463,7 @@ void sqlite3GenerateConstraintChecks(
** KEY values of this row before the update. */
int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
int op = OP_Ne;
int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
for(i=0; i<pPk->nKeyCol; i++){
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
@@ -1563,7 +1564,7 @@ void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
pik_flags = 0;
if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
}
@@ -1649,7 +1650,7 @@ int sqlite3OpenTableAndIndices(
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
int iIdxCur = iBase++;
assert( pIdx->pSchema==pTab->pSchema );
if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
*piDataCur = iIdxCur;
}
if( aToOpen==0 || aToOpen[i+1] ){
+23 -1
View File
@@ -3114,6 +3114,28 @@ int sqlite3_test_control(int op, ...){
break;
}
/*
** sqlite3_test_control(FAULT_INSTALL, xCallback)
**
** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called,
** if xCallback is not NULL.
**
** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
** is called immediately after installing the new callback and the return
** value from sqlite3FaultSim(0) becomes the return from
** sqlite3_test_control().
*/
case SQLITE_TESTCTRL_FAULT_INSTALL: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961
** sqlite3Config.xTestCallback = va_arg(ap, int(*)(int));
*/
typedef int(*TESTCALLBACKFUNC_t)(int);
sqlite3Config.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
rc = sqlite3FaultSim(0);
break;
}
/*
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
**
@@ -3423,5 +3445,5 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
}
+7 -5
View File
@@ -13,17 +13,19 @@
*/
#include "sqliteInt.h"
#if SQLITE_OS_WIN
/*
** Include the header file for the Windows VFS.
*/
#include "os_win.h"
#endif
/*
** The code in this file is only used if we are compiling multithreaded
** on a win32 system.
*/
#ifdef SQLITE_MUTEX_W32
/*
** Include the header file for the Windows VFS.
*/
#include "os_win.h"
/*
** Each recursive mutex is an instance of the following structure.
*/
+31 -12
View File
@@ -2825,7 +2825,7 @@ static int winGetReadLock(winFile *pFile){
pFile->lastErrno = osGetLastError();
/* No need to log a failure to lock */
}
OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
return res;
}
@@ -2849,7 +2849,7 @@ static int winUnlockReadLock(winFile *pFile){
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
"winUnlockReadLock", pFile->zPath);
}
OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
return res;
}
@@ -2924,8 +2924,16 @@ static int winLock(sqlite3_file *id, int locktype){
** If you are using this code as a model for alternative VFSes, do not
** copy this retry logic. It is a hack intended for Windows only.
*/
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
pFile->h, cnt, sqlite3ErrName(res)));
lastErrno = osGetLastError();
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
pFile->h, cnt, res));
if( lastErrno==ERROR_INVALID_HANDLE ){
pFile->lastErrno = lastErrno;
rc = SQLITE_IOERR_LOCK;
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
pFile->h, cnt, sqlite3ErrName(rc)));
return rc;
}
if( cnt ) sqlite3_win32_sleep(1);
}
gotPendingLock = res;
@@ -3010,7 +3018,7 @@ static int winLock(sqlite3_file *id, int locktype){
** non-zero, otherwise zero.
*/
static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
int rc;
int res;
winFile *pFile = (winFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -3018,17 +3026,17 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
assert( id!=0 );
if( pFile->locktype>=RESERVED_LOCK ){
rc = 1;
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
res = 1;
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
}else{
rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
if( rc ){
res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
if( res ){
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
}
rc = !rc;
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
res = !res;
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
}
*pResOut = rc;
*pResOut = res;
OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
pFile->h, pResOut, *pResOut));
return SQLITE_OK;
@@ -3169,6 +3177,17 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
}
#ifdef SQLITE_TEST
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
LPHANDLE phFile = (LPHANDLE)pArg;
HANDLE hOldFile = pFile->h;
pFile->h = *phFile;
*phFile = hOldFile;
OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
hOldFile, pFile->h));
return SQLITE_OK;
}
#endif
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
+39 -29
View File
@@ -626,7 +626,8 @@ struct Pager {
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
u8 tempFile; /* zFilename is a temporary file */
u8 tempFile; /* zFilename is a temporary or immutable file */
u8 noLock; /* Do not lock (except in WAL mode) */
u8 readOnly; /* True for a read-only database */
u8 memDb; /* True to inhibit all file I/O */
@@ -1091,7 +1092,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
if( isOpen(pPager->fd) ){
assert( pPager->eLock>=eLock );
rc = sqlite3OsUnlock(pPager->fd, eLock);
rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
if( pPager->eLock!=UNKNOWN_LOCK ){
pPager->eLock = (u8)eLock;
}
@@ -1115,7 +1116,7 @@ static int pagerLockDb(Pager *pPager, int eLock){
assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
rc = sqlite3OsLock(pPager->fd, eLock);
rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
pPager->eLock = (u8)eLock;
IOTRACE(("LOCK %p %d\n", pPager, eLock))
@@ -4674,30 +4675,38 @@ int sqlite3PagerOpen(
** + The value returned by sqlite3OsSectorSize()
** + The largest page size that can be written atomically.
*/
if( rc==SQLITE_OK && !readOnly ){
setSectorSize(pPager);
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
if( szPageDflt<pPager->sectorSize ){
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
}else{
szPageDflt = (u32)pPager->sectorSize;
}
}
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
{
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
int ii;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
szPageDflt = ii;
if( rc==SQLITE_OK ){
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
if( !readOnly ){
setSectorSize(pPager);
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
if( szPageDflt<pPager->sectorSize ){
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
}else{
szPageDflt = (u32)pPager->sectorSize;
}
}
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
{
int ii;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
szPageDflt = ii;
}
}
}
}
#endif
}
pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
|| sqlite3_uri_boolean(zFilename, "immutable", 0) ){
vfsFlags |= SQLITE_OPEN_READONLY;
goto act_like_temp_file;
}
}
}else{
/* If a temporary file is requested, it is not opened immediately.
@@ -4707,10 +4716,14 @@ int sqlite3PagerOpen(
** This branch is also run for an in-memory database. An in-memory
** database is the same as a temp-file that is never written out to
** disk and uses an in-memory rollback journal.
**
** This branch also runs for files marked as immutable.
*/
act_like_temp_file:
tempFile = 1;
pPager->eState = PAGER_READER;
pPager->eLock = EXCLUSIVE_LOCK;
pPager->eState = PAGER_READER; /* Pretend we already have a lock */
pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE locking mode */
pPager->noLock = 1; /* Do no locking */
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
}
@@ -4751,9 +4764,6 @@ int sqlite3PagerOpen(
/* pPager->nPage = 0; */
pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
/* pPager->state = PAGER_UNLOCK; */
#if 0
assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
#endif
/* pPager->errMask = 0; */
pPager->tempFile = (u8)tempFile;
assert( tempFile==PAGER_LOCKINGMODE_NORMAL
+4 -3
View File
@@ -4498,10 +4498,11 @@ static void explainSimpleCount(
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
pTab->zName,
pIdx ? " USING COVERING INDEX " : "",
pIdx ? pIdx->zName : ""
pTab->zName,
bCover ? " USING COVERING INDEX " : "",
bCover ? pIdx->zName : ""
);
sqlite3VdbeAddOp4(
pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
+3 -1
View File
@@ -697,7 +697,8 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){
*/
static void interrupt_handler(int NotUsed){
UNUSED_PARAMETER(NotUsed);
seenInterrupt = 1;
seenInterrupt++;
if( seenInterrupt>2 ) exit(1);
if( db ) sqlite3_interrupt(db);
}
#endif
@@ -2430,6 +2431,7 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
csv_append_char(&sCsv, 0); /* To ensure sCsv.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
+39 -3
View File
@@ -555,7 +555,10 @@ int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicate that a file cannot be deleted when open.
** flag indicate that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -570,6 +573,7 @@ int sqlite3_exec(
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
/*
** CAPI3REF: File Locking Levels
@@ -938,6 +942,12 @@ struct sqlite3_io_methods {
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -961,6 +971,7 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_HAS_MOVED 20
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
/*
** CAPI3REF: Mutex Handle
@@ -2774,6 +2785,30 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behavior requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
** "1") or "false" (or "off" or "no" or "0") to indicate that the
** [powersafe overwrite] property does or does not apply to the
** storage media on which the database file resides. ^The psow query
** parameter only works for the built-in unix and Windows VFSes.
**
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
** which if set disables file locking in rollback journal modes. This
** is useful for accessing a database on a filesystem that does not
** support locking. Caution: Database corruption might result if two
** or more processes write to the same database and any one of those
** processes uses nolock=1.
**
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
** parameter that indicates that the database file is stored on
** read-only media. ^When immutable is set, SQLite assumes that the
** database file cannot be changed, even by a process with higher
** privilege, and so the database is opened read-only and all locking
** and change detection is disabled. Caution: Setting the immutable
** property on a database file that does in fact change can result
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
** See also: [SQLITE_IOCAP_IMMUTABLE].
**
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
@@ -2803,8 +2838,9 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
+22 -3
View File
@@ -1694,7 +1694,7 @@ struct Index {
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
unsigned isResized:1; /* True if resizeIndexObject() has been called */
@@ -1707,6 +1707,16 @@ struct Index {
#endif
};
/*
** Allowed values for Index.idxType
*/
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
/* Return true if index X is a PRIMARY KEY index */
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
/*
** Each sample stored in the sqlite_stat3 table is represented in memory
** using a structure of this type. See documentation at the top of the
@@ -2709,11 +2719,10 @@ struct Sqlite3Config {
int isMutexInit; /* True after mutexes are initialized */
int isMallocInit; /* True after malloc is initialized */
int isPCacheInit; /* True after malloc is initialized */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
int bLocaltimeFault; /* True to fail localtime() calls */
#ifdef SQLITE_ENABLE_SQLLOG
void(*xSqllog)(void*,sqlite3*,const char*, int);
void *pSqllogArg;
@@ -2725,6 +2734,10 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
#ifndef SQLITE_OMIT_BUILTIN_TEST
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
};
/*
@@ -3026,6 +3039,12 @@ int sqlite3ParseUri(const char*,const char*,unsigned int*,
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
int sqlite3CodeOnce(Parse *);
#ifdef SQLITE_OMIT_BUILTIN_TEST
# define sqlite3FaultSim(X) SQLITE_OK
#else
int sqlite3FaultSim(int);
#endif
Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
int sqlite3BitvecSet(Bitvec*, u32);
+50
View File
@@ -117,6 +117,16 @@ int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
return TCL_OK;
}
#if SQLITE_OS_WIN
/*
** Decode a Win32 HANDLE object.
*/
int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
*phFile = (HANDLE)sqlite3TestTextToPtr(zA);
return TCL_OK;
}
#endif
extern const char *sqlite3ErrName(int);
#define t1ErrorName sqlite3ErrName
@@ -5210,6 +5220,7 @@ static int file_control_lockproxy_test(
return TCL_OK;
}
#if SQLITE_OS_WIN
/*
** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
**
@@ -5243,6 +5254,42 @@ static int file_control_win32_av_retry(
return TCL_OK;
}
/*
** tclcmd: file_control_win32_set_handle DB HANDLE
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
*/
static int file_control_win32_set_handle(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3 *db;
int rc;
HANDLE hFile = NULL;
char z[100];
if( objc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
return TCL_ERROR;
}
if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
return TCL_ERROR;
}
rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
(void*)&hFile);
sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
Tcl_AppendResult(interp, z, (char*)0);
return TCL_OK;
}
#endif
/*
** tclcmd: file_control_persist_wal DB PERSIST-FLAG
**
@@ -6472,7 +6519,10 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
#if SQLITE_OS_WIN
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
{ "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
#endif
{ "file_control_persist_wal", file_control_persist_wal, 0 },
{ "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
{ "file_control_vfsname", file_control_vfsname, 0 },
+86 -2
View File
@@ -568,7 +568,90 @@ static int testPendingByte(
rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte);
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return TCL_OK;
}
}
/*
** The sqlite3FaultSim() callback:
*/
static Tcl_Interp *faultSimInterp = 0;
static int faultSimScriptSize = 0;
static char *faultSimScript;
static int faultSimCallback(int x){
char zInt[30];
int i;
int isNeg;
int rc;
if( x==0 ){
memcpy(faultSimScript+faultSimScriptSize, "0", 2);
}else{
/* Convert x to text without using any sqlite3 routines */
if( x<0 ){
isNeg = 1;
x = -x;
}else{
isNeg = 0;
}
zInt[sizeof(zInt)-1] = 0;
for(i=sizeof(zInt)-2; i>0 && x>0; i--, x /= 10){
zInt[i] = (x%10) + '0';
}
if( isNeg ) zInt[i--] = '-';
memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
}
rc = Tcl_Eval(faultSimInterp, faultSimScript);
if( rc ){
fprintf(stderr, "fault simulator script failed: [%s]", faultSimScript);
rc = SQLITE_ERROR;
}else{
rc = atoi(Tcl_GetStringResult(faultSimInterp));
}
Tcl_ResetResult(faultSimInterp);
return rc;
}
/*
** sqlite3_test_control_fault_install SCRIPT
**
** Arrange to invoke SCRIPT with the integer argument to sqlite3FaultSim()
** appended, whenever sqlite3FaultSim() is called. Or, if SCRIPT is the
** empty string, cancel the sqlite3FaultSim() callback.
*/
static int faultInstallCmd(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
const char *zScript;
int nScript;
int rc;
if( argc!=1 && argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" SCRIPT\"", (void*)0);
}
zScript = argc==2 ? argv[1] : "";
nScript = (int)strlen(zScript);
if( faultSimScript ){
free(faultSimScript);
faultSimScript = 0;
}
if( nScript==0 ){
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, 0);
}else{
faultSimScript = malloc( nScript+100 );
if( faultSimScript==0 ){
Tcl_AppendResult(interp, "out of memory", (void*)0);
return SQLITE_ERROR;
}
memcpy(faultSimScript, zScript, nScript);
faultSimScript[nScript] = ' ';
faultSimScriptSize = nScript+1;
faultSimInterp = interp;
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, faultSimCallback);
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return SQLITE_OK;
}
/*
** sqlite3BitvecBuiltinTest SIZE PROGRAM
@@ -638,7 +721,8 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
{ "fake_big_file", (Tcl_CmdProc*)fake_big_file },
#endif
{ "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest },
{ "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
{ "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
{ "sqlite3_test_control_fault_install", (Tcl_CmdProc*)faultInstallCmd },
};
int i;
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
+53 -20
View File
@@ -127,8 +127,10 @@ struct Testvfs {
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_READ_MASK 0x00010000
#define TESTVFS_UNLOCK_MASK 0x00020000
#define TESTVFS_LOCK_MASK 0x00040000
#define TESTVFS_CKLOCK_MASK 0x00080000
#define TESTVFS_ALL_MASK 0x0003FFFF
#define TESTVFS_ALL_MASK 0x000FFFFF
#define TESTVFS_MAX_PAGES 1024
@@ -466,8 +468,15 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an tvfs-file.
*/
static int tvfsLock(sqlite3_file *pFile, int eLock){
TestvfsFd *p = tvfsGetFd(pFile);
return sqlite3OsLock(p->pReal, eLock);
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
char zLock[30];
sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1),
Tcl_NewStringObj(zLock, -1), 0, 0);
}
return sqlite3OsLock(pFd->pReal, eLock);
}
/*
@@ -476,6 +485,12 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
char zLock[30];
sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1),
Tcl_NewStringObj(zLock, -1), 0, 0);
}
if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
return SQLITE_IOERR_UNLOCK;
}
@@ -486,8 +501,13 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
*/
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
TestvfsFd *p = tvfsGetFd(pFile);
return sqlite3OsCheckReservedLock(p->pReal, pResOut);
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
0, 0, 0);
}
return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
}
/*
@@ -1111,26 +1131,32 @@ static int testvfs_obj_cmd(
break;
}
/* TESTVFS filter METHOD-LIST
**
** Activate special processing for those methods contained in the list
*/
case CMD_FILTER: {
static struct VfsMethod {
char *zName;
int mask;
} vfsmethod [] = {
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
{ "xShmMap", TESTVFS_SHMMAP_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
{ "xRead", TESTVFS_READ_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
{ "xAccess", TESTVFS_ACCESS_MASK },
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
{ "xUnlock", TESTVFS_UNLOCK_MASK },
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
{ "xShmMap", TESTVFS_SHMMAP_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
{ "xRead", TESTVFS_READ_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
{ "xAccess", TESTVFS_ACCESS_MASK },
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
{ "xUnlock", TESTVFS_UNLOCK_MASK },
{ "xLock", TESTVFS_LOCK_MASK },
{ "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
};
Tcl_Obj **apElem = 0;
int nElem = 0;
@@ -1162,6 +1188,12 @@ static int testvfs_obj_cmd(
break;
}
/*
** TESTVFS script ?SCRIPT?
**
** Query or set the script to be run when filtered VFS events
** occur.
*/
case CMD_SCRIPT: {
if( objc==3 ){
int nByte;
@@ -1248,6 +1280,7 @@ static int testvfs_obj_cmd(
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
{ "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
{ "immutable", SQLITE_IOCAP_IMMUTABLE },
{ 0, 0 }
};
Tcl_Obj *pRet;
+1 -1
View File
@@ -187,7 +187,7 @@ void sqlite3Update(
iIdxCur = iDataCur+1;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
if( pIdx->autoIndex==2 && pPk!=0 ){
if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){
iDataCur = pParse->nTab;
pTabList->a[0].iCursor = iDataCur;
}
+18
View File
@@ -31,6 +31,24 @@ void sqlite3Coverage(int x){
}
#endif
/*
** Give a callback to the test harness that can be used to simulate faults
** in places where it is difficult or expensive to do so purely by means
** of inputs.
**
** The intent of the integer argument is to let the fault simulator know
** which of multiple sqlite3FaultSim() calls has been hit.
**
** Return whatever integer value the test callback returns, or return
** SQLITE_OK if no test callback is installed.
*/
#ifndef SQLITE_OMIT_BUILTIN_TEST
int sqlite3FaultSim(int iTest){
int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
return xCallback ? xCallback(iTest) : SQLITE_OK;
}
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
+5 -5
View File
@@ -3464,7 +3464,7 @@ case OP_Close: {
** is greater than or equal to the key value. If there are no records
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGt P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -3478,7 +3478,7 @@ case OP_Close: {
** is greater than the key value. If there are no records greater than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
*/
/* Opcode: SeekLt P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -3492,7 +3492,7 @@ case OP_Close: {
** is less than the key value. If there are no records less than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLe P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -3506,7 +3506,7 @@ case OP_Close: {
** is less than or equal to the key value. If there are no records
** less than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT: /* jump, in3 */
case OP_SeekLE: /* jump, in3 */
@@ -6281,7 +6281,7 @@ case OP_Init: { /* jump */
if( zTrace ){
int i;
for(i=0; i<db->nDb; i++){
if( MASKBIT(i) & p->btreeMask)==0 ) continue;
if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
}
}
-1
View File
@@ -350,7 +350,6 @@ static int vdbeSorterIterInit(
rc = sqlite3OsRead(
pSorter->pTemp1, &pIter->aBuffer[iBuf], nRead, iStart
);
assert( rc!=SQLITE_IOERR_SHORT_READ );
}
if( rc==SQLITE_OK ){
+104 -24
View File
@@ -2718,13 +2718,20 @@ static void explainOneScan(
if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0
&& ALWAYS(pLoop->u.btree.pIndex!=0)
){
const char *zFmt;
Index *pIdx = pLoop->u.btree.pIndex;
char *zWhere = explainIndexRange(db, pLoop, pItem->pTab);
zMsg = sqlite3MAppendf(db, zMsg,
((flags & WHERE_AUTO_INDEX) ?
"%s USING AUTOMATIC %sINDEX%.0s%s" :
"%s USING %sINDEX %s%s"),
zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""),
pLoop->u.btree.pIndex->zName, zWhere);
assert( !(flags&WHERE_AUTO_INDEX) || (flags&WHERE_IDX_ONLY) );
if( !HasRowid(pItem->pTab) && IsPrimaryKeyIndex(pIdx) ){
zFmt = zWhere ? "%s USING PRIMARY KEY%.0s%s" : "%s%.0s%s";
}else if( flags & WHERE_AUTO_INDEX ){
zFmt = "%s USING AUTOMATIC COVERING INDEX%.0s%s";
}else if( flags & WHERE_IDX_ONLY ){
zFmt = "%s USING COVERING INDEX %s%s";
}else{
zFmt = "%s USING INDEX %s%s";
}
zMsg = sqlite3MAppendf(db, zMsg, zFmt, zMsg, pIdx->zName, zWhere);
sqlite3DbFree(db, zWhere);
}else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){
zMsg = sqlite3MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg);
@@ -3216,7 +3223,7 @@ static Bitmask codeOneLoopStart(
sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, iRowidReg);
sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
sqlite3VdbeAddOp2(v, OP_Seek, iCur, iRowidReg); /* Deferred seek */
}else{
}else if( iCur!=iIdxCur ){
Index *pPk = sqlite3PrimaryKeyIndex(pIdx->pTable);
iRowidReg = sqlite3GetTempRange(pParse, pPk->nKeyCol);
for(j=0; j<pPk->nKeyCol; j++){
@@ -3286,6 +3293,10 @@ static Bitmask codeOneLoopStart(
**
** B: <after the loop>
**
** Added 2014-05-26: If the table is a WITHOUT ROWID table, then
** use an ephermeral index instead of a RowSet to record the primary
** keys of the rows we have already seen.
**
*/
WhereClause *pOrWc; /* The OR-clause broken out into subterms */
SrcList *pOrTab; /* Shortened table list or OR-clause generation */
@@ -3300,6 +3311,7 @@ static Bitmask codeOneLoopStart(
int untestedTerms = 0; /* Some terms not completely tested */
int ii; /* Loop counter */
Expr *pAndExpr = 0; /* An ".. AND (...)" expression */
Table *pTab = pTabItem->pTab;
pTerm = pLoop->aLTerm[0];
assert( pTerm!=0 );
@@ -3332,7 +3344,8 @@ static Bitmask codeOneLoopStart(
}
/* Initialize the rowset register to contain NULL. An SQL NULL is
** equivalent to an empty rowset.
** equivalent to an empty rowset. Or, create an ephermeral index
** capable of holding primary keys in the case of a WITHOUT ROWID.
**
** Also initialize regReturn to contain the address of the instruction
** immediately following the OP_Return at the bottom of the loop. This
@@ -3343,9 +3356,16 @@ static Bitmask codeOneLoopStart(
** called on an uninitialized cursor.
*/
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
regRowset = ++pParse->nMem;
if( HasRowid(pTab) ){
regRowset = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
regRowset = pParse->nTab++;
sqlite3VdbeAddOp2(v, OP_OpenEphemeral, regRowset, pPk->nKeyCol);
sqlite3VdbeSetP4KeyInfo(pParse, pPk);
}
regRowid = ++pParse->nMem;
sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
}
iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
@@ -3381,11 +3401,16 @@ static Bitmask codeOneLoopStart(
}
}
/* Run a separate WHERE clause for each term of the OR clause. After
** eliminating duplicates from other WHERE clauses, the action for each
** sub-WHERE clause is to to invoke the main loop body as a subroutine.
*/
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr;
WhereInfo *pSubWInfo; /* Info for single OR-term scan */
Expr *pOrExpr = pOrTerm->pExpr; /* Current OR clause term */
int j1 = 0; /* Address of jump operation */
if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){
pAndExpr->pLeft = pOrExpr;
pOrExpr = pAndExpr;
@@ -3400,17 +3425,63 @@ static Bitmask codeOneLoopStart(
explainOneScan(
pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0
);
/* This is the sub-WHERE clause body. First skip over
** duplicate rows from prior sub-WHERE clauses, and record the
** rowid (or PRIMARY KEY) for the current row so that the same
** row will be skipped in subsequent sub-WHERE clauses.
*/
if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
int r;
r = sqlite3ExprCodeGetColumn(pParse, pTabItem->pTab, -1, iCur,
regRowid, 0);
sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset,
sqlite3VdbeCurrentAddr(v)+2, r, iSet);
VdbeCoverage(v);
int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
if( HasRowid(pTab) ){
r = sqlite3ExprCodeGetColumn(pParse, pTab, -1, iCur, regRowid, 0);
j1 = sqlite3VdbeAddOp4Int(v, OP_RowSetTest, regRowset, 0, r,iSet);
VdbeCoverage(v);
}else{
Index *pPk = sqlite3PrimaryKeyIndex(pTab);
int nPk = pPk->nKeyCol;
int iPk;
/* Read the PK into an array of temp registers. */
r = sqlite3GetTempRange(pParse, nPk);
for(iPk=0; iPk<nPk; iPk++){
int iCol = pPk->aiColumn[iPk];
sqlite3ExprCodeGetColumn(pParse, pTab, iCol, iCur, r+iPk, 0);
}
/* Check if the temp table already contains this key. If so,
** the row has already been included in the result set and
** can be ignored (by jumping past the Gosub below). Otherwise,
** insert the key into the temp table and proceed with processing
** the row.
**
** Use some of the same optimizations as OP_RowSetTest: If iSet
** is zero, assume that the key cannot already be present in
** the temp table. And if iSet is -1, assume that there is no
** need to insert the key into the temp table, as it will never
** be tested for. */
if( iSet ){
j1 = sqlite3VdbeAddOp4Int(v, OP_Found, regRowset, 0, r, nPk);
VdbeCoverage(v);
}
if( iSet>=0 ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, r, nPk, regRowid);
sqlite3VdbeAddOp3(v, OP_IdxInsert, regRowset, regRowid, 0);
if( iSet ) sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
}
/* Release the array of temp registers */
sqlite3ReleaseTempRange(pParse, r, nPk);
}
}
/* Invoke the main loop body as a subroutine */
sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
/* Jump here (skipping the main loop body subroutine) if the
** current sub-WHERE row is a duplicate from prior sub-WHEREs. */
if( j1 ) sqlite3VdbeJumpHere(v, j1);
/* The pSubWInfo->untestedTerms flag means that this OR term
** contained one or more AND term from a notReady table. The
** terms from the notReady table could not be tested and will
@@ -3434,6 +3505,7 @@ static Bitmask codeOneLoopStart(
assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 );
if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0
&& (ii==0 || pSubLoop->u.btree.pIndex==pCov)
&& (HasRowid(pTab) || !IsPrimaryKeyIndex(pSubLoop->u.btree.pIndex))
){
assert( pSubWInfo->a[0].iIdxCur==iCovCur );
pCov = pSubLoop->u.btree.pIndex;
@@ -3761,7 +3833,7 @@ static int whereLoopCheaperProperSubset(
if( pX->rRun > pY->rRun ) return 0; /* X costs more than Y */
if( pX->nOut > pY->nOut ) return 0; /* X costs more than Y */
}
for(j=0, i=pX->nLTerm-1; i>=0; i--){
for(i=pX->nLTerm-1; i>=0; i--){
for(j=pY->nLTerm-1; j>=0; j--){
if( pY->aLTerm[j]==pX->aLTerm[i] ) break;
}
@@ -4759,7 +4831,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
pNew = pBuilder->pNew;
memset(&sSum, 0, sizeof(sSum));
pItem = pWInfo->pTabList->a + pNew->iTab;
if( !HasRowid(pItem->pTab) ) return SQLITE_OK;
iCur = pItem->iCursor;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
@@ -6008,7 +6079,14 @@ WhereInfo *sqlite3WhereBegin(
int op = OP_OpenRead;
/* iIdxCur is always set if to a positive value if ONEPASS is possible */
assert( iIdxCur!=0 || (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 );
if( pWInfo->okOnePass ){
if( !HasRowid(pTab) && IsPrimaryKeyIndex(pIx)
&& (wctrlFlags & WHERE_ONETABLE_ONLY)!=0
){
/* This is one term of an OR-optimization using the PRIMARY KEY of a
** WITHOUT ROWID table. No need for a separate index */
iIndexCur = pLevel->iTabCur;
op = 0;
}else if( pWInfo->okOnePass ){
Index *pJ = pTabItem->pTab->pIndex;
iIndexCur = iIdxCur;
assert( wctrlFlags & WHERE_ONEPASS_DESIRED );
@@ -6026,9 +6104,11 @@ WhereInfo *sqlite3WhereBegin(
pLevel->iIdxCur = iIndexCur;
assert( pIx->pSchema==pTab->pSchema );
assert( iIndexCur>=0 );
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
VdbeComment((v, "%s", pIx->zName));
if( op ){
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
VdbeComment((v, "%s", pIx->zName));
}
}
if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor);
+54
View File
@@ -58,12 +58,24 @@ proc do_backcompat_test {rv bin1 bin2 script} {
code1 { sqlite3 db test.db }
code2 { sqlite3 db test.db }
foreach c {code1 code2} {
$c {
set v [split [db version] .]
if {[llength $v]==3} {lappend v 0}
set ::sqlite_libversion [format \
"%d%.2d%.2d%2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
]
}
}
uplevel $script
catch { code1 { db close } }
catch { code2 { db close } }
catch { close $::bc_chan2 }
catch { close $::bc_chan1 }
}
array set ::incompatible [list]
@@ -381,6 +393,48 @@ ifcapable fts3 {
} {
do_test backcompat-3.7 [list sql1 $q] [sql2 $q]
}
# Now test that an incremental merge can be started by one version
# and finished by another. And that the integrity-check still
# passes.
do_test backcompat-3.8 {
sql1 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE t2 USING fts3(words);
}
code1 [list source $testdir/genesis.tcl]
code1 { fts_kjv_genesis }
sql1 {
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
}
} {0 {0 1 2 3 4 5}}
if {[code1 { set ::sqlite_libversion }] >=3071200
&& [code2 { set ::sqlite_libversion }] >=3071200
} {
do_test backcompat-3.9 {
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql2 { INSERT INTO t2(t2) VALUES('merge=2500,4'); }
sql2 {
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
}
} {0 {0 1} 1 0}
do_test backcompat-3.10 {
sql1 { INSERT INTO t2(t2) VALUES('integrity-check') }
sql2 { INSERT INTO t2(t2) VALUES('integrity-check') }
} {}
}
}
}
}
+44
View File
@@ -598,5 +598,49 @@ det 7.5 "SELECT count(*) FROM t2" {
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
}
#-------------------------------------------------------------------------
# The following tests - eqp-8.* - test that queries that use the OP_Count
# optimization return something sensible with EQP.
#
drop_all_tables
do_execsql_test 8.0 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
CREATE TABLE t2(a, b, c);
}
det 8.1.1 "SELECT * FROM t2" {
0 0 0 {SCAN TABLE t2}
}
det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
det 8.1.3 "SELECT count(*) FROM t2" {
0 0 0 {SCAN TABLE t2}
}
det 8.2.1 "SELECT * FROM t1" {
0 0 0 {SCAN TABLE t1}
}
det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
}
det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
}
det 8.2.4 "SELECT count(*) FROM t1" {
0 0 0 {SCAN TABLE t1}
}
finish_test
+10 -9
View File
@@ -213,16 +213,17 @@ do_test fts3d-4.matches {
{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
{0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
check_terms_all fts3d-4.1 {a four is one test that this three two was}
puts [db eval {SELECT c FROM t1 } ]
check_terms_all fts3d-4.1 {a four is test that this was}
check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
check_doclist_all fts3d-4.1.2 four {}
check_doclist_all fts3d-4.1.3 is {[1 0[1]] [3 0[1]]}
check_doclist_all fts3d-4.1.4 one {}
#check_doclist_all fts3d-4.1.4 one {}
check_doclist_all fts3d-4.1.5 test {[1 0[3]] [2 0[3]] [3 0[3]]}
check_doclist_all fts3d-4.1.6 that {[2 0[0]]}
check_doclist_all fts3d-4.1.7 this {[1 0[0]] [3 0[0]]}
check_doclist_all fts3d-4.1.8 three {}
check_doclist_all fts3d-4.1.9 two {}
#check_doclist_all fts3d-4.1.8 three {}
#check_doclist_all fts3d-4.1.9 two {}
check_doclist_all fts3d-4.1.10 was {[2 0[1]]}
check_terms fts3d-4.2 0 0 {a four test that was}
@@ -239,16 +240,16 @@ check_doclist fts3d-4.3.3 0 1 is {[3 0[1]]}
check_doclist fts3d-4.3.4 0 1 test {[3 0[3]]}
check_doclist fts3d-4.3.5 0 1 this {[3 0[0]]}
check_terms fts3d-4.4 1 0 {a four is one test that this three two was}
check_terms fts3d-4.4 1 0 {a four is test that this was}
check_doclist fts3d-4.4.1 1 0 a {[1 0[2]] [2 0[2]] [3 0[2]]}
check_doclist fts3d-4.4.2 1 0 four {[1] [2 0[4]] [3 0[4]]}
check_doclist fts3d-4.4.2 1 0 four {[2 0[4]] [3 0[4]]}
check_doclist fts3d-4.4.3 1 0 is {[1 0[1]] [3 0[1]]}
check_doclist fts3d-4.4.4 1 0 one {[1] [2] [3]}
#check_doclist fts3d-4.4.4 1 0 one {[1] [2] [3]}
check_doclist fts3d-4.4.5 1 0 test {[1 0[3]] [2 0[3]] [3 0[3]]}
check_doclist fts3d-4.4.6 1 0 that {[2 0[0]]}
check_doclist fts3d-4.4.7 1 0 this {[1 0[0]] [3 0[0]]}
check_doclist fts3d-4.4.8 1 0 three {[1] [2] [3]}
check_doclist fts3d-4.4.9 1 0 two {[1] [2] [3]}
#check_doclist fts3d-4.4.8 1 0 three {[1] [2] [3]}
#check_doclist fts3d-4.4.9 1 0 two {[1] [2] [3]}
check_doclist fts3d-4.4.10 1 0 was {[2 0[1]]}
# Optimize should leave the result in the level of the highest-level
+1
View File
@@ -59,6 +59,7 @@ do_execsql_test 1.2.1 {
SELECT content FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
} {{a b c d e f a x y}}
do_execsql_test 1.2.2 {
SELECT snippet(t1, '[', ']'), offsets(t1), mit(matchinfo(t1, 'pcxnal'))
FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
+5
View File
@@ -509,4 +509,9 @@ do_test fts3expr-8.7 { test_fts3expr "((((blah!))))" } {PHRASE 3 0 blah}
do_test fts3expr-8.8 { test_fts3expr "(,(blah-),)" } {PHRASE 3 0 blah}
set sqlite_fts3_enable_parentheses 0
do_test fts3expr-9.1 {
test_fts3expr "f (e NEAR/2 a)"
} {AND {PHRASE 3 0 f} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}}
finish_test
+57
View File
@@ -0,0 +1,57 @@
# 2014 May 7
#
# 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 FTS3 module.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts3expr4
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3||!icu {
finish_test
return
}
set sqlite_fts3_enable_parentheses 1
proc test_icu_fts3expr {expr} {
db one {SELECT fts3_exprtest('icu', $expr, 'a', 'b', 'c')}
}
proc do_icu_expr_test {tn expr res} {
uplevel [list do_test $tn [list test_icu_fts3expr $expr] $res]
}
#-------------------------------------------------------------------------
#
do_icu_expr_test 1.1 "abcd" {PHRASE 3 0 abcd}
do_icu_expr_test 1.2 " tag " {PHRASE 3 0 tag}
do_icu_expr_test 1.3 {"x y z"} {PHRASE 3 0 x y z}
do_icu_expr_test 1.4 {x OR y} {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
do_icu_expr_test 1.5 {(x OR y)} {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
do_icu_expr_test 1.6 { "(x OR y)" } {PHRASE 3 0 ( x or y )}
# In "col:word", if "col" is not the name of a column, the entire thing
# is passed to the tokenizer.
#
do_icu_expr_test 1.7 {a:word} {PHRASE 0 0 word}
do_icu_expr_test 1.8 {d:word} {PHRASE 3 0 d:word}
set sqlite_fts3_enable_parentheses 0
do_icu_expr_test 2.1 {
f (e NEAR/2 a)
} {AND {AND {AND {PHRASE 3 0 f} {PHRASE 3 0 (}} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}} {PHRASE 3 0 )}}
finish_test
+437
View File
@@ -0,0 +1,437 @@
# 2014 May 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.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS4 module.
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4growth
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
finish_test
return
}
source $testdir/genesis.tcl
do_execsql_test 1.1 { CREATE VIRTUAL TABLE x1 USING fts3; }
do_test 1.2 {
foreach L {
{"See here, young man," said Mulga Bill, "from Walgett to the sea,}
{From Conroy's Gap to Castlereagh, there's none can ride like me.}
{I'm good all round at everything as everybody knows,}
{Although I'm not the one to talk -- I hate a man that blows.}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql { SELECT end_block, length(root) FROM x1_segdir }
} {{0 114} 114 {0 118} 118 {0 95} 95 {0 115} 115}
do_execsql_test 1.3 {
INSERT INTO x1(x1) VALUES('optimize');
SELECT level, end_block, length(root) FROM x1_segdir;
} {0 {0 394} 394}
do_test 1.4 {
foreach L {
{But riding is my special gift, my chiefest, sole delight;}
{Just ask a wild duck can it swim, a wildcat can it fight.}
{There's nothing clothed in hair or hide, or built of flesh or steel,}
{There's nothing walks or jumps, or runs, on axle, hoof, or wheel,}
{But what I'll sit, while hide will hold and girths and straps are tight:}
{I'll ride this here two-wheeled concern right straight away at sight."}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql {
INSERT INTO x1(x1) VALUES('merge=4,4');
SELECT level, end_block, length(root) FROM x1_segdir;
}
} {0 {0 110} 110 0 {0 132} 132 0 {0 129} 129 1 {128 658} 2}
do_execsql_test 1.5 {
SELECT length(block) FROM x1_segments;
} {658 {}}
do_test 1.6 {
foreach L {
{'Twas Mulga Bill, from Eaglehawk, that sought his own abode,}
{That perched above Dead Man's Creek, beside the mountain road.}
{He turned the cycle down the hill and mounted for the fray,}
{But 'ere he'd gone a dozen yards it bolted clean away.}
{It left the track, and through the trees, just like a silver steak,}
{It whistled down the awful slope towards the Dead Man's Creek.}
{It shaved a stump by half an inch, it dodged a big white-box:}
{The very wallaroos in fright went scrambling up the rocks,}
{The wombats hiding in their caves dug deeper underground,}
{As Mulga Bill, as white as chalk, sat tight to every bound.}
{It struck a stone and gave a spring that cleared a fallen tree,}
{It raced beside a precipice as close as close could be;}
{And then as Mulga Bill let out one last despairing shriek}
{It made a leap of twenty feet into the Dead Man's Creek.}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql {
SELECT level, end_block, length(root) FROM x1_segdir;
}
} {1 {128 658} 2 1 {130 1377} 6 0 {0 117} 117}
do_execsql_test 1.7 {
SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (129, 130);
} {1377}
#-------------------------------------------------------------------------
#
do_execsql_test 2.1 {
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE x2 USING fts4;
}
fts_kjv_genesis
do_test 2.2 {
foreach id [db eval {SELECT docid FROM t1}] {
execsql {
INSERT INTO x2(docid, content) SELECT $id, words FROM t1 WHERE docid=$id
}
}
foreach id [db eval {SELECT docid FROM t1}] {
execsql {
INSERT INTO x2(docid, content) SELECT NULL, words FROM t1 WHERE docid=$id
}
if {[db one {SELECT count(*) FROM x2_segdir WHERE level<2}]==2} break
}
} {}
do_execsql_test 2.3 {
SELECT count(*) FROM x2_segdir WHERE level=2;
SELECT count(*) FROM x2_segdir WHERE level=3;
} {6 0}
do_execsql_test 2.4 {
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT count(*) FROM x2_segdir WHERE level=2;
SELECT count(*) FROM x2_segdir WHERE level=3;
} {6 1}
do_execsql_test 2.5 {
SELECT end_block FROM x2_segdir WHERE level=3;
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT end_block FROM x2_segdir WHERE level=3;
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT end_block FROM x2_segdir WHERE level=3;
} {{3828 -3430} {3828 -10191} {3828 -14109}}
do_execsql_test 2.6 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
} {14109}
do_execsql_test 2.7 {
INSERT INTO x2(x2) VALUES('merge=1000,4');
SELECT end_block FROM x2_segdir WHERE level=3;
} {{3828 86120}}
do_execsql_test 2.8 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
} {86120}
#--------------------------------------------------------------------------
# Test that delete markers are removed from FTS segments when possible.
# It is only possible to remove delete markers when the output of the
# merge operation will become the oldest segment in the index.
#
# 3.1 - when the oldest segment is created by an 'optimize'.
# 3.2 - when the oldest segment is created by an incremental merge.
# 3.3 - by a crisis merge.
#
proc insert_doc {args} {
foreach iDoc $args {
set L [lindex {
{In your eagerness to engage the Trojans,}
{dont any of you charge ahead of others,}
{trusting in your strength and horsemanship.}
{And dont lag behind. That will hurt our charge.}
{Any man whose chariot confronts an enemys}
{should thrust with his spear at him from there.}
{Thats the most effective tactic, the way}
{men wiped out city strongholds long ago —}
{their chests full of that style and spirit.}
} [expr $iDoc%9]]
execsql { REPLACE INTO x3(docid, content) VALUES($iDoc, $L) }
}
}
proc delete_doc {args} {
foreach iDoc $args {
execsql { DELETE FROM x3 WHERE docid = $iDoc }
}
}
proc second {x} { lindex $x 1 }
db func second second
do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts4 }
do_test 3.1.1 {
db transaction { insert_doc 1 2 3 4 5 6 }
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {0 0 412}
do_test 3.1.2 {
delete_doc 1 2 3 4 5 6
execsql { SELECT count(*) FROM x3_segdir }
} {0}
do_test 3.1.3 {
db transaction {
insert_doc 1 2 3 4 5 6 7 8 9
delete_doc 9 8 7
}
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {0 0 591 0 1 65 0 2 72 0 3 76}
do_test 3.1.4 {
execsql { INSERT INTO x3(x3) VALUES('optimize') }
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {0 0 412}
do_test 3.2.1 {
execsql { DELETE FROM x3 }
insert_doc 8 7 6 5 4 3 2 1
delete_doc 7 8
execsql { SELECT count(*) FROM x3_segdir }
} {10}
do_test 3.2.2 {
execsql { INSERT INTO x3(x3) VALUES('merge=500,10') }
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {1 0 412}
# This assumes the crisis merge happens when there are already 16
# segments and one more is added.
#
do_test 3.3.1 {
execsql { DELETE FROM x3 }
insert_doc 1 2 3 4 5 6 7 8 9 10 11
delete_doc 11 10 9 8 7
execsql { SELECT count(*) FROM x3_segdir }
} {16}
do_test 3.3.2 {
insert_doc 12
execsql { SELECT level, idx, second(end_block) FROM x3_segdir WHERE level=1 }
} {1 0 412}
#--------------------------------------------------------------------------
# Check a theory on a bug in fts4 - that segments with idx==0 were not
# being incrementally merged correctly. Theory turned out to be false.
#
do_execsql_test 4.1 {
DROP TABLE IF EXISTS x4;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE x4 USING fts4(words);
}
do_test 4.2 {
fts_kjv_genesis
execsql { INSERT INTO x4 SELECT words FROM t1 }
execsql { INSERT INTO x4 SELECT words FROM t1 }
} {}
do_execsql_test 4.3 {
SELECT level, idx, second(end_block) FROM x4_segdir
} {0 0 117483 0 1 118006}
do_execsql_test 4.4 {
INSERT INTO x4(x4) VALUES('merge=10,2');
SELECT count(*) FROM x4_segdir;
} {3}
do_execsql_test 4.5 {
INSERT INTO x4(x4) VALUES('merge=10,2');
SELECT count(*) FROM x4_segdir;
} {3}
do_execsql_test 4.6 {
INSERT INTO x4(x4) VALUES('merge=1000,2');
SELECT count(*) FROM x4_segdir;
} {1}
#--------------------------------------------------------------------------
# Check that segments are not promoted if the "end_block" field does not
# contain a size.
#
do_execsql_test 5.1 {
DROP TABLE IF EXISTS x2;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE x2 USING fts4;
}
fts_kjv_genesis
proc first {L} {lindex $L 0}
db func first first
do_test 5.2 {
foreach r [db eval { SELECT rowid FROM t1 }] {
execsql {
INSERT INTO x2(docid, content) SELECT docid, words FROM t1 WHERE rowid=$r
}
}
foreach d [db eval { SELECT docid FROM t1 LIMIT -1 OFFSET 20 }] {
execsql { DELETE FROM x2 WHERE docid = $d }
}
execsql {
INSERT INTO x2(x2) VALUES('optimize');
SELECT level, idx, end_block FROM x2_segdir
}
} {2 0 {752 1926}}
do_execsql_test 5.3 {
UPDATE x2_segdir SET end_block = CAST( first(end_block) AS INTEGER );
SELECT end_block, typeof(end_block) FROM x2_segdir;
} {752 integer}
do_execsql_test 5.4 {
INSERT INTO x2 SELECT words FROM t1 LIMIT 50;
SELECT level, idx, end_block FROM x2_segdir
} {2 0 752 0 0 {758 5174}}
do_execsql_test 5.5 {
UPDATE x2_segdir SET end_block = end_block || ' 1926' WHERE level=2;
INSERT INTO x2 SELECT words FROM t1 LIMIT 40;
SELECT level, idx, end_block FROM x2_segdir
} {0 0 {752 1926} 0 1 {758 5174} 0 2 {763 4170}}
proc t1_to_x2 {} {
foreach id [db eval {SELECT docid FROM t1 LIMIT 2}] {
execsql {
DELETE FROM x2 WHERE docid=$id;
INSERT INTO x2(docid, content) SELECT $id, words FROM t1 WHERE docid=$id;
}
}
}
#--------------------------------------------------------------------------
# Check that segments created by auto-merge are not promoted until they
# are completed.
#
do_execsql_test 6.1 {
CREATE VIRTUAL TABLE x5 USING fts4;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 0;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 25;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 50;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 75;
SELECT count(*) FROM x5_segdir
} {4}
do_execsql_test 6.2 {
INSERT INTO x5(x5) VALUES('merge=2,4');
SELECT level, idx, end_block FROM x5_segdir;
} {0 0 {10 9216} 0 1 {21 9330} 0 2 {31 8850} 0 3 {40 8689} 1 0 {1320 -3117}}
do_execsql_test 6.3 {
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 100;
SELECT level, idx, end_block FROM x5_segdir;
} {
0 0 {10 9216} 0 1 {21 9330} 0 2 {31 8850}
0 3 {40 8689} 1 0 {1320 -3117} 0 4 {1329 8297}
}
do_execsql_test 6.4 {
INSERT INTO x5(x5) VALUES('merge=200,4');
SELECT level, idx, end_block FROM x5_segdir;
} {0 0 {1329 8297} 1 0 {1320 28009}}
do_execsql_test 6.5 {
INSERT INTO x5 SELECT words FROM t1;
SELECT level, idx, end_block FROM x5_segdir;
} {
0 1 {1329 8297} 0 0 {1320 28009} 0 2 {1449 118006}
}
#--------------------------------------------------------------------------
# Ensure that if part of an incremental merge is performed by an old
# version that does not support storing segment sizes in the end_block
# field, no size is stored in the final segment (as it would be incorrect).
#
do_execsql_test 7.1 {
CREATE VIRTUAL TABLE x6 USING fts4;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
}
do_execsql_test 7.2 {
INSERT INTO x6(x6) VALUES('merge=25,4');
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 {16014 -51226}
}
do_execsql_test 7.3 {
UPDATE x6_segdir SET end_block = first(end_block) WHERE level=1;
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 16014
}
do_execsql_test 7.4 {
INSERT INTO x6(x6) VALUES('merge=25,4');
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 16014
}
do_execsql_test 7.5 {
INSERT INTO x6(x6) VALUES('merge=2500,4');
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {598 118006} 0 1 {718 118006} 1 0 16014
}
do_execsql_test 7.6 {
INSERT INTO x6(x6) VALUES('merge=2500,2');
SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
} {
2 0 23695 24147 {41262 633507}
}
do_execsql_test 7.7 {
SELECT sum(length(block)) FROM x6_segments
WHERE blockid BETWEEN 23695 AND 24147
} {633507}
finish_test
+93
View File
@@ -0,0 +1,93 @@
# 2014 May 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.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS4 module.
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4growth2
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
finish_test
return
}
source $testdir/genesis.tcl
do_execsql_test 1.0 { CREATE TABLE t1(docid, words); }
fts_kjv_genesis
proc structure {} {
puts [ db eval {SELECT level, count(*) FROM x1_segdir GROUP BY level} ]
}
proc tt {val} {
execsql {
DELETE FROM x1
WHERE docid IN (SELECT docid FROM t1 WHERE (rowid-1)%4==$val+0);
}
execsql {
INSERT INTO x1(docid, content)
SELECT docid, words FROM t1 WHERE (rowid%4)==$val+0;
}
}
do_execsql_test 1.1 {
CREATE VIRTUAL TABLE x1 USING fts4;
INSERT INTO x1(x1) VALUES('automerge=2');
}
do_test 1.2 {
for {set i 0} {$i < 40} {incr i} {
tt 0 ; tt 1 ; tt 2 ; tt 3
}
execsql {
SELECT max(level) FROM x1_segdir;
SELECT count(*) FROM x1_segdir WHERE level=2;
}
} {2 1}
do_test 1.3 {
for {set i 0} {$i < 40} {incr i} {
tt 0 ; tt 1 ; tt 2 ; tt 3
}
execsql {
SELECT max(level) FROM x1_segdir;
SELECT count(*) FROM x1_segdir WHERE level=2;
}
} {2 1}
#-------------------------------------------------------------------------
#
do_execsql_test 2.1 {
DELETE FROM t1 WHERE rowid>16;
DROP TABLE IF EXISTS x1;
CREATE VIRTUAL TABLE x1 USING fts4;
}
db func second second
proc second {L} {lindex $L 1}
for {set tn 0} {$tn < 40} {incr tn} {
do_test 2.2.$tn {
for {set i 0} {$i < 100} {incr i} {
tt 0 ; tt 1 ; tt 2 ; tt 3
}
execsql { SELECT max(level) FROM x1_segdir }
} {1}
}
finish_test
+44
View File
@@ -53,6 +53,50 @@ do_execsql_test 2.2 { SELECT count(*) FROM t1_segdir; } 35
do_execsql_test 2.3 { INSERT INTO t1(t1) VALUES('optimize') } {}
do_execsql_test 2.4 { SELECT count(*) FROM t1_segdir; } 1
#-------------------------------------------------------------------------
# Now test that the automerge=? option appears to work.
#
do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING fts4; }
set doc ""
foreach c1 "a b c d e f g h i j" {
foreach c2 "a b c d e f g h i j" {
foreach c3 "a b c d e f g h i j" {
lappend doc "$c1$c2$c3"
}
}
}
set doc [string repeat $doc 10]
foreach {tn am expected} {
1 {automerge=2} {1 1 2 1 4 1 6 1}
2 {automerge=4} {1 2 2 1 3 1}
3 {automerge=8} {0 4 1 3 2 1}
4 {automerge=1} {0 4 1 3 2 1}
} {
foreach {tn2 openclose} {1 {} 2 { db close ; sqlite3 db test.db }} {
do_test 2.2.$tn.$tn2 {
execsql { DELETE FROM t2 }
execsql { INSERT INTO t2(t2) VALUES($am) };
eval $openclose
for {set i 0} {$i < 100} {incr i} {
execsql {
BEGIN;
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
COMMIT;
}
}
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
} [list {*}$expected]
}
}
sqlite3_enable_shared_cache $::enable_shared_cache
finish_test
+45
View File
@@ -165,6 +165,51 @@ do_execsql_test 5.4 { SELECT docid FROM t2 WHERE t2 MATCH 'c' } {3}
do_execsql_test 5.x { DROP TABLE t2 }
#-------------------------------------------------------------------------
# Check that if an indexed column name is a prefix of a notindexed column
# name, the column is still correctly tokenized. This was a problem at one
# point.
do_execsql_test 6.1.1 {
CREATE VIRTUAL TABLE t1 USING fts4(
poiCategory, poiCategoryId, notindexed=poiCategoryId
);
INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
}
do_execsql_test 6.1.2 {
SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
} { Restaurant 6021 }
do_execsql_test 6.1.3 {
SELECT * FROM t1 WHERE t1 MATCH 're*';
} { Restaurant 6021 }
do_execsql_test 6.1.4 {
SELECT * FROM t1 WHERE t1 MATCH '6021';
} {}
do_execsql_test 6.1.5 {
SELECT * FROM t1 WHERE t1 MATCH '60*';
} {}
do_execsql_test 6.2.1 {
DROP TABLE t1;
CREATE VIRTUAL TABLE t1 USING fts4(
poiCategory, poiCategoryId, notindexed=poiCategory
);
INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
}
do_execsql_test 6.2.2 {
SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
} {}
do_execsql_test 6.2.3 {
SELECT * FROM t1 WHERE t1 MATCH 're*';
} {}
do_execsql_test 6.2.4 {
SELECT * FROM t1 WHERE t1 MATCH '6021';
} { Restaurant 6021 }
do_execsql_test 6.2.5 {
SELECT * FROM t1 WHERE t1 MATCH '60*';
} { Restaurant 6021 }
finish_test
+12
View File
@@ -1194,6 +1194,18 @@ do_test func-24.12 {
WHEN 'program' THEN null ELSE t1 END) FROM tbl1
}
} {,is,free,software}
# Tests to verify ticket http://www.sqlite.org/src/tktview/55746f9e65f8587c0
do_test func-24.13 {
execsql {
SELECT typeof(group_concat(x)) FROM (SELECT '' AS x);
}
} {text}
do_test func-24.14 {
execsql {
SELECT typeof(group_concat(x,''))
FROM (SELECT '' AS x UNION ALL SELECT '');
}
} {text}
# Use the test_isolation function to make sure that type conversions
+23
View File
@@ -413,6 +413,29 @@ do_execsql_test insert-11.1 {
} {123456789 '123456789' '123456789'}
# More columns of input than there are columns in the table.
# Ticket http://www.sqlite.org/src/info/e9654505cfda9361
#
do_execsql_test insert-12.1 {
CREATE TABLE t12a(a,b,c,d,e,f,g);
INSERT INTO t12a VALUES(101,102,103,104,105,106,107);
CREATE TABLE t12b(x);
INSERT INTO t12b(x,rowid,x,x,x,x,x) SELECT * FROM t12a;
SELECT rowid, x FROM t12b;
} {102 101}
do_execsql_test insert-12.2 {
CREATE TABLE tab1( value INTEGER);
INSERT INTO tab1 (value, _rowid_) values( 11, 1);
INSERT INTO tab1 (value, _rowid_) SELECT 22,999;
SELECT * FROM tab1;
} {11 22}
do_execsql_test insert-12.3 {
CREATE TABLE t12c(a, b DEFAULT 'xyzzy', c);
INSERT INTO t12c(a, rowid, c) SELECT 'one', 999, 'two';
SELECT * FROM t12c;
} {one xyzzy two}
integrity_check insert-99.0
finish_test
+16
View File
@@ -604,5 +604,21 @@ do_execsql_test misc1-19.2 {
SELECT * FROM t19b;
} {4 5 6}
# 2014-05-16: Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature.
#
unset -nocomplain fault_callbacks
set fault_callbacks {}
proc fault_callback {n} {
lappend ::fault_callbacks $n
return 0
}
do_test misc1-19.1 {
sqlite3_test_control_fault_install fault_callback
set fault_callbacks
} {0}
do_test misc1-19.2 {
sqlite3_test_control_fault_install
set fault_callbacks
} {0}
finish_test
+185
View File
@@ -0,0 +1,185 @@
# 2014-05-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 nolock=1 and immutable=1 query
# parameters and the SQLITE_IOCAP_IMMUTABLE device characteristic.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
unset -nocomplain tvfs_calls
proc tvfs_reset {} {
global tvfs_calls
array set tvfs_calls {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
}
proc tvfs_callback {op args} {
global tvfs_calls
incr tvfs_calls($op)
return SQLITE_OK
}
tvfs_reset
testvfs tvfs
tvfs script tvfs_callback
tvfs filter {xLock xUnlock xCheckReservedLock xAccess}
############################################################################
# Verify that the nolock=1 query parameter for URI filenames disables all
# calls to xLock and xUnlock for rollback databases.
#
do_test nolock-1.0 {
db close
forcedelete test.db
tvfs_reset
sqlite db test.db -vfs tvfs
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 7 xUnlock 5 xCheckReservedLock 0}
do_test nolock-1.1 {
db close
forcedelete test.db
tvfs_reset
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 7 xUnlock 5 xCheckReservedLock 0}
do_test nolock-1.2 {
db close
forcedelete test.db
tvfs_reset
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 0 xUnlock 0 xCheckReservedLock 0}
do_test nolock-1.3 {
db close
tvfs_reset
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1 -readonly 1
db eval {SELECT * FROM t1}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 2 xUnlock 2 xCheckReservedLock 0}
do_test nolock-1.4 {
db close
tvfs_reset
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1 -readonly 1
db eval {SELECT * FROM t1}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 0 xUnlock 0 xCheckReservedLock 0}
#############################################################################
# Verify that immutable=1 disables both locking and xAccess calls to the
# journal files.
#
do_test nolock-2.0 {
db close
forcedelete test.db
# begin by creating a test database
sqlite3 db test.db
db eval {
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES('hello','world');
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(12345,67890);
SELECT * FROM t1, t2;
}
} {hello world 12345 67890}
do_test nolock-2.1 {
tvfs_reset
sqlite3 db2 test.db -vfs tvfs
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.2 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
do_test nolock-2.11 {
db2 close
tvfs_reset
sqlite3 db2 file:test.db?immutable=0 -vfs tvfs -uri 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.12 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
do_test nolock-2.21 {
db2 close
tvfs_reset
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.22 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
do_test nolock-2.31 {
db2 close
tvfs_reset
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1 -readonly 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.32 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
############################################################################
# Verify that the SQLITE_IOCAP_IMMUTABLE flag works
#
do_test nolock-3.1 {
db2 close
tvfs devchar immutable
tvfs_reset
sqlite3 db2 test.db -vfs tvfs
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-3.2 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
do_test nolock-3.11 {
db2 close
tvfs_reset
sqlite3 db2 test.db -vfs tvfs -readonly 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-3.12 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
db2 close
db close
tvfs delete
finish_test
+2
View File
@@ -112,6 +112,7 @@ set allquicktests [test_set $alltests -exclude {
incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test
vtab_err.test walslow.test walcrash.test walcrash3.test
walthread.test rtree3.test indexfault.test securedel2.test
fts4growth.test fts4growth2.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
@@ -196,6 +197,7 @@ test_suite "fts3" -prefix "" -description {
fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
fts4check.test fts4unicode.test fts4noti.test
fts3varint.test
fts4growth.test fts4growth2.test
}
test_suite "nofaultsim" -prefix "" -description {
+6
View File
@@ -32,6 +32,9 @@ do_test rdonly-1.1 {
SELECT * FROM t1;
}
} {1}
do_test rdonly-1.1.1 {
sqlite3_db_readonly db main
} {0}
# Changes the write version from 1 to 3. Verify that the database
# can be read but not written.
@@ -47,6 +50,9 @@ do_test rdonly-1.3 {
SELECT * FROM t1;
}
} {1}
do_test rdonly-1.3.1 {
sqlite3_db_readonly db main
} {1}
do_test rdonly-1.4 {
catchsql {
INSERT INTO t1 VALUES(2)
+54 -2
View File
@@ -302,8 +302,60 @@ do_test shell5-1.11 {
sqlite3 db test.db
db eval {SELECT *, '|' FROM t1}
} {a b { } | x y {} | p q r |}
db close
#----------------------------------------------------------------------------
#
reset_db
sqlite3 db test.db
do_test shell5-2.1 {
set fd [open shell5.csv w]
puts $fd ",hello"
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t1(a, b);
.import shell5.csv t1
}]
db eval { SELECT * FROM t1 }
} {{} hello}
do_test shell5-2.2 {
set fd [open shell5.csv w]
puts $fd {"",hello}
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t2(a, b);
.import shell5.csv t2
}]
db eval { SELECT * FROM t2 }
} {{} hello}
do_test shell5-2.3 {
set fd [open shell5.csv w]
puts $fd {"x""y",hello}
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t3(a, b);
.import shell5.csv t3
}]
db eval { SELECT * FROM t3 }
} {x\"y hello}
do_test shell5-2.4 {
set fd [open shell5.csv w]
puts $fd {"xy""",hello}
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t4(a, b);
.import shell5.csv t4
}]
db eval { SELECT * FROM t4 }
} {xy\" hello}
finish_test
+1 -1
View File
@@ -181,7 +181,7 @@ do_execsql_test skipscan1-3.2 {
do_execsql_test skipscan1-3.2eqp {
EXPLAIN QUERY PLAN
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
} {/* INDEX sqlite_autoindex_t3_1 (ANY(a) AND b=?)*/}
} {/* PRIMARY KEY (ANY(a) AND b=?)*/}
do_execsql_test skipscan1-3.2sort {
EXPLAIN QUERY PLAN
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
+14
View File
@@ -186,6 +186,20 @@ do_execsql_test skipscan2-2.5eqp {
SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
} {/*INDEX peoplew_idx1 */}
# A skip-scan on a PK index of a WITHOUT ROWID table.
#
do_execsql_test skipscan2-3.1 {
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
}
do_test skipscan2-3.2 {
for {set i 0} {$i < 1000} {incr i} {
execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
}
execsql { ANALYZE }
} {}
do_eqp_test skipscan2-3.3eqp {
SELECT * FROM t3 WHERE b=42;
} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}}
finish_test
+1
View File
@@ -136,6 +136,7 @@ ifcapable fts3 {
"-- SELECT (SELECT max(idx) FROM 'main'.'x1_segdir' WHERE level = ?) + 1"
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
"-- REPLACE INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
"-- SELECT level, idx, end_block FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ? ORDER BY level DESC, idx ASC"
}
do_trace_test 2.3 {
+92
View File
@@ -0,0 +1,92 @@
# 2014-03-31
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# The focus of this file is testing the OR optimization on WITHOUT ROWID
# tables.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix whereI
do_execsql_test 1.0 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
INSERT INTO t1 VALUES(1, 'a', 'z');
INSERT INTO t1 VALUES(2, 'b', 'y');
INSERT INTO t1 VALUES(3, 'c', 'x');
INSERT INTO t1 VALUES(4, 'd', 'w');
CREATE INDEX i1 ON t1(b);
CREATE INDEX i2 ON t1(c);
}
do_eqp_test 1.1 {
SELECT a FROM t1 WHERE b='b' OR c='x'
} {
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (b=?)}
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (c=?)}
}
do_execsql_test 1.2 {
SELECT a FROM t1 WHERE b='b' OR c='x'
} {2 3}
do_execsql_test 1.3 {
SELECT a FROM t1 WHERE b='a' OR c='z'
} {1}
#----------------------------------------------------------------------
# Try that again, this time with non integer PRIMARY KEY values.
#
do_execsql_test 2.0 {
CREATE TABLE t2(a, b, c, PRIMARY KEY(a)) WITHOUT ROWID;
INSERT INTO t2 VALUES('i', 'a', 'z');
INSERT INTO t2 VALUES('ii', 'b', 'y');
INSERT INTO t2 VALUES('iii', 'c', 'x');
INSERT INTO t2 VALUES('iv', 'd', 'w');
CREATE INDEX i3 ON t2(b);
CREATE INDEX i4 ON t2(c);
}
do_eqp_test 2.1 {
SELECT a FROM t2 WHERE b='b' OR c='x'
} {
0 0 0 {SEARCH TABLE t2 USING INDEX i3 (b=?)}
0 0 0 {SEARCH TABLE t2 USING INDEX i4 (c=?)}
}
do_execsql_test 2.2 {
SELECT a FROM t2 WHERE b='b' OR c='x'
} {ii iii}
do_execsql_test 2.3 {
SELECT a FROM t2 WHERE b='a' OR c='z'
} {i}
#----------------------------------------------------------------------
# On a table with a multi-column PK.
#
do_execsql_test 3.0 {
CREATE TABLE t3(a, b, c, d, PRIMARY KEY(c, b)) WITHOUT ROWID;
INSERT INTO t3 VALUES('f', 1, 1, 'o');
INSERT INTO t3 VALUES('o', 2, 1, 't');
INSERT INTO t3 VALUES('t', 1, 2, 't');
INSERT INTO t3 VALUES('t', 2, 2, 'f');
CREATE INDEX t3i1 ON t3(d);
CREATE INDEX t3i2 ON t3(a);
SELECT c||'.'||b FROM t3 WHERE a='t' OR d='t'
} {
2.1 2.2 1.2
}
finish_test
+48 -2
View File
@@ -24,7 +24,7 @@ db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
lappend ::log $msg
lappend ::log $msg
}
sqlite3 db test.db
db eval {PRAGMA mmap_size=0}
@@ -128,7 +128,53 @@ while {1} {
file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
db close
forcedelete test.db
sqlite3 db test.db
sqlite3 db2 test.db
do_test win32lock-3.0 {
db eval {
CREATE TABLE t1(x);
INSERT INTO t1 VALUES(1);
INSERT INTO t1 VALUES(2);
INSERT INTO t1 VALUES(3);
}
} {}
do_test win32lock-3.1 {
db eval {
BEGIN EXCLUSIVE;
INSERT INTO t1 VALUES(4);
}
} {}
do_test win32lock-3.2 {
catchsql {
BEGIN EXCLUSIVE;
INSERT INTO t1 VALUES(5);
COMMIT;
} db2
} {1 {database is locked}}
do_test win32lock-3.3 {
db eval {
COMMIT;
}
} {}
do_test win32lock-3.4 {
set handle [lindex [file_control_win32_set_handle db 0] end]
list [catchsql {
BEGIN EXCLUSIVE;
INSERT INTO t1 VALUES(6);
COMMIT;
}] [file_control_win32_set_handle db $handle] [sqlite3_extended_errcode db]
} {{1 {disk I/O error}} {0 0} SQLITE_IOERR_LOCK}
db2 close
db close
sqlite3_shutdown
test_sqlite3_log
test_sqlite3_log
sqlite3_initialize
finish_test
+19 -2
View File
@@ -146,6 +146,17 @@ IF NOT DEFINED CONFIGURATIONS (
%_VECHO% Configurations = '%CONFIGURATIONS%'
REM
REM NOTE: If the command used to invoke NMAKE is not already set, use the
REM default.
REM
IF NOT DEFINED NMAKE_CMD (
SET NMAKE_CMD=nmake -B -f Makefile.msc
)
%_VECHO% NmakeCmd = '%NMAKE_CMD%'
%_VECHO% NmakeArgs = '%NMAKE_ARGS%'
REM
REM NOTE: Setup environment variables to translate between the MSVC platform
REM names and the names to be used for the platform-specific binary
@@ -266,6 +277,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM and/or Visual Studio. This block may need to be updated in the
REM future to account for additional environment variables.
REM
CALL :fn_UnsetVariable CommandPromptType
CALL :fn_UnsetVariable DevEnvDir
CALL :fn_UnsetVariable ExtensionSdkDir
CALL :fn_UnsetVariable Framework35Version
@@ -303,6 +315,8 @@ FOR %%P IN (%PLATFORMS%) DO (
REM environment variables to be picked up by the MSVC makefile
REM itself.
REM
%_AECHO% Building the %%B configuration for platform %%P with name %%D...
IF /I "%%B" == "Debug" (
SET DEBUG=2
SET MEMDEBUG=1
@@ -382,6 +396,8 @@ FOR %%P IN (%PLATFORMS%) DO (
REM
IF DEFINED USE_WINV63_NSDKLIBPATH (
CALL :fn_AppendVariable NSDKLIBPATH \lib\winv6.3\um\x86
) ELSE IF "%VisualStudioVersion%" == "12.0" (
CALL :fn_AppendVariable NSDKLIBPATH \..\8.0\lib\win8\um\x86
) ELSE (
CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86
)
@@ -395,7 +411,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM file, etc.
REM
IF NOT DEFINED NOCLEAN (
%__ECHO% nmake -f Makefile.msc clean
%__ECHO% %NMAKE_CMD% clean
IF ERRORLEVEL 1 (
ECHO Failed to clean for platform %%P.
@@ -407,6 +423,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM need to remove the build output for the files we are
REM specifically wanting to build for each platform.
REM
%_AECHO% Cleaning final output files only...
%__ECHO% DEL /Q *.lo sqlite3.dll sqlite3.lib sqlite3.pdb
)
@@ -417,7 +434,7 @@ FOR %%P IN (%PLATFORMS%) DO (
REM Also, disable looking for and/or linking to the native Tcl
REM runtime library.
REM
%__ECHO% nmake -f Makefile.msc sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
%__ECHO% %NMAKE_CMD% sqlite3.dll XCOMPILE=1 USE_NATIVE_LIBPATHS=1 NO_TCL=1 %NMAKE_ARGS%
IF ERRORLEVEL 1 (
ECHO Failed to build %%B "sqlite3.dll" for platform %%P.
+202 -56
View File
@@ -65,12 +65,16 @@
# argument is optional and if present must contain the name of the directory
# containing the root of the source tree for SQLite. The third argument is
# optional and if present must contain the flavor the VSIX package to build.
# Currently, the only supported package flavors are "WinRT", "WinRT81", and
# "WP80". The fourth argument is optional and if present must be a string
# containing a list of platforms to include in the VSIX package. The format
# of the platform list string is "platform1,platform2,platform3". Typically,
# when on Windows, this script is executed using commands similar to the
# following from a normal Windows command prompt:
# Currently, the only supported package flavors are "WinRT", "WinRT81", "WP80",
# "WP81", and "Win32". The fourth argument is optional and if present must be
# a string containing a list of platforms to include in the VSIX package. The
# platform list is "platform1,platform2,platform3". The fifth argument is
# optional and if present must contain the version of Visual Studio required by
# the package. Currently, the only supported versions are "2012" and "2013".
# The package flavors "WinRT81" and "WP81" are only supported when the Visual
# Studio version is "2013". Typically, when on Windows, this script is
# executed using commands similar to the following from a normal Windows
# command prompt:
#
# CD /D C:\dev\sqlite\core
# tclsh85 tool\mkvsix.tcl C:\Temp
@@ -100,7 +104,7 @@ proc fail { {error ""} {usage false} } {
puts stdout "usage:\
[file tail [info nameofexecutable]]\
[file tail [info script]] <binaryDirectory> \[sourceDirectory\]\
\[packageFlavor\] \[platformNames\]"
\[packageFlavor\] \[platformNames\] \[vsVersion\]"
exit 1
}
@@ -170,13 +174,81 @@ proc writeFile { fileName data } {
return ""
}
proc substFile { fileName } {
proc getMinVsVersionXmlChunk { vsVersion } {
switch -exact $vsVersion {
2012 {
return [appendArgs \
"\r\n " {MinVSVersion="11.0"}]
}
2013 {
return [appendArgs \
"\r\n " {MinVSVersion="12.0"}]
}
default {
return ""
}
}
}
proc getMaxPlatformVersionXmlChunk { packageFlavor vsVersion } {
#
# NOTE: Performs all Tcl command, variable, and backslash substitutions in
# the specified file and then rewrites the contents of that same file
# with the substituted data.
# NOTE: Only Visual Studio 2013 supports this SDK manifest attribute.
#
return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
if {![string equal $vsVersion 2013]} then {
return ""
}
switch -exact $packageFlavor {
WinRT {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.0"}]
}
WinRT81 {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.1"}]
}
WP80 {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.0"}]
}
WP81 {
return [appendArgs \
"\r\n " {MaxPlatformVersion="8.1"}]
}
default {
return ""
}
}
}
proc getExtraFileListXmlChunk { packageFlavor vsVersion } {
#
# NOTE: Windows Phone 8.0 does not require any extra attributes in its VSIX
# package SDK manifests; however, it appears that Windows Phone 8.1
# does.
#
if {[string equal $packageFlavor WP80]} then {
return ""
}
set appliesTo [expr {[string equal $packageFlavor Win32] ? \
"VisualC" : "WindowsAppContainer"}]
switch -exact $vsVersion {
2012 {
return [appendArgs \
"\r\n " AppliesTo=\" $appliesTo \" \
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
}
2013 {
return [appendArgs \
"\r\n " AppliesTo=\" $appliesTo \" \
"\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
}
default {
return ""
}
}
}
proc replaceFileNameTokens { fileName name buildName platformName } {
@@ -188,6 +260,15 @@ proc replaceFileNameTokens { fileName name buildName platformName } {
<name> $name] $fileName]
}
proc substFile { fileName } {
#
# NOTE: Performs all Tcl command, variable, and backslash substitutions in
# the specified file and then rewrites the contents of that same file
# with the substituted data.
#
return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]]
}
#
# NOTE: This is the entry point for this script.
#
@@ -206,7 +287,7 @@ set rootName [file rootname [file tail $script]]
# NOTE: Process and verify all the command line arguments.
#
set argc [llength $argv]
if {$argc < 1 || $argc > 4} then {fail}
if {$argc < 1 || $argc > 5} then {fail}
set binaryDirectory [lindex $argv 0]
@@ -251,58 +332,123 @@ if {[string length $packageFlavor] == 0} then {
fail "invalid package flavor"
}
if {[string equal -nocase $packageFlavor WinRT]} then {
set shortName SQLite.WinRT
set displayName "SQLite for Windows Runtime"
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.0
set minVsVersion 11.0
set extraSdkPath ""
set extraFileListAttributes [appendArgs \
"\r\n " {AppliesTo="WindowsAppContainer"} \
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
} elseif {[string equal -nocase $packageFlavor WinRT81]} then {
set shortName SQLite.WinRT81
set displayName "SQLite for Windows Runtime (Windows 8.1)"
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.1
set minVsVersion 12.0
set extraSdkPath ""
set extraFileListAttributes [appendArgs \
"\r\n " {AppliesTo="WindowsAppContainer"} \
"\r\n " {DependsOn="Microsoft.VCLibs, version=12.0"}]
} elseif {[string equal -nocase $packageFlavor WP80]} then {
set shortName SQLite.WP80
set displayName "SQLite for Windows Phone"
set targetPlatformIdentifier "Windows Phone"
set targetPlatformVersion v8.0
set minVsVersion 11.0
set extraSdkPath "\\..\\$targetPlatformIdentifier"
set extraFileListAttributes ""
} elseif {[string equal -nocase $packageFlavor Win32]} then {
set shortName SQLite.Win32
set displayName "SQLite for Windows"
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.0
set minVsVersion 11.0
set extraSdkPath ""
set extraFileListAttributes [appendArgs \
"\r\n " {AppliesTo="VisualC"} \
"\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}]
} else {
fail "unsupported package flavor, must be one of: WinRT WinRT81 WP80 Win32"
}
if {$argc >= 4} then {
set platformNames [list]
foreach platformName [split [lindex $argv 3] ", "] {
set platformName [string trim $platformName]
if {[string length $platformName] > 0} then {
lappend platformNames $platformName
}
}
}
if {$argc >= 5} then {
set vsVersion [lindex $argv 4]
} else {
set vsVersion 2012
}
if {[string length $vsVersion] == 0} then {
fail "invalid Visual Studio version"
}
if {![string equal $vsVersion 2012] && ![string equal $vsVersion 2013]} then {
fail [appendArgs \
"unsupported Visual Studio version, must be one of: " \
[list 2012 2013]]
}
set shortNames(WinRT,2012) SQLite.WinRT
set shortNames(WinRT,2013) SQLite.WinRT.2013
set shortNames(WinRT81,2013) SQLite.WinRT81
set shortNames(WP80,2012) SQLite.WP80
set shortNames(WP80,2013) SQLite.WP80.2013
set shortNames(WP81,2013) SQLite.WP81
set shortNames(Win32,2012) SQLite.Win32
set shortNames(Win32,2013) SQLite.Win32.2013
set displayNames(WinRT,2012) "SQLite for Windows Runtime"
set displayNames(WinRT,2013) "SQLite for Windows Runtime"
set displayNames(WinRT81,2013) "SQLite for Windows Runtime (Windows 8.1)"
set displayNames(WP80,2012) "SQLite for Windows Phone"
set displayNames(WP80,2013) "SQLite for Windows Phone"
set displayNames(WP81,2013) "SQLite for Windows Phone 8.1"
set displayNames(Win32,2012) "SQLite for Windows"
set displayNames(Win32,2013) "SQLite for Windows"
if {[string equal $packageFlavor WinRT]} then {
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath ""
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor WinRT81]} then {
if {$vsVersion ne "2013"} then {
fail [appendArgs \
"unsupported combination, package flavor " $packageFlavor \
" is only supported with Visual Studio 2013"]
}
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.1
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath ""
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor WP80]} then {
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier "Windows Phone"
set targetPlatformVersion v8.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath "\\..\\$targetPlatformIdentifier"
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor WP81]} then {
if {$vsVersion ne "2013"} then {
fail [appendArgs \
"unsupported combination, package flavor " $packageFlavor \
" is only supported with Visual Studio 2013"]
}
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier WindowsPhoneApp
set targetPlatformVersion v8.1
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath "\\..\\$targetPlatformIdentifier"
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} elseif {[string equal $packageFlavor Win32]} then {
set shortName $shortNames($packageFlavor,$vsVersion)
set displayName $displayNames($packageFlavor,$vsVersion)
set targetPlatformIdentifier Windows
set targetPlatformVersion v8.0
set minVsVersion [getMinVsVersionXmlChunk $vsVersion]
set maxPlatformVersion \
[getMaxPlatformVersionXmlChunk $packageFlavor $vsVersion]
set extraSdkPath ""
set extraFileListAttributes \
[getExtraFileListXmlChunk $packageFlavor $vsVersion]
} else {
fail [appendArgs \
"unsupported package flavor, must be one of: " \
[list WinRT WinRT81 WP80 WP81 Win32]]
}
###############################################################################
#
@@ -490,7 +636,7 @@ if {![info exists buildNames]} then {
# overridden via the command line or the user-specific customizations
# file.
#
if {![info exists platformNames]} then {
if {![info exists platformNames] || [llength $platformNames] == 0} then {
set platformNames [list x86 x64 ARM]
}
+1 -1
View File
@@ -4,7 +4,7 @@
# compiler warnings in SQLite.
#
rm -f sqlite3.c
make sqlite3.c-debug
make sqlite3.c
echo '********** No optimizations. Includes FTS4 and RTREE *********'
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
Binary file not shown.