Compare commits

..

76 Commits

Author SHA1 Message Date
mistachkin c216566ba5 Fix memory/resource leaks for WinCE and Cygwin.
FossilOrigin-Name: 2470d1bb08b2661bcfde7a605208eb6044836d5c
2013-10-16 09:49:10 +00:00
dan a4bbc8b119 Add the "languageid" hidden column to fts4aux.
FossilOrigin-Name: 891df358e51075fb937f34952ce43bf51130b0d0
2013-10-15 19:06:17 +00:00
dan cfe111b1f7 Changes to test code to make sure no server threads are left running after server1.test finishes.
FossilOrigin-Name: 1086e00bcaacc88ef2a9dda8a20698b0899ad2f7
2013-10-15 15:35:27 +00:00
drh a703f50d7e Fix an 8-byte alignment problem on the "crash test" harness (test code,
not in the core) that causes problems on Sparc.

FossilOrigin-Name: bcbc65030fa7c61f94100142e94ba2a5774f85b0
2013-10-15 14:29:32 +00:00
drh a2617433a9 Fix harmless macro redefinition warnings in the totype extension.
FossilOrigin-Name: c9c1f8d6701b0a1bc939a7e35e565d4160dbf8d3
2013-10-15 11:58:34 +00:00
mistachkin bc863b50ba Fix harmless macro redefinition warnings in the totype extension.
FossilOrigin-Name: a38adeb7ffd77474754b66877d60717cdb3cb865
2013-10-15 10:43:04 +00:00
mistachkin 0593516fcc Fix harmless compiler warning in the totype extension. Include all standard whitespace characters in totypeIsspace. Minor adjustments to style and comments.
FossilOrigin-Name: 73238f655a58c810876f46cc04eab1ac2d5b8ef7
2013-10-14 22:35:40 +00:00
drh 5f8cdac620 Move the tointeger() and toreal() functions out of core and make them into
a run-time loadable extension.

FossilOrigin-Name: 9f66dd7e3790c04f0ab724419f5381bd21f9ebad
2013-10-14 21:14:42 +00:00
dan 362d21614e Fix a crash in FTS incremental phrase processing that can occur if the second or subsequent token is much more common in the dataset than the first.
FossilOrigin-Name: 0bf438fc30582a08fddfc3cec49366ee17ae2abe
2013-10-14 20:30:51 +00:00
drh 4398c9524f Add implementations for the toInteger() and toReal() SQL functions.
FossilOrigin-Name: a0f7cbc068416cf55b86056f2ce7ee505c6cc3ea
2013-10-14 19:35:33 +00:00
dan 67896cef89 Fix for building with SQLITE_OMIT_FOREIGN_KEY.
FossilOrigin-Name: b8b5f6c8f646989bc62bb59416de9bca003a5896
2013-10-14 15:41:39 +00:00
drh 71d5338c5d Update the foreign_key_check pragma so that when a parent table is undefined
it is treated as an empty table.

FossilOrigin-Name: 208b259ad73b51e7df163fee3d7ed2bd79767597
2013-10-14 14:30:02 +00:00
drh 0ae4f14e45 Corrects to comments on the STAT4 implementation.
FossilOrigin-Name: e06f74d32d44f281dd21908d401184f35f9455a4
2013-10-14 14:21:59 +00:00
drh a7f4bf3f88 Make subroutines sampleCopy() and valueFromExpr() have file scope.
FossilOrigin-Name: 1660efbe46439734c7dc1674994ceb86a9b41d1a
2013-10-14 13:21:00 +00:00
drh c0f1d0c697 Add a new application_id for GeoPackage version 1.0.
FossilOrigin-Name: 98ddfe45713775657e586f5a2499cf3c036f13dd
2013-10-14 10:46:05 +00:00
mistachkin d5570119b7 Merge updates from trunk.
FossilOrigin-Name: a88b5be01e68b26267ff6eb05e931ef2e7fc9f99
2013-10-12 23:39:49 +00:00
drh 3ef261567a Restore the index_list pragma back to its former operation. Create a new
PRAGMA stats used to access the table and index widths and heights.

FossilOrigin-Name: f0cf8c85dcbcc7778aed2816792c368d777f79cb
2013-10-12 20:22:00 +00:00
dan 5e87830fa3 In "PRAGMA foreign_key_check", treat missing parent tables as empty (instead of as errors).
FossilOrigin-Name: 8c13a7fd738e5441af370537649b0bfa97679cda
2013-10-12 19:06:48 +00:00
dan a8dbadacee Fix handling of "DROP TABLE" commands when "PRAGMA defer_foreign_keys=1" is set.
FossilOrigin-Name: 27001356ed8201529b3f31d4313f2010f1b4e1b1
2013-10-12 15:12:43 +00:00
drh 5dbb7cc24f Add tests that demonstrate that PRAGMA defer_foreign_keys will reset to off
at the conclusion of the next transaction.

FossilOrigin-Name: 67e28a11de97e97889f0c0f41c05605721c605c1
2013-10-12 13:16:15 +00:00
mistachkin b084582299 Fix harmless compiler warning.
FossilOrigin-Name: 4b130f88fba216e088f61252bbcdde57ec7ee6a9
2013-10-12 02:33:22 +00:00
mistachkin 0ed02a6dcb Permit the creation of VSIX packages for Win32.
FossilOrigin-Name: 035d03e94252f31025b39da49d8401933352fb77
2013-10-12 02:31:34 +00:00
mistachkin 549bc3db1f Fix Unicode character encoding issues on Windows.
FossilOrigin-Name: c9310c9a2bad11f1d033a57b33ea7aed43a8238d
2013-10-12 00:56:21 +00:00
drh cf9fca4629 Identify requirements text in the SQLITE_CONFIG_ documentation. Fix a typo
(a duplicated word) in part of that documentation.  Add some requirements
marks for DETACH to the test scripts.  No code changes.

FossilOrigin-Name: 1be0a3adaba2914c65c46fbebc4906ae4e70f899
2013-10-11 23:37:57 +00:00
mistachkin 0aedc6be45 The split amalgamation option should be disabled by default.
FossilOrigin-Name: 7c24d22ffa1e12f3d24cad06b5ff7cc34219b2bb
2013-10-11 23:02:13 +00:00
mistachkin 7651091de5 Enhance debugging support for the split amalgamation files when compiling with MSVC.
FossilOrigin-Name: 8ff17c553d8c159fa81c961441e16dbba8da62ba
2013-10-11 23:01:18 +00:00
drh 2b51f2153b Fix a harmless compiler warning in lemon.c.
FossilOrigin-Name: 62959c0ce3a2c486ebd82e6511efad0412b944a0
2013-10-11 23:01:02 +00:00
mistachkin 691d4c9936 Add -no-undefined option when linking the shared libraries.
FossilOrigin-Name: 977d2b12e5efc70c26129b08c1f6d65c9d6d211e
2013-10-11 22:19:55 +00:00
mistachkin cbc53fec75 Fix test numbering.
FossilOrigin-Name: cef39f6933dcfec4b4a087a05dbb4e7766003fb7
2013-10-11 22:17:39 +00:00
drh e4bf4f08c0 Add requirements marks. No code changes.
FossilOrigin-Name: 5e0d43ab55de006b20c58cb18b938d1c7b658e51
2013-10-11 20:14:37 +00:00
drh 3432daa8b2 Additional test cases and requirements marks for the unlikely(),
likelihood() and instr() functions.

FossilOrigin-Name: 5f01cd36ee8678a07b79f9e01855daffb6bb8c43
2013-10-11 16:35:49 +00:00
drh 4f99189051 Fix various harmless compiler warnings. Change the "warnings.sh" script to
work with STAT4 instead of STAT3.

FossilOrigin-Name: 7df06684ab36bfdad9e9aca6940b7a665c2a0cb5
2013-10-11 15:05:05 +00:00
drh 80e0b72e8d Make sure the sqlite3.h file occurs at the very top of the sqlite3.c
amalgamation.

FossilOrigin-Name: 03593817ab5abdd4bbaa5e47e2e4745eef025af9
2013-10-11 13:27:26 +00:00
mistachkin e71e0603c5 Fix compilation issue for WinRT.
FossilOrigin-Name: 7a2006ca94c458c7b1eae7b2b6df51da67546462
2013-10-11 05:51:15 +00:00
drh 7e65c94bdc Add a rule to the main.mk makefile for building showdb.
FossilOrigin-Name: fc5552da0d3c41aea58292d267c247f9ca8ed474
2013-10-10 17:33:52 +00:00
drh a0cbd3fd17 Enhancements to the vfslog.c module to show all change-counter changes and
to show the hostname and pid of the process that creates each log file.

FossilOrigin-Name: af7abebeb1f70466833bc766d294d721eaef746f
2013-10-10 15:04:52 +00:00
drh 919e3b3908 Another fix to the hash signature algorithm in vfslog.c.
FossilOrigin-Name: 34212aa8c405c4ff3f8045ec0cf2a860af61540f
2013-10-10 13:41:04 +00:00
drh 7cd84ffc60 Fix the hash signature algorithm in vfslog.c. Add a utility program to
show the hash signatures for every page of a database file.

FossilOrigin-Name: eaf4de13a63b2294ae575432a022493308a4313a
2013-10-10 13:38:51 +00:00
dan 30e2f0ae08 Add ext/misc/vfslog.c, a VFS shim for unix that keeps a log of method calls made by SQLite.
FossilOrigin-Name: 24a827b87666670c56d68a18685f4f712852fa92
2013-10-10 13:04:46 +00:00
drh 3d8b2395b3 Estimate row sizes for tables and indices and use those estimates during
query planning.  Enhance the index_info pragma to show the estimated row
sizes and to show the estimated row size for the main table as well.  Allow
an alternative row size estimate to be specified in the sqlite_stat1 table.

FossilOrigin-Name: d27b88b8c2705f444f794096c719e6f38a792165
2013-10-10 12:38:11 +00:00
drh 26586e77d9 Make sure the correct printf format is used for type tRowcnt regardless
of whether 32-bit or 64-bit row counts are specified at compile-time.

FossilOrigin-Name: e97d7d3044aa6c5e21d1faab7d5e709d92faa261
2013-10-09 19:07:22 +00:00
drh 1f1fc0c24d Move a conditional inside of an #ifdef in order to make all branches
reachable regardless of compile-time options used.

FossilOrigin-Name: f7cc30d45b77f58c258b21f5823c2b39a44e2bf5
2013-10-08 23:16:48 +00:00
drh 833d198fb1 Fix test cases for the new information in PRAGMA index_list.
FossilOrigin-Name: dd03be1065537679c2daf5e4200902c47714fceb
2013-10-08 22:25:22 +00:00
drh b50596d64d Rollback some of the previous changes in the branch such that the estimated
row sizes are now only used as a tie-breaker for index scans.

FossilOrigin-Name: 65553ff34b41e54d129ff2fee96be714105503c4
2013-10-08 20:42:41 +00:00
drh 5f3e5e747d Use #ifdefs to omit unused code in the columnType() routine depending on
compile-time options.

FossilOrigin-Name: 3fd5e33217a91402b3499fa0977469b91618a928
2013-10-08 20:01:35 +00:00
drh 186ad8cc32 Further refinement of the idea of multiplying run-time cost estimates by
the estimated row size.

FossilOrigin-Name: 18bd6ba96d19de6047baebfa15b1f739577c9ec4
2013-10-08 18:40:37 +00:00
mistachkin 86f72f0721 Fix compilation issue with MSVC.
FossilOrigin-Name: 36d64dc36f18c166b2c93c43579fa3bbb5cd545f
2013-10-07 21:49:16 +00:00
drh 3495d20dbe Multiply all cursor step cost estimates by the estimated size of the row in
bytes, in order to get the query planner ot make use of estimated row sizes.
This check-in uses magic numbers in a few places (for example, estimates of
the size of output rows) and needs lots of refinement.  Consider this a
proof-of-concept only.

FossilOrigin-Name: cb34cfe57c2a664fbfae8106e95114400ea222d5
2013-10-07 17:32:15 +00:00
mistachkin bbff218016 Merge updates from trunk.
FossilOrigin-Name: 435ce3b3fc0cffb4d7e6f2694c3100066e19f9ed
2013-09-24 19:07:48 +00:00
mistachkin 9a5cbbc4a5 Merge updates from trunk.
FossilOrigin-Name: 8922be1a3e0269552e12b87fe1e5141c38a8d3f8
2013-09-06 22:27:55 +00:00
mistachkin 0157e01cc8 Add the ability to generate assembly listing files using the MSVC makefile.
FossilOrigin-Name: 6caa2cd10421a85db6740fb2ae8a42b573959562
2013-09-06 21:41:11 +00:00
mistachkin 9a5b271908 When converting from a BLOB value in the tointeger() and toreal() SQL functions, make sure that endianness of the machine does not matter.
FossilOrigin-Name: 94c4cdc50d2753c859e494d53cebd09edd2e5663
2013-09-06 20:30:53 +00:00
mistachkin aeddf19e60 Additional test cases for the tointeger() and toreal() SQL functions when converting from a BLOB.
FossilOrigin-Name: e1814452faa698946ef77f06a42665277ee59cc1
2013-09-04 00:58:00 +00:00
mistachkin 1c215c9fd4 Merge updates from trunk.
FossilOrigin-Name: 2982725e12715fba425a46ae024f317f031b6a54
2013-09-01 23:36:44 +00:00
mistachkin 05b1ba1e3f Handle BLOBs specially, treating them as binary, in the tointeger() and toreal() SQL functions.
FossilOrigin-Name: c4c53acb985a248c89db2d75025d941e3a4899bc
2013-08-31 21:41:09 +00:00
mistachkin a17713ff8d Disable several toreal() tests that require high floating point precision when it is unavailable.
FossilOrigin-Name: b724219b008d9851de18bd4158375100d781c5a3
2013-08-29 02:27:39 +00:00
mistachkin 09dee52885 Prevent the implementation of the toreal() SQL function from being 'optimized' by MSVC.
FossilOrigin-Name: 047bd1c24553b00ccf12d7745bb4c46820b91f5e
2013-08-29 01:17:24 +00:00
mistachkin 5db4f78ef5 Merge updates from trunk.
FossilOrigin-Name: 375dfe288fd0c4eb3c343a3cb23a7e3851903805
2013-08-29 01:11:45 +00:00
mistachkin 60883e5401 Fix boundary case for the toreal() SQL function.
FossilOrigin-Name: abe82c634ccda7d62687df5917d18a9d6e411142
2013-08-29 01:01:11 +00:00
mistachkin 312404ef76 Merge updates from trunk.
FossilOrigin-Name: ffc6e682836cdf275189427109f8af2aeb423bcd
2013-08-28 18:56:04 +00:00
mistachkin 98ab33a82f Add test cases for tointeger() and toreal() functions. Fixes for several tests.
FossilOrigin-Name: 5e1e9fd5e4f189836442baa42244be00de13ff0f
2013-08-20 09:26:38 +00:00
drh db1c12b79f Fix compiler warnings and boundary cases for the tointeger() and toreal()
functions.

FossilOrigin-Name: 4438b9865826446721b7aa09295fe335bf2fafb7
2013-08-20 02:07:50 +00:00
drh 36df58e45f Performance optimizations in the VDBE and especially to the OP_Next and
related opcodes.

FossilOrigin-Name: d78c5d89de4b840351b026c9db1952fc24e689d0
2013-08-20 00:42:11 +00:00
drh 5805eedb87 Performance improvement to SQL function calls in the VDBE.
FossilOrigin-Name: d2efea1682a7e708000c1f5d36370aaf1199b3be
2013-08-19 23:18:12 +00:00
drh 749ced9923 Additional performance improvements in sqlite3BtreeNext() and
sqlite3BtreePrevious().

FossilOrigin-Name: 6f99b54aedeb91e46d52f65504d02a9cc61c0062
2013-08-19 22:22:41 +00:00
mistachkin cf02d7cf0b Add tointeger() and toreal() SQL functions.
FossilOrigin-Name: af49707211ff7c7c4d30f4f457631ea8a9fa39eb
2013-08-19 21:15:34 +00:00
mistachkin 626c25846c Merge updates from trunk.
FossilOrigin-Name: dd4b77c82af07bdcc92ed743f050e70887e5956e
2013-07-20 00:39:33 +00:00
drh 0057a74675 Merge in the latest changes from trunk. Simplify the implementation of the
tointeger() and toreal() functions.  Fix test cases and put unambiguous
labels on all testcase names.

FossilOrigin-Name: 9b837b0508fbfb395f0a0d8e4bd127730c80ffc5
2013-06-21 19:29:33 +00:00
mistachkin f5fe3ae9e6 Merge updates from trunk.
FossilOrigin-Name: fa2a91e6c631864846484d13cffdc51856953cd1
2013-06-21 18:32:11 +00:00
mistachkin 1654256ac8 Merge updates from trunk.
FossilOrigin-Name: 6fbad957259eb8c15eaf7e5657240ae24aaf343e
2013-05-15 08:00:44 +00:00
mistachkin f13394c0ad Experimental changes to support a Win32 VSIX package flavor.
FossilOrigin-Name: abedd7cb454aab99b62b63ed4fdd70c31ef87b0b
2013-04-11 00:13:46 +00:00
mistachkin 46d269bc14 Merge updates from trunk.
FossilOrigin-Name: d63fa039a01330f5300c3a936d2f9ffb018952b9
2013-03-13 20:52:11 +00:00
mistachkin bc3ec28b88 Rename the experimental todouble() function to toreal(), update comments.
FossilOrigin-Name: 12c318ef1b674d1ef347458ce149398885f5ba10
2013-03-13 06:48:05 +00:00
mistachkin ee1c64ed25 Increase strictness of the new experimental functions and add more tests.
FossilOrigin-Name: 05c4463ec5f36dde50f6eb116624dc40142f2c8c
2013-03-12 09:07:25 +00:00
mistachkin 32be00a55b Add more tests.
FossilOrigin-Name: f9468e334d6086b8a80c6a4204ec4e03fe59cf96
2013-03-11 06:24:46 +00:00
mistachkin 69f3d04810 Add experimental tointeger() and todouble() SQL functions.
FossilOrigin-Name: 465fd853d3e3544cb06b15ffa32ce25774d816c7
2013-03-11 01:23:37 +00:00
52 changed files with 3177 additions and 358 deletions
+3 -2
View File
@@ -396,6 +396,7 @@ TESTSRC += \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/wholenumber.c
# Source code to the library files needed by the test fixture
@@ -500,11 +501,11 @@ sqlite3.pc: $(TOP)/sqlite3.pc.in
./config.status
libsqlite3.la: $(LIBOBJ)
$(LTLINK) -o $@ $(LIBOBJ) $(TLIBS) \
$(LTLINK) -no-undefined -o $@ $(LIBOBJ) $(TLIBS) \
${ALLOWRELEASE} -rpath "$(libdir)" -version-info "8:6:8"
libtclsqlite3.la: tclsqlite.lo libsqlite3.la
$(LTLINK) -o $@ tclsqlite.lo \
$(LTLINK) -no-undefined -o $@ tclsqlite.lo \
libsqlite3.la @TCL_STUB_LIB_SPEC@ $(TLIBS) \
-rpath "$(TCLLIBDIR)" \
-version-info "8:6:8" \
+45 -7
View File
@@ -13,6 +13,13 @@ TOP = .
USE_AMALGAMATION = 1
!ENDIF
# Set this non-0 to split the SQLite amalgamation file into chunks to
# be used for debugging with Visual Studio.
#
!IFNDEF SPLIT_AMALGAMATION
SPLIT_AMALGAMATION = 0
!ENDIF
# Set this non-0 to use the International Components for Unicode (ICU).
#
!IFNDEF USE_ICU
@@ -25,6 +32,13 @@ USE_ICU = 0
USE_CRT_DLL = 0
!ENDIF
# Set this non-0 to generate assembly code listings for the source code
# files.
#
!IFNDEF USE_LISTINGS
USE_LISTINGS = 0
!ENDIF
# Set this non-0 to attempt setting the native compiler automatically
# for cross-compiling the command line tools needed during the compilation
# process.
@@ -181,6 +195,13 @@ NSDKLIBPATH = $(NSDKLIBPATH:\\=\)
#
BCC = $(NCC) -W3
# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
!IF $(USE_LISTINGS)!=0
BCC = $(BCC) -FAcs
!ENDIF
# Check if the native library paths should be used when compiling
# the command line tools used during the compilation process. If
# so, set the necessary macro now.
@@ -196,6 +217,13 @@ NLTLIBPATHS = "/LIBPATH:$(NCRTLIBPATH)" "/LIBPATH:$(NSDKLIBPATH)"
TCC = $(CC) -W3 -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src -fp:precise
RCC = $(RC) -DSQLITE_OS_WIN=1 -I$(TOP) -I$(TOP)\src
# Check if assembly code listings should be generated for the source
# code files to be compiled.
#
!IF $(USE_LISTINGS)!=0
TCC = $(TCC) -FAcs
!ENDIF
# When compiling the library for use in the WinRT environment,
# the following compile-time options must be used as well to
# disable use of Win32 APIs that are not available and to enable
@@ -754,6 +782,7 @@ TESTEXT = \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \
$(TOP)\ext\misc\spellfix.c \
$(TOP)\ext\misc\totype.c \
$(TOP)\ext\misc\wholenumber.c
@@ -892,10 +921,19 @@ sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
$(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl
# Set the source code file to be used by executables and libraries when
# they need the amalgamation.
#
!IF $(SPLIT_AMALGAMATION)!=0
SQLITE3C = sqlite3-all.c
!ELSE
SQLITE3C = sqlite3.c
!ENDIF
# Rule to build the amalgamation
#
sqlite3.lo: sqlite3.c
$(LTCOMPILE) -c sqlite3.c
sqlite3.lo: $(SQLITE3C)
$(LTCOMPILE) -c $(SQLITE3C)
# Rules to build the LEMON compiler generator
#
@@ -1255,7 +1293,7 @@ TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2) libsqlite3.lib
TESTFIXTURE_SRC1 = $(TESTEXT) sqlite3.c
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
!IF $(USE_AMALGAMATION)==0
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
!ELSE
@@ -1283,8 +1321,8 @@ queryplantest: testfixture.exe sqlite3.exe
test: testfixture.exe sqlite3.exe
.\testfixture.exe $(TOP)\test\veryquick.test
sqlite3_analyzer.c: sqlite3.c $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
copy sqlite3.c + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@
sqlite3_analyzer.c: $(SQLITE3C) $(TOP)\src\test_stat.c $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
copy $(SQLITE3C) + $(TOP)\src\test_stat.c + $(TOP)\src\tclsqlite.c $@
echo static const char *tclsh_main_loop(void){ >> $@
echo static const char *zMainloop = >> $@
$(NAWK) -f $(TOP)\tool\tostr.awk $(TOP)\tool\spaceanal.tcl >> $@
@@ -1296,7 +1334,7 @@ sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
clean:
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
del /Q *.da *.bb *.bbg gmon.out
del /Q *.cod *.da *.bb *.bbg gmon.out
del /Q sqlite3.h opcodes.c opcodes.h
del /Q lemon.exe lempar.c parse.*
del /Q mkkeywordhash.exe keywordhash.h
@@ -1310,7 +1348,7 @@ clean:
del /Q tclsqlite3.exe tclsqlite3.exp
del /Q testfixture.exe testfixture.exp test.db
del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def
del /Q sqlite3.c
del /Q sqlite3.c sqlite3-*.c
del /Q sqlite3rc.h
del /Q shell.c sqlite3ext.h
del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c
+4 -4
View File
@@ -3036,7 +3036,7 @@ static int fts3FilterMethod(
){
int rc;
char *zSql; /* SQL statement used to access %_content */
int eSearch;;
int eSearch;
Fts3Table *p = (Fts3Table *)pCursor->pVtab;
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
@@ -4327,11 +4327,11 @@ static int fts3EvalIncrPhraseNext(
while( bEof==0 ){
int bMaxSet = 0;
sqlite3_int64 iMax; /* Largest docid for all iterators */
sqlite3_int64 iMax = 0; /* Largest docid for all iterators */
int i; /* Used to iterate through tokens */
/* Advance the iterator for each token in the phrase once. */
for(i=0; rc==SQLITE_OK && i<p->nToken; i++){
for(i=0; rc==SQLITE_OK && i<p->nToken && bEof==0; i++){
rc = incrPhraseTokenNext(pTab, p, i, &a[i], &bEof);
if( a[i].bIgnore==0 && (bMaxSet==0 || DOCID_CMP(iMax, a[i].iDocid)<0) ){
iMax = a[i].iDocid;
@@ -4370,7 +4370,7 @@ static int fts3EvalIncrPhraseNext(
int nDist = p->nToken-1-i;
int res = fts3PoslistPhraseMerge(&pOut, nDist, 0, 1, &pL, &pR);
if( res==0 ) break;
nList = (pOut - aDoclist);
nList = (int)(pOut - aDoclist);
}
}
if( i==(p->nToken-1) ){
+96 -33
View File
@@ -31,6 +31,7 @@ struct Fts3auxCursor {
Fts3SegFilter filter;
char *zStop;
int nStop; /* Byte-length of string zStop */
int iLangid; /* Language id to query */
int isEof; /* True if cursor is at EOF */
sqlite3_int64 iRowid; /* Current rowid */
@@ -45,7 +46,8 @@ struct Fts3auxCursor {
/*
** Schema of the terms table.
*/
#define FTS3_TERMS_SCHEMA "CREATE TABLE x(term, col, documents, occurrences)"
#define FTS3_AUX_SCHEMA \
"CREATE TABLE x(term, col, documents, occurrences, languageid HIDDEN)"
/*
** This function does all the work for both the xConnect and xCreate methods.
@@ -92,7 +94,7 @@ static int fts3auxConnectMethod(
}
nFts3 = (int)strlen(zFts3);
rc = sqlite3_declare_vtab(db, FTS3_TERMS_SCHEMA);
rc = sqlite3_declare_vtab(db, FTS3_AUX_SCHEMA);
if( rc!=SQLITE_OK ) return rc;
nByte = sizeof(Fts3auxTable) + sizeof(Fts3Table) + nDb + nFts3 + 2;
@@ -152,6 +154,8 @@ static int fts3auxBestIndexMethod(
int iEq = -1;
int iGe = -1;
int iLe = -1;
int iLangid = -1;
int iNext = 1; /* Next free argvIndex value */
UNUSED_PARAMETER(pVTab);
@@ -163,36 +167,48 @@ static int fts3auxBestIndexMethod(
pInfo->orderByConsumed = 1;
}
/* Search for equality and range constraints on the "term" column. */
/* Search for equality and range constraints on the "term" column.
** And equality constraints on the hidden "languageid" column. */
for(i=0; i<pInfo->nConstraint; i++){
if( pInfo->aConstraint[i].usable && pInfo->aConstraint[i].iColumn==0 ){
if( pInfo->aConstraint[i].usable ){
int op = pInfo->aConstraint[i].op;
if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
int iCol = pInfo->aConstraint[i].iColumn;
if( iCol==0 ){
if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iEq = i;
if( op==SQLITE_INDEX_CONSTRAINT_LT ) iLe = i;
if( op==SQLITE_INDEX_CONSTRAINT_LE ) iLe = i;
if( op==SQLITE_INDEX_CONSTRAINT_GT ) iGe = i;
if( op==SQLITE_INDEX_CONSTRAINT_GE ) iGe = i;
}
if( iCol==4 ){
if( op==SQLITE_INDEX_CONSTRAINT_EQ ) iLangid = i;
}
}
}
if( iEq>=0 ){
pInfo->idxNum = FTS4AUX_EQ_CONSTRAINT;
pInfo->aConstraintUsage[iEq].argvIndex = 1;
pInfo->aConstraintUsage[iEq].argvIndex = iNext++;
pInfo->estimatedCost = 5;
}else{
pInfo->idxNum = 0;
pInfo->estimatedCost = 20000;
if( iGe>=0 ){
pInfo->idxNum += FTS4AUX_GE_CONSTRAINT;
pInfo->aConstraintUsage[iGe].argvIndex = 1;
pInfo->aConstraintUsage[iGe].argvIndex = iNext++;
pInfo->estimatedCost /= 2;
}
if( iLe>=0 ){
pInfo->idxNum += FTS4AUX_LE_CONSTRAINT;
pInfo->aConstraintUsage[iLe].argvIndex = 1 + (iGe>=0);
pInfo->aConstraintUsage[iLe].argvIndex = iNext++;
pInfo->estimatedCost /= 2;
}
}
if( iLangid>=0 ){
pInfo->aConstraintUsage[iLangid].argvIndex = iNext++;
pInfo->estimatedCost--;
}
return SQLITE_OK;
}
@@ -352,7 +368,14 @@ static int fts3auxFilterMethod(
Fts3auxCursor *pCsr = (Fts3auxCursor *)pCursor;
Fts3Table *pFts3 = ((Fts3auxTable *)pCursor->pVtab)->pFts3Tab;
int rc;
int isScan;
int isScan = 0;
int iLangVal = 0; /* Language id to query */
int iEq = -1; /* Index of term=? value in apVal */
int iGe = -1; /* Index of term>=? value in apVal */
int iLe = -1; /* Index of term<=? value in apVal */
int iLangid = -1; /* Index of languageid=? value in apVal */
int iNext = 0;
UNUSED_PARAMETER(nVal);
UNUSED_PARAMETER(idxStr);
@@ -362,7 +385,21 @@ static int fts3auxFilterMethod(
|| idxNum==FTS4AUX_LE_CONSTRAINT || idxNum==FTS4AUX_GE_CONSTRAINT
|| idxNum==(FTS4AUX_LE_CONSTRAINT|FTS4AUX_GE_CONSTRAINT)
);
isScan = (idxNum!=FTS4AUX_EQ_CONSTRAINT);
if( idxNum==FTS4AUX_EQ_CONSTRAINT ){
iEq = iNext++;
}else{
isScan = 1;
if( idxNum & FTS4AUX_GE_CONSTRAINT ){
iGe = iNext++;
}
if( idxNum & FTS4AUX_LE_CONSTRAINT ){
iLe = iNext++;
}
}
if( iNext<nVal ){
iLangid = iNext++;
}
/* In case this cursor is being reused, close and zero it. */
testcase(pCsr->filter.zTerm);
@@ -374,22 +411,35 @@ static int fts3auxFilterMethod(
pCsr->filter.flags = FTS3_SEGMENT_REQUIRE_POS|FTS3_SEGMENT_IGNORE_EMPTY;
if( isScan ) pCsr->filter.flags |= FTS3_SEGMENT_SCAN;
if( idxNum&(FTS4AUX_EQ_CONSTRAINT|FTS4AUX_GE_CONSTRAINT) ){
if( iEq>=0 || iGe>=0 ){
const unsigned char *zStr = sqlite3_value_text(apVal[0]);
assert( (iEq==0 && iGe==-1) || (iEq==-1 && iGe==0) );
if( zStr ){
pCsr->filter.zTerm = sqlite3_mprintf("%s", zStr);
pCsr->filter.nTerm = sqlite3_value_bytes(apVal[0]);
if( pCsr->filter.zTerm==0 ) return SQLITE_NOMEM;
}
}
if( idxNum&FTS4AUX_LE_CONSTRAINT ){
int iIdx = (idxNum&FTS4AUX_GE_CONSTRAINT) ? 1 : 0;
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iIdx]));
pCsr->nStop = sqlite3_value_bytes(apVal[iIdx]);
if( iLe>=0 ){
pCsr->zStop = sqlite3_mprintf("%s", sqlite3_value_text(apVal[iLe]));
pCsr->nStop = sqlite3_value_bytes(apVal[iLe]);
if( pCsr->zStop==0 ) return SQLITE_NOMEM;
}
if( iLangid>=0 ){
iLangVal = sqlite3_value_int(apVal[iLangid]);
rc = sqlite3Fts3SegReaderCursor(pFts3, 0, 0, FTS3_SEGCURSOR_ALL,
/* If the user specified a negative value for the languageid, use zero
** instead. This works, as the "languageid=?" constraint will also
** be tested by the VDBE layer. The test will always be false (since
** this module will not return a row with a negative languageid), and
** so the overall query will return zero rows. */
if( iLangVal<0 ) iLangVal = 0;
}
pCsr->iLangid = iLangVal;
rc = sqlite3Fts3SegReaderCursor(pFts3, iLangVal, 0, FTS3_SEGCURSOR_ALL,
pCsr->filter.zTerm, pCsr->filter.nTerm, 0, isScan, &pCsr->csr
);
if( rc==SQLITE_OK ){
@@ -413,24 +463,37 @@ static int fts3auxEofMethod(sqlite3_vtab_cursor *pCursor){
*/
static int fts3auxColumnMethod(
sqlite3_vtab_cursor *pCursor, /* Cursor to retrieve value from */
sqlite3_context *pContext, /* Context for sqlite3_result_xxx() calls */
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
Fts3auxCursor *p = (Fts3auxCursor *)pCursor;
assert( p->isEof==0 );
if( iCol==0 ){ /* Column "term" */
sqlite3_result_text(pContext, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
}else if( iCol==1 ){ /* Column "col" */
if( p->iCol ){
sqlite3_result_int(pContext, p->iCol-1);
}else{
sqlite3_result_text(pContext, "*", -1, SQLITE_STATIC);
}
}else if( iCol==2 ){ /* Column "documents" */
sqlite3_result_int64(pContext, p->aStat[p->iCol].nDoc);
}else{ /* Column "occurrences" */
sqlite3_result_int64(pContext, p->aStat[p->iCol].nOcc);
switch( iCol ){
case 0: /* term */
sqlite3_result_text(pCtx, p->csr.zTerm, p->csr.nTerm, SQLITE_TRANSIENT);
break;
case 1: /* col */
if( p->iCol ){
sqlite3_result_int(pCtx, p->iCol-1);
}else{
sqlite3_result_text(pCtx, "*", -1, SQLITE_STATIC);
}
break;
case 2: /* documents */
sqlite3_result_int64(pCtx, p->aStat[p->iCol].nDoc);
break;
case 3: /* occurrences */
sqlite3_result_int64(pCtx, p->aStat[p->iCol].nOcc);
break;
default: /* languageid */
assert( iCol==4 );
sqlite3_result_int(pCtx, p->iLangid);
break;
}
return SQLITE_OK;
+1 -1
View File
@@ -4780,7 +4780,7 @@ static int fts3DoAutoincrmerge(
if( rc ) return rc;
}
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
if( rc ) return rc;;
if( rc ) return rc;
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
sqlite3_step(pStmt);
+512
View File
@@ -0,0 +1,512 @@
/*
** 2013-10-14
**
** 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 SQLite extension implements functions tointeger(X) and toreal(X).
**
** If X is an integer, real, or string value that can be
** losslessly represented as an integer, then tointeger(X)
** returns the corresponding integer value.
** If X is an 8-byte BLOB then that blob is interpreted as
** a signed two-compliment little-endian encoding of an integer
** and tointeger(X) returns the corresponding integer value.
** Otherwise tointeger(X) return NULL.
**
** If X is an integer, real, or string value that can be
** convert into a real number, preserving at least 15 digits
** of precision, then toreal(X) returns the corresponding real value.
** If X is an 8-byte BLOB then that blob is interpreted as
** a 64-bit IEEE754 big-endian floating point value
** and toreal(X) returns the corresponding real value.
** Otherwise toreal(X) return NULL.
**
** Note that tointeger(X) of an 8-byte BLOB assumes a little-endian
** encoding whereas toreal(X) of an 8-byte BLOB assumes a big-endian
** encoding.
*/
#include "sqlite3ext.h"
SQLITE_EXTENSION_INIT1
#include <assert.h>
#include <string.h>
/*
** Determine if this is running on a big-endian or little-endian
** processor
*/
#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
|| defined(__x86_64) || defined(__x86_64__)
# define TOTYPE_BIGENDIAN 0
# define TOTYPE_LITTLEENDIAN 1
#else
const int totype_one = 1;
# define TOTYPE_BIGENDIAN (*(char *)(&totype_one)==0)
# define TOTYPE_LITTLEENDIAN (*(char *)(&totype_one)==1)
#endif
/*
** Constants for the largest and smallest possible 64-bit signed integers.
** These macros are designed to work correctly on both 32-bit and 64-bit
** compilers.
*/
#ifndef LARGEST_INT64
# define LARGEST_INT64 (0xffffffff|(((sqlite3_int64)0x7fffffff)<<32))
#endif
#ifndef SMALLEST_INT64
# define SMALLEST_INT64 (((sqlite3_int64)-1) - LARGEST_INT64)
#endif
/*
** Return TRUE if character c is a whitespace character
*/
static int totypeIsspace(unsigned char c){
return c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f' || c=='\r';
}
/*
** Return TRUE if character c is a digit
*/
static int totypeIsdigit(unsigned char c){
return c>='0' && c<='9';
}
/*
** Compare the 19-character string zNum against the text representation
** value 2^63: 9223372036854775808. Return negative, zero, or positive
** if zNum is less than, equal to, or greater than the string.
** Note that zNum must contain exactly 19 characters.
**
** Unlike memcmp() this routine is guaranteed to return the difference
** in the values of the last digit if the only difference is in the
** last digit. So, for example,
**
** totypeCompare2pow63("9223372036854775800")
**
** will return -8.
*/
static int totypeCompare2pow63(const char *zNum){
int c = 0;
int i;
/* 012345678901234567 */
const char *pow63 = "922337203685477580";
for(i=0; c==0 && i<18; i++){
c = (zNum[i]-pow63[i])*10;
}
if( c==0 ){
c = zNum[18] - '8';
}
return c;
}
/*
** Convert zNum to a 64-bit signed integer.
**
** If the zNum value is representable as a 64-bit twos-complement
** integer, then write that value into *pNum and return 0.
**
** If zNum is exactly 9223372036854665808, return 2. This special
** case is broken out because while 9223372036854665808 cannot be a
** signed 64-bit integer, its negative -9223372036854665808 can be.
**
** If zNum is too big for a 64-bit integer and is not
** 9223372036854665808 or if zNum contains any non-numeric text,
** then return 1.
**
** The string is not necessarily zero-terminated.
*/
static int totypeAtoi64(const char *zNum, sqlite3_int64 *pNum, int length){
sqlite3_uint64 u = 0;
int neg = 0; /* assume positive */
int i;
int c = 0;
int nonNum = 0;
const char *zStart;
const char *zEnd = zNum + length;
while( zNum<zEnd && totypeIsspace(*zNum) ) zNum++;
if( zNum<zEnd ){
if( *zNum=='-' ){
neg = 1;
zNum++;
}else if( *zNum=='+' ){
zNum++;
}
}
zStart = zNum;
while( zNum<zEnd && zNum[0]=='0' ){ zNum++; } /* Skip leading zeros. */
for(i=0; &zNum[i]<zEnd && (c=zNum[i])>='0' && c<='9'; i++){
u = u*10 + c - '0';
}
if( u>LARGEST_INT64 ){
*pNum = SMALLEST_INT64;
}else if( neg ){
*pNum = -(sqlite3_int64)u;
}else{
*pNum = (sqlite3_int64)u;
}
if( (c!=0 && &zNum[i]<zEnd) || (i==0 && zStart==zNum) || i>19 || nonNum ){
/* zNum is empty or contains non-numeric text or is longer
** than 19 digits (thus guaranteeing that it is too large) */
return 1;
}else if( i<19 ){
/* Less than 19 digits, so we know that it fits in 64 bits */
assert( u<=LARGEST_INT64 );
return 0;
}else{
/* zNum is a 19-digit numbers. Compare it against 9223372036854775808. */
c = totypeCompare2pow63(zNum);
if( c<0 ){
/* zNum is less than 9223372036854775808 so it fits */
assert( u<=LARGEST_INT64 );
return 0;
}else if( c>0 ){
/* zNum is greater than 9223372036854775808 so it overflows */
return 1;
}else{
/* zNum is exactly 9223372036854775808. Fits if negative. The
** special case 2 overflow if positive */
assert( u-1==LARGEST_INT64 );
assert( (*pNum)==SMALLEST_INT64 );
return neg ? 0 : 2;
}
}
}
/*
** The string z[] is an text representation of a real number.
** Convert this string to a double and write it into *pResult.
**
** The string is not necessarily zero-terminated.
**
** Return TRUE if the result is a valid real number (or integer) and FALSE
** if the string is empty or contains extraneous text. Valid numbers
** are in one of these formats:
**
** [+-]digits[E[+-]digits]
** [+-]digits.[digits][E[+-]digits]
** [+-].digits[E[+-]digits]
**
** Leading and trailing whitespace is ignored for the purpose of determining
** validity.
**
** If some prefix of the input string is a valid number, this routine
** returns FALSE but it still converts the prefix and writes the result
** into *pResult.
*/
static int totypeAtoF(const char *z, double *pResult, int length){
const char *zEnd = z + length;
/* sign * significand * (10 ^ (esign * exponent)) */
int sign = 1; /* sign of significand */
sqlite3_int64 s = 0; /* significand */
int d = 0; /* adjust exponent for shifting decimal point */
int esign = 1; /* sign of exponent */
int e = 0; /* exponent */
int eValid = 1; /* True exponent is either not used or is well-formed */
double result;
int nDigits = 0;
int nonNum = 0;
*pResult = 0.0; /* Default return value, in case of an error */
/* skip leading spaces */
while( z<zEnd && totypeIsspace(*z) ) z++;
if( z>=zEnd ) return 0;
/* get sign of significand */
if( *z=='-' ){
sign = -1;
z++;
}else if( *z=='+' ){
z++;
}
/* skip leading zeroes */
while( z<zEnd && z[0]=='0' ) z++, nDigits++;
/* copy max significant digits to significand */
while( z<zEnd && totypeIsdigit(*z) && s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
z++, nDigits++;
}
/* skip non-significant significand digits
** (increase exponent by d to shift decimal left) */
while( z<zEnd && totypeIsdigit(*z) ) z++, nDigits++, d++;
if( z>=zEnd ) goto totype_atof_calc;
/* if decimal point is present */
if( *z=='.' ){
z++;
/* copy digits from after decimal to significand
** (decrease exponent by d to shift decimal right) */
while( z<zEnd && totypeIsdigit(*z) && s<((LARGEST_INT64-9)/10) ){
s = s*10 + (*z - '0');
z++, nDigits++, d--;
}
/* skip non-significant digits */
while( z<zEnd && totypeIsdigit(*z) ) z++, nDigits++;
}
if( z>=zEnd ) goto totype_atof_calc;
/* if exponent is present */
if( *z=='e' || *z=='E' ){
z++;
eValid = 0;
if( z>=zEnd ) goto totype_atof_calc;
/* get sign of exponent */
if( *z=='-' ){
esign = -1;
z++;
}else if( *z=='+' ){
z++;
}
/* copy digits to exponent */
while( z<zEnd && totypeIsdigit(*z) ){
e = e<10000 ? (e*10 + (*z - '0')) : 10000;
z++;
eValid = 1;
}
}
/* skip trailing spaces */
if( nDigits && eValid ){
while( z<zEnd && totypeIsspace(*z) ) z++;
}
totype_atof_calc:
/* adjust exponent by d, and update sign */
e = (e*esign) + d;
if( e<0 ) {
esign = -1;
e *= -1;
} else {
esign = 1;
}
/* if 0 significand */
if( !s ) {
/* In the IEEE 754 standard, zero is signed.
** Add the sign if we've seen at least one digit */
result = (sign<0 && nDigits) ? -(double)0 : (double)0;
} else {
/* attempt to reduce exponent */
if( esign>0 ){
while( s<(LARGEST_INT64/10) && e>0 ) e--,s*=10;
}else{
while( !(s%10) && e>0 ) e--,s/=10;
}
/* adjust the sign of significand */
s = sign<0 ? -s : s;
/* if exponent, scale significand as appropriate
** and store in result. */
if( e ){
double scale = 1.0;
/* attempt to handle extremely small/large numbers better */
if( e>307 && e<342 ){
while( e%308 ) { scale *= 1.0e+1; e -= 1; }
if( esign<0 ){
result = s / scale;
result /= 1.0e+308;
}else{
result = s * scale;
result *= 1.0e+308;
}
}else if( e>=342 ){
if( esign<0 ){
result = 0.0*s;
}else{
result = 1e308*1e308*s; /* Infinity */
}
}else{
/* 1.0e+22 is the largest power of 10 than can be
** represented exactly. */
while( e%22 ) { scale *= 1.0e+1; e -= 1; }
while( e>0 ) { scale *= 1.0e+22; e -= 22; }
if( esign<0 ){
result = s / scale;
}else{
result = s * scale;
}
}
} else {
result = (double)s;
}
}
/* store the result */
*pResult = result;
/* return true if number and no extra non-whitespace chracters after */
return z>=zEnd && nDigits>0 && eValid && nonNum==0;
}
/*
** tointeger(X): If X is any value (integer, double, blob, or string) that
** can be losslessly converted into an integer, then make the conversion and
** return the result. Otherwise, return NULL.
*/
static void tointegerFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
(void)argc;
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_FLOAT: {
double rVal = sqlite3_value_double(argv[0]);
sqlite3_int64 iVal = (sqlite3_int64)rVal;
if( rVal==(double)iVal ){
sqlite3_result_int64(context, iVal);
}
break;
}
case SQLITE_INTEGER: {
sqlite3_result_int64(context, sqlite3_value_int64(argv[0]));
break;
}
case SQLITE_BLOB: {
const unsigned char *zBlob = sqlite3_value_blob(argv[0]);
if( zBlob ){
int nBlob = sqlite3_value_bytes(argv[0]);
if( nBlob==sizeof(sqlite3_int64) ){
sqlite3_int64 iVal;
if( TOTYPE_BIGENDIAN ){
int i;
unsigned char zBlobRev[sizeof(sqlite3_int64)];
for(i=0; i<sizeof(sqlite3_int64); i++){
zBlobRev[i] = zBlob[sizeof(sqlite3_int64)-1-i];
}
memcpy(&iVal, zBlobRev, sizeof(sqlite3_int64));
}else{
memcpy(&iVal, zBlob, sizeof(sqlite3_int64));
}
sqlite3_result_int64(context, iVal);
}
}
break;
}
case SQLITE_TEXT: {
const unsigned char *zStr = sqlite3_value_text(argv[0]);
if( zStr ){
int nStr = sqlite3_value_bytes(argv[0]);
if( nStr && !totypeIsspace(zStr[0]) ){
sqlite3_int64 iVal;
if( !totypeAtoi64((const char*)zStr, &iVal, nStr) ){
sqlite3_result_int64(context, iVal);
}
}
}
break;
}
default: {
assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
break;
}
}
}
/*
** toreal(X): If X is any value (integer, double, blob, or string) that can
** be losslessly converted into a real number, then do so and return that
** real number. Otherwise return NULL.
*/
#if defined(_MSC_VER)
#pragma warning(disable: 4748)
#pragma optimize("", off)
#endif
static void torealFunc(
sqlite3_context *context,
int argc,
sqlite3_value **argv
){
assert( argc==1 );
(void)argc;
switch( sqlite3_value_type(argv[0]) ){
case SQLITE_FLOAT: {
sqlite3_result_double(context, sqlite3_value_double(argv[0]));
break;
}
case SQLITE_INTEGER: {
sqlite3_int64 iVal = sqlite3_value_int64(argv[0]);
double rVal = (double)iVal;
if( iVal==(sqlite3_int64)rVal ){
sqlite3_result_double(context, rVal);
}
break;
}
case SQLITE_BLOB: {
const unsigned char *zBlob = sqlite3_value_blob(argv[0]);
if( zBlob ){
int nBlob = sqlite3_value_bytes(argv[0]);
if( nBlob==sizeof(double) ){
double rVal;
if( TOTYPE_LITTLEENDIAN ){
int i;
unsigned char zBlobRev[sizeof(double)];
for(i=0; i<sizeof(double); i++){
zBlobRev[i] = zBlob[sizeof(double)-1-i];
}
memcpy(&rVal, zBlobRev, sizeof(double));
}else{
memcpy(&rVal, zBlob, sizeof(double));
}
sqlite3_result_double(context, rVal);
}
}
break;
}
case SQLITE_TEXT: {
const unsigned char *zStr = sqlite3_value_text(argv[0]);
if( zStr ){
int nStr = sqlite3_value_bytes(argv[0]);
if( nStr && !totypeIsspace(zStr[0]) && !totypeIsspace(zStr[nStr-1]) ){
double rVal;
if( totypeAtoF((const char*)zStr, &rVal, nStr) ){
sqlite3_result_double(context, rVal);
return;
}
}
}
break;
}
default: {
assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
break;
}
}
}
#if defined(_MSC_VER)
#pragma optimize("", on)
#pragma warning(default: 4748)
#endif
#ifdef _WIN32
__declspec(dllexport)
#endif
int sqlite3_totype_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
){
int rc = SQLITE_OK;
SQLITE_EXTENSION_INIT2(pApi);
(void)pzErrMsg; /* Unused parameter */
rc = sqlite3_create_function(db, "tointeger", 1, SQLITE_UTF8, 0,
tointegerFunc, 0, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(db, "toreal", 1, SQLITE_UTF8, 0,
torealFunc, 0, 0);
}
return rc;
}
+706
View File
@@ -0,0 +1,706 @@
/*
** 2013-10-09
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
******************************************************************************
**
** This file contains the implementation of an SQLite vfs wrapper for
** unix that generates per-database log files of all disk activity.
*/
/*
** This module contains code for a wrapper VFS that causes a log of
** most VFS calls to be written into a file on disk. The log
** is stored as comma-separated variables.
**
** All calls on sqlite3_file objects are logged.
** Additionally, calls to the xAccess(), xOpen(), and xDelete()
** methods are logged. The other sqlite3_vfs object methods (xDlXXX,
** xRandomness, xSleep, xCurrentTime, xGetLastError and xCurrentTimeInt64)
** are not logged.
*/
#include "sqlite3.h"
#include <string.h>
#include <assert.h>
#include <stdio.h>
#if SQLITE_OS_UNIX
# include <unistd.h>
#endif
/*
** Forward declaration of objects used by this utility
*/
typedef struct VLogLog VLogLog;
typedef struct VLogVfs VLogVfs;
typedef struct VLogFile VLogFile;
/* There is a pair (an array of size 2) of the following objects for
** each database file being logged. The first contains the filename
** and is used to log I/O with the main database. The second has
** a NULL filename and is used to log I/O for the journal. Both
** out pointers are the same.
*/
struct VLogLog {
VLogLog *pNext; /* Next in a list of all active logs */
VLogLog **ppPrev; /* Pointer to this in the list */
int nRef; /* Number of references to this object */
int nFilename; /* Length of zFilename in bytes */
char *zFilename; /* Name of database file. NULL for journal */
FILE *out; /* Write information here */
};
struct VLogVfs {
sqlite3_vfs base; /* VFS methods */
sqlite3_vfs *pVfs; /* Parent VFS */
};
struct VLogFile {
sqlite3_file base; /* IO methods */
sqlite3_file *pReal; /* Underlying file handle */
VLogLog *pLog; /* The log file for this file */
};
#define REALVFS(p) (((VLogVfs*)(p))->pVfs)
/*
** Methods for VLogFile
*/
static int vlogClose(sqlite3_file*);
static int vlogRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
static int vlogWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
static int vlogTruncate(sqlite3_file*, sqlite3_int64 size);
static int vlogSync(sqlite3_file*, int flags);
static int vlogFileSize(sqlite3_file*, sqlite3_int64 *pSize);
static int vlogLock(sqlite3_file*, int);
static int vlogUnlock(sqlite3_file*, int);
static int vlogCheckReservedLock(sqlite3_file*, int *pResOut);
static int vlogFileControl(sqlite3_file*, int op, void *pArg);
static int vlogSectorSize(sqlite3_file*);
static int vlogDeviceCharacteristics(sqlite3_file*);
/*
** Methods for VLogVfs
*/
static int vlogOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
static int vlogDelete(sqlite3_vfs*, const char *zName, int syncDir);
static int vlogAccess(sqlite3_vfs*, const char *zName, int flags, int *);
static int vlogFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
static void *vlogDlOpen(sqlite3_vfs*, const char *zFilename);
static void vlogDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
static void vlogDlClose(sqlite3_vfs*, void*);
static int vlogRandomness(sqlite3_vfs*, int nByte, char *zOut);
static int vlogSleep(sqlite3_vfs*, int microseconds);
static int vlogCurrentTime(sqlite3_vfs*, double*);
static int vlogGetLastError(sqlite3_vfs*, int, char *);
static int vlogCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
static VLogVfs vlog_vfs = {
{
1, /* iVersion */
0, /* szOsFile (set by register_vlog()) */
1024, /* mxPathname */
0, /* pNext */
"vfslog", /* zName */
0, /* pAppData */
vlogOpen, /* xOpen */
vlogDelete, /* xDelete */
vlogAccess, /* xAccess */
vlogFullPathname, /* xFullPathname */
vlogDlOpen, /* xDlOpen */
vlogDlError, /* xDlError */
vlogDlSym, /* xDlSym */
vlogDlClose, /* xDlClose */
vlogRandomness, /* xRandomness */
vlogSleep, /* xSleep */
vlogCurrentTime, /* xCurrentTime */
vlogGetLastError, /* xGetLastError */
vlogCurrentTimeInt64 /* xCurrentTimeInt64 */
},
0
};
static sqlite3_io_methods vlog_io_methods = {
1, /* iVersion */
vlogClose, /* xClose */
vlogRead, /* xRead */
vlogWrite, /* xWrite */
vlogTruncate, /* xTruncate */
vlogSync, /* xSync */
vlogFileSize, /* xFileSize */
vlogLock, /* xLock */
vlogUnlock, /* xUnlock */
vlogCheckReservedLock, /* xCheckReservedLock */
vlogFileControl, /* xFileControl */
vlogSectorSize, /* xSectorSize */
vlogDeviceCharacteristics, /* xDeviceCharacteristics */
0, /* xShmMap */
0, /* xShmLock */
0, /* xShmBarrier */
0 /* xShmUnmap */
};
#if SQLITE_OS_UNIX && !defined(NO_GETTOD)
#include <sys/time.h>
static sqlite3_uint64 vlog_time(){
struct timeval sTime;
gettimeofday(&sTime, 0);
return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
}
#elif SQLITE_OS_WIN
#include <windows.h>
#include <time.h>
static sqlite3_uint64 vlog_time(){
FILETIME ft;
sqlite3_uint64 u64time = 0;
GetSystemTimeAsFileTime(&ft);
u64time |= ft.dwHighDateTime;
u64time <<= 32;
u64time |= ft.dwLowDateTime;
/* ft is 100-nanosecond intervals, we want microseconds */
return u64time /(sqlite3_uint64)10;
}
#else
static sqlite3_uint64 vlog_time(){
return 0;
}
#endif
/*
** Write a message to the log file
*/
static void vlogLogPrint(
VLogLog *pLog, /* The log file to write into */
sqlite3_int64 tStart, /* Start time of system call */
sqlite3_int64 tElapse, /* Elapse time of system call */
const char *zOp, /* Type of system call */
sqlite3_int64 iArg1, /* First argument */
sqlite3_int64 iArg2, /* Second argument */
const char *zArg3, /* Third argument */
int iRes /* Result */
){
char z1[40], z2[40], z3[70];
if( pLog==0 ) return;
if( iArg1>=0 ){
sqlite3_snprintf(sizeof(z1), z1, "%lld", iArg1);
}else{
z1[0] = 0;
}
if( iArg2>=0 ){
sqlite3_snprintf(sizeof(z2), z2, "%lld", iArg2);
}else{
z2[0] = 0;
}
if( zArg3 ){
sqlite3_snprintf(sizeof(z3), z3, "\"%s\"", zArg3);
}else{
z3[0] = 0;
}
fprintf(pLog->out,"%lld,%lld,%s,%d,%s,%s,%s,%d\n",
tStart, tElapse, zOp, pLog->zFilename==0, z1, z2, z3, iRes);
}
/*
** List of all active log connections. Protected by the master mutex.
*/
static VLogLog *allLogs = 0;
/*
** Close a VLogLog object
*/
static void vlogLogClose(VLogLog *p){
if( p ){
sqlite3_mutex *pMutex;
p->nRef--;
if( p->nRef>0 || p->zFilename==0 ) return;
pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMutex);
*p->ppPrev = p->pNext;
if( p->pNext ) p->pNext->ppPrev = p->ppPrev;
sqlite3_mutex_leave(pMutex);
fclose(p->out);
sqlite3_free(p);
}
}
/*
** Open a VLogLog object on the given file
*/
static VLogLog *vlogLogOpen(const char *zFilename){
int nName = (int)strlen(zFilename);
int isJournal = 0;
sqlite3_mutex *pMutex;
VLogLog *pLog, *pTemp;
sqlite3_int64 tNow = 0;
if( nName>4 && strcmp(zFilename+nName-4,"-wal")==0 ){
return 0; /* Do not log wal files */
}else
if( nName>8 && strcmp(zFilename+nName-8,"-journal")==0 ){
nName -= 8;
isJournal = 1;
}else if( nName>12
&& sqlite3_strglob("-mj??????9??", zFilename+nName-12)==0 ){
return 0; /* Do not log master journal files */
}
pTemp = sqlite3_malloc( sizeof(*pLog)*2 + nName + 60 );
if( pTemp==0 ) return 0;
pMutex = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
sqlite3_mutex_enter(pMutex);
for(pLog=allLogs; pLog; pLog=pLog->pNext){
if( pLog->nFilename==nName && !memcmp(pLog->zFilename, zFilename, nName) ){
break;
}
}
if( pLog==0 ){
pLog = pTemp;
pTemp = 0;
memset(pLog, 0, sizeof(*pLog)*2);
pLog->zFilename = (char*)&pLog[2];
tNow = vlog_time();
sqlite3_snprintf(nName+60, pLog->zFilename, "%.*s-debuglog-%lld",
nName, zFilename, tNow);
pLog->out = fopen(pLog->zFilename, "a");
if( pLog->out==0 ){
sqlite3_mutex_leave(pMutex);
sqlite3_free(pLog);
return 0;
}
pLog->nFilename = nName;
pLog[1].out = pLog[0].out;
pLog->ppPrev = &allLogs;
if( allLogs ) allLogs->ppPrev = &pLog->pNext;
pLog->pNext = allLogs;
allLogs = pLog;
}
sqlite3_mutex_leave(pMutex);
if( pTemp ){
sqlite3_free(pTemp);
}else{
#if SQLITE_OS_UNIX
char zHost[200];
zHost[0] = 0;
gethostname(zHost, sizeof(zHost)-1);
zHost[sizeof(zHost)-1] = 0;
vlogLogPrint(pLog, tNow, 0, "IDENT", getpid(), -1, zHost, 0);
#endif
}
if( pLog && isJournal ) pLog++;
pLog->nRef++;
return pLog;
}
/*
** Close an vlog-file.
*/
static int vlogClose(sqlite3_file *pFile){
sqlite3_uint64 tStart, tElapse;
int rc = SQLITE_OK;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
if( p->pReal->pMethods ){
rc = p->pReal->pMethods->xClose(p->pReal);
}
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "CLOSE", -1, -1, 0, rc);
vlogLogClose(p->pLog);
return rc;
}
/*
** Compute signature for a block of content.
**
** For blocks of 16 or fewer bytes, the signature is just a hex dump of
** the entire block.
**
** For blocks of more than 16 bytes, the signature is a hex dump of the
** first 8 bytes followed by a 64-bit has of the entire block.
*/
static void vlogSignature(unsigned char *p, int n, char *zCksum){
unsigned int s0 = 0, s1 = 0;
unsigned int *pI;
int i;
if( n<=16 ){
for(i=0; i<n; i++) sqlite3_snprintf(3, zCksum+i*2, "%02x", p[i]);
}else{
pI = (unsigned int*)p;
for(i=0; i<n-7; i+=8){
s0 += pI[0] + s1;
s1 += pI[1] + s0;
pI += 2;
}
for(i=0; i<8; i++) sqlite3_snprintf(3, zCksum+i*2, "%02x", p[i]);
sqlite3_snprintf(18, zCksum+i*2, "-%08x%08x", s0, s1);
}
}
/*
** Read data from an vlog-file.
*/
static int vlogRead(
sqlite3_file *pFile,
void *zBuf,
int iAmt,
sqlite_int64 iOfst
){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
char zSig[40];
tStart = vlog_time();
rc = p->pReal->pMethods->xRead(p->pReal, zBuf, iAmt, iOfst);
tElapse = vlog_time() - tStart;
if( rc==SQLITE_OK ){
vlogSignature(zBuf, iAmt, zSig);
}else{
zSig[0] = 0;
}
vlogLogPrint(p->pLog, tStart, tElapse, "READ", iAmt, iOfst, zSig, rc);
if( rc==SQLITE_OK
&& p->pLog
&& p->pLog->zFilename
&& iOfst<=24
&& iOfst+iAmt>=28
){
unsigned char *x = ((unsigned char*)zBuf)+(24-iOfst);
unsigned iCtr;
iCtr = (x[0]<<24) + (x[1]<<16) + (x[2]<<8) + x[3];
vlogLogPrint(p->pLog, tStart, 0, "CHNGCTR-READ", iCtr, -1, 0, 0);
}
return rc;
}
/*
** Write data to an vlog-file.
*/
static int vlogWrite(
sqlite3_file *pFile,
const void *z,
int iAmt,
sqlite_int64 iOfst
){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
char zSig[40];
tStart = vlog_time();
vlogSignature((unsigned char*)z, iAmt, zSig);
rc = p->pReal->pMethods->xWrite(p->pReal, z, iAmt, iOfst);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "WRITE", iAmt, iOfst, zSig, rc);
if( rc==SQLITE_OK
&& p->pLog
&& p->pLog->zFilename
&& iOfst<=24
&& iOfst+iAmt>=28
){
unsigned char *x = ((unsigned char*)z)+(24-iOfst);
unsigned iCtr;
iCtr = (x[0]<<24) + (x[1]<<16) + (x[2]<<8) + x[3];
vlogLogPrint(p->pLog, tStart, 0, "CHNGCTR-WRITE", iCtr, -1, 0, 0);
}
return rc;
}
/*
** Truncate an vlog-file.
*/
static int vlogTruncate(sqlite3_file *pFile, sqlite_int64 size){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xTruncate(p->pReal, size);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "TRUNCATE", size, -1, 0, rc);
return rc;
}
/*
** Sync an vlog-file.
*/
static int vlogSync(sqlite3_file *pFile, int flags){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xSync(p->pReal, flags);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "SYNC", flags, -1, 0, rc);
return rc;
}
/*
** Return the current file-size of an vlog-file.
*/
static int vlogFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xFileSize(p->pReal, pSize);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "FILESIZE", *pSize, -1, 0, rc);
return rc;
}
/*
** Lock an vlog-file.
*/
static int vlogLock(sqlite3_file *pFile, int eLock){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xLock(p->pReal, eLock);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "LOCK", eLock, -1, 0, rc);
return rc;
}
/*
** Unlock an vlog-file.
*/
static int vlogUnlock(sqlite3_file *pFile, int eLock){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xUnlock(p->pReal, eLock);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "UNLOCK", eLock, -1, 0, rc);
return rc;
}
/*
** Check if another file-handle holds a RESERVED lock on an vlog-file.
*/
static int vlogCheckReservedLock(sqlite3_file *pFile, int *pResOut){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xCheckReservedLock(p->pReal, pResOut);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "CHECKRESERVEDLOCK",
*pResOut, -1, "", rc);
return rc;
}
/*
** File control method. For custom operations on an vlog-file.
*/
static int vlogFileControl(sqlite3_file *pFile, int op, void *pArg){
VLogFile *p = (VLogFile *)pFile;
sqlite3_uint64 tStart, tElapse;
int rc;
tStart = vlog_time();
rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg);
if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){
*(char**)pArg = sqlite3_mprintf("vlog/%z", *(char**)pArg);
}
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "FILECONTROL", op, -1, 0, rc);
return rc;
}
/*
** Return the sector-size in bytes for an vlog-file.
*/
static int vlogSectorSize(sqlite3_file *pFile){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xSectorSize(p->pReal);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "SECTORSIZE", -1, -1, 0, rc);
return rc;
}
/*
** Return the device characteristic flags supported by an vlog-file.
*/
static int vlogDeviceCharacteristics(sqlite3_file *pFile){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogFile *p = (VLogFile *)pFile;
tStart = vlog_time();
rc = p->pReal->pMethods->xDeviceCharacteristics(p->pReal);
tElapse = vlog_time() - tStart;
vlogLogPrint(p->pLog, tStart, tElapse, "DEVCHAR", -1, -1, 0, rc);
return rc;
}
/*
** Open an vlog file handle.
*/
static int vlogOpen(
sqlite3_vfs *pVfs,
const char *zName,
sqlite3_file *pFile,
int flags,
int *pOutFlags
){
int rc;
sqlite3_uint64 tStart, tElapse;
sqlite3_int64 iArg2;
VLogFile *p = (VLogFile*)pFile;
p->pReal = (sqlite3_file*)&p[1];
if( (flags & (SQLITE_OPEN_MAIN_DB|SQLITE_OPEN_MAIN_JOURNAL))!=0 ){
p->pLog = vlogLogOpen(zName);
}else{
p->pLog = 0;
}
tStart = vlog_time();
rc = REALVFS(pVfs)->xOpen(REALVFS(pVfs), zName, p->pReal, flags, pOutFlags);
tElapse = vlog_time() - tStart;
iArg2 = pOutFlags ? *pOutFlags : -1;
vlogLogPrint(p->pLog, tStart, tElapse, "OPEN", flags, iArg2, 0, rc);
if( rc==SQLITE_OK ){
pFile->pMethods = &vlog_io_methods;
}else{
if( p->pLog ) vlogLogClose(p->pLog);
p->pLog = 0;
}
return rc;
}
/*
** Delete the file located at zPath. If the dirSync argument is true,
** ensure the file-system modifications are synced to disk before
** returning.
*/
static int vlogDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogLog *pLog;
tStart = vlog_time();
rc = REALVFS(pVfs)->xDelete(REALVFS(pVfs), zPath, dirSync);
tElapse = vlog_time() - tStart;
pLog = vlogLogOpen(zPath);
vlogLogPrint(pLog, tStart, tElapse, "DELETE", dirSync, -1, 0, rc);
vlogLogClose(pLog);
return rc;
}
/*
** Test for access permissions. Return true if the requested permission
** is available, or false otherwise.
*/
static int vlogAccess(
sqlite3_vfs *pVfs,
const char *zPath,
int flags,
int *pResOut
){
int rc;
sqlite3_uint64 tStart, tElapse;
VLogLog *pLog;
tStart = vlog_time();
rc = REALVFS(pVfs)->xAccess(REALVFS(pVfs), zPath, flags, pResOut);
tElapse = vlog_time() - tStart;
pLog = vlogLogOpen(zPath);
vlogLogPrint(pLog, tStart, tElapse, "ACCESS", flags, *pResOut, 0, rc);
vlogLogClose(pLog);
return rc;
}
/*
** Populate buffer zOut with the full canonical pathname corresponding
** to the pathname in zPath. zOut is guaranteed to point to a buffer
** of at least (INST_MAX_PATHNAME+1) bytes.
*/
static int vlogFullPathname(
sqlite3_vfs *pVfs,
const char *zPath,
int nOut,
char *zOut
){
return REALVFS(pVfs)->xFullPathname(REALVFS(pVfs), zPath, nOut, zOut);
}
/*
** Open the dynamic library located at zPath and return a handle.
*/
static void *vlogDlOpen(sqlite3_vfs *pVfs, const char *zPath){
return REALVFS(pVfs)->xDlOpen(REALVFS(pVfs), zPath);
}
/*
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
** utf-8 string describing the most recent error encountered associated
** with dynamic libraries.
*/
static void vlogDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
REALVFS(pVfs)->xDlError(REALVFS(pVfs), nByte, zErrMsg);
}
/*
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
*/
static void (*vlogDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
return REALVFS(pVfs)->xDlSym(REALVFS(pVfs), p, zSym);
}
/*
** Close the dynamic library handle pHandle.
*/
static void vlogDlClose(sqlite3_vfs *pVfs, void *pHandle){
REALVFS(pVfs)->xDlClose(REALVFS(pVfs), pHandle);
}
/*
** Populate the buffer pointed to by zBufOut with nByte bytes of
** random data.
*/
static int vlogRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
return REALVFS(pVfs)->xRandomness(REALVFS(pVfs), nByte, zBufOut);
}
/*
** Sleep for nMicro microseconds. Return the number of microseconds
** actually slept.
*/
static int vlogSleep(sqlite3_vfs *pVfs, int nMicro){
return REALVFS(pVfs)->xSleep(REALVFS(pVfs), nMicro);
}
/*
** Return the current time as a Julian Day number in *pTimeOut.
*/
static int vlogCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
return REALVFS(pVfs)->xCurrentTime(REALVFS(pVfs), pTimeOut);
}
static int vlogGetLastError(sqlite3_vfs *pVfs, int a, char *b){
return REALVFS(pVfs)->xGetLastError(REALVFS(pVfs), a, b);
}
static int vlogCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
return REALVFS(pVfs)->xCurrentTimeInt64(REALVFS(pVfs), p);
}
/*
** Register debugvfs as the default VFS for this process.
*/
int sqlite3_register_vfslog(const char *zArg){
vlog_vfs.pVfs = sqlite3_vfs_find(0);
vlog_vfs.base.szOsFile = sizeof(VLogFile) + vlog_vfs.pVfs->szOsFile;
return sqlite3_vfs_register(&vlog_vfs.base, 1);
}
+1
View File
@@ -26,4 +26,5 @@
>68 belong =0x42654c6e Bentley Systems Localization File -
>60 belong =0x5f4d544e Monotone source repository -
>68 belong =0x47504b47 OGC GeoPackage file -
>68 belong =0x47503130 OGC GeoPackage version 1.0 file -
>0 string =SQLite SQLite3 database
+9 -2
View File
@@ -279,7 +279,9 @@ TESTSRC += \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/wholenumber.c
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/wholenumber.c \
$(TOP)/ext/misc/vfslog.c
#TESTSRC += $(TOP)/ext/fts2/fts2_tokenizer.c
@@ -618,6 +620,10 @@ $(TEST_EXTENSION): $(TOP)/src/test_loadext.c
extensiontest: testfixture$(EXE) $(TEST_EXTENSION)
./testfixture$(EXE) $(TOP)/test/loadext.test
showdb: $(TOP)/tool/showdb.c sqlite3.c
$(TCC) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION -o showdb \
$(TOP)/tool/showdb.c sqlite3.c
# This target will fail if the SQLite amalgamation contains any exported
# symbols that do not begin with "sqlite3_". It is run as part of the
# releasetest.tcl script.
@@ -651,9 +657,10 @@ clean:
rm -f fts3-testfixture fts3-testfixture.exe
rm -f testfixture testfixture.exe
rm -f threadtest3 threadtest3.exe
rm -f sqlite3.c fts?amal.c tclsqlite3.c
rm -f sqlite3.c sqlite3-*.c fts?amal.c tclsqlite3.c
rm -f sqlite3rc.h
rm -f shell.c sqlite3ext.h
rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c
rm -f sqlite-*-output.vsix
rm -f mptester mptester.exe
rm -f showdb
+59 -54
View File
@@ -1,9 +1,9 @@
C Try\sto\sremember\sstatistics\sfrom\sANALYZE\susing\sLogEst\sinstead\sof\su64.
D 2013-10-07T16:53:50.515
C Fix\smemory/resource\sleaks\sfor\sWinCE\sand\sCygwin.
D 2013-10-16T09:49:10.719
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5e41da95d92656a5004b03d3576e8b226858a28e
F Makefile.in 0522b53cdc1fcfc18f3a98e0246add129136c654
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 9af063716f726a73b5d5c98c69ea97eca6a9369b
F Makefile.msc ec5d662ed5a15ff819928c0495017af13910d7b6
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
F README cd04a36fbc7ea56932a4052d7d0b7f09f27c33d6
F VERSION a8d1f6839521130dc73c5408cdd24bcfd791df34
@@ -78,10 +78,10 @@ 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 6d277a3ff6b20ff815184395407c5a4bd7787f9c
F ext/fts3/fts3.c f25ae5729d40cc4e661c0a552685038f27e72bc9
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 8689f7cf85020e7f88d1e761eeac480c3b0ea7ad
F ext/fts3/fts3_aux.c b02632f6dd0e375ce97870206d914ea6d8df5ccd
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c f8eb1046063ba342c7114eba175cabb31c4a64e7
F ext/fts3/fts3_hash.c 8dd2d06b66c72c628c2732555a32bc0943114914
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
@@ -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 851e65f413576055f2e86a63d45b7d67c829db56
F ext/fts3/fts3_write.c 17817f0cb6c8555e1be5e073fbddf676c60f4ea9
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
@@ -115,6 +115,8 @@ F ext/misc/percentile.c bcbee3c061b884eccb80e21651daaae8e1e43c63
F ext/misc/regexp.c af92cdaa5058fcec1451e49becc7ba44dba023dc
F ext/misc/rot13.c 1ac6f95f99b575907b9b09c81a349114cf9be45a
F ext/misc/spellfix.c 5e1d547e9a2aed13897fa91bac924333f62fd2d9
F ext/misc/totype.c 4a167594e791abeed95e0a8db028822b5e8fe512
F ext/misc/vfslog.c 1abb192d8d4bd323adbddec0c024580496b51b7a
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
@@ -138,8 +140,8 @@ F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt f2b23a6bde8f1c6e86b957e4d94eab0add520b0d
F main.mk a10f1925ae3bb545a045d1f1867506f49bee972f
F magic.txt 814d3de5ec227817ff2ad26cbc73159c968a2a58
F main.mk c6a433cb334bbb019625c137ab5d5e7568b47cff
F mkdll.sh 7d09b23c05d56532e9d44a50868eb4b12ff4f74a
F mkextu.sh 416f9b7089d80e5590a29692c9d9280a10dbad9f
F mkextw.sh d2a981497b404d6498f5ff3e3b1f3816bdfcb338
@@ -157,7 +159,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/analyze.c 3994309c21b7324217cd32225b7abb5cb1bd1946
F src/analyze.c f1c5ed1fe128c3f106dcd95e97ee9ef94db7a3fa
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
@@ -166,15 +168,15 @@ F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c d5720cbb21ae56e7e5b07847e05e5b203818acac
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
F src/build.c 46bb89df0a204eb7154874f966f11d16a7fbced7
F src/build.c 8ae900bf021a66ac110f5eb2dcf994d24d1c2061
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 65196e95e69f36993659bd7781abe7c2f1994739
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c 45788c5e48734f2af4acd75a876466e5b9838e34
F src/expr.c e7338ccffdc391c53ba2d51c5eb6a2f5299e040e
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c be866cd8c4fa6cae98ba33109578fd1a3311ee5b
F src/fkey.c 5dc10cbaa355753903cd2a64da040f948997ebf8
F src/func.c 2c47b65e6e00e3e9374942f28254faf8adafe398
F src/global.c 5caf4deab621abb45b4c607aad1bd21c20aac759
F src/hash.c ac3470bbf1ca4ae4e306a8ecb0fdf1731810ffe4
@@ -203,36 +205,36 @@ F src/os.c b4ad71336fd96f97776f75587cd9e8218288f5be
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_unix.c 243fb37f47dc072fc59839ea241ff0a17c8d76e6
F src/os_win.c b8f54f42d9c232c48cb694b7dbe94e601c816b5c
F src/os_win.c c812a3c37e113423f1579aba876acc240189d5d6
F src/pager.c 2aa4444ffe86e9282d03bc349a4a5e49bd77c0e8
F src/pager.h f094af9f6ececfaa8a1e93876905a4f34233fb0c
F src/parse.y a97566d6da75075589a7c716d1bda14b586cf8da
F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
F src/pragma.c f4ff6e29c316d06bf7dffca0c8cee7c229cae42e
F src/pragma.c 64d3d1f8b4ed144ba85c061d00d96d6be8aa2fea
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c 7459801d02997b07e8b8da85ef255392ba1d022b
F src/resolve.c 5f15b00644c36a1610b87857abf42db38c07519c
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 19611e6da6646a1090164b29d6b23b7c8e7364ea
F src/shell.c 5ee50ca3e35453bbd6ccdf1bdd0f6bbe9738e9fb
F src/sqlite.h.in ec40aa958a270416fb04b4f72210357bf163d2c5
F src/select.c 15127b54cc11defb2cddef6914e1f384501a61c4
F src/shell.c 6f11f0e9ded63d48e306f2c6858c521e568a47bb
F src/sqlite.h.in 4c6eb96fded1d56a27cec04b6b6803789eb28f54
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h a5fa87b540662fb552ba81c0d4eeb368aebb5af7
F src/sqliteInt.h 4dd81a25a919509ce94b1f8f120bbef14458d4b9
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c 3b5f3716e320480659239abe887164521c575d83
F src/test1.c 26226cfd2b6dc3f77d2eb27f07ffcf236b4e728b
F src/test1.c 5757066e503a8ed51313cb3a5d9bcdcced2991a9
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c a6d1ac55ac054d0b2b8f37b5e655b6c92645a013
F src/test6.c a437f76f9874d2563352a7e6cd0d43217663c220
F src/test7.c 126b886b53f0358b92aba9b81d3fcbfbe9a93cd6
F src/test6.c 00af0fe1947305222b8ed488a69c76c5a2b632e2
F src/test7.c 72b732baa5642f795655ba1126ea032af46ecfd2
F src/test8.c c7aab1d9fbbf54fc33d43b73aa24aa55f9eaf534
F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
@@ -261,7 +263,7 @@ F src/test_quota.c 30c64f0ef84734f2231a686df41ed882b0c59bc0
F src/test_quota.h 8761e463b25e75ebc078bd67d70e39b9c817a0cb
F src/test_rtree.c f3d1d12538dccb75fd916e3fa58f250edbdd3b47
F src/test_schema.c cd12a2223c3a394f4d07bb93bdf6d344c5c121b6
F src/test_server.c 2f99eb2837dfa06a4aacf24af24c6affdf66a84f
F src/test_server.c a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
F src/test_stat.c d1569c7a4839f13e80187e2c26b2ab4da2d03935
F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
@@ -275,7 +277,7 @@ F src/tokenize.c 70061085a51f2f4fc15ece94f32c03bcb78e63b2
F src/trigger.c ba0a883cd536b7dfdd4df3733001f5372a4299da
F src/update.c f5182157f5d0d0a97bc5f5e3c9bdba0dfbe08f08
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 2f0c9b1f884d038eb90f48cf17042a88dc1629d3
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
F src/vacuum.c f313bc97123a4dd4bfd3f50a00c4d44c08a5b1b7
F src/vdbe.c 56e648f5ba9a91810caf216857adfed9039cd174
F src/vdbe.h 4f554b5627f26710c4c36d919110a3fc611ca5c4
@@ -283,14 +285,14 @@ F src/vdbeInt.h ff57f67aee1ba26a3a47e786533dab155ab6dad6
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
F src/vdbeaux.c 55f4858fe6abd84bd7311acbf30a75a28903ec25
F src/vdbeblob.c 5dc79627775bd9a9b494dd956e26297946417d69
F src/vdbemem.c 817ce21ab4ca57f902619bb8fef3f8a51bbd0ed8
F src/vdbemem.c 649933bad3e922465b726eaf85c72a75acba2ab7
F src/vdbesort.c 3937e06b2a0e354500e17dc206ef4c35770a5017
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
F src/where.c 7916e32a4d7f8cc891a08de09380ef519415d275
F src/where.c dd2d0d69280d6653d8ef8cf3b6b4b848b9058197
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
@@ -319,7 +321,7 @@ F test/async4.test 1787e3952128aa10238bf39945126de7ca23685a
F test/async5.test 383ab533fdb9f7ad228cc99ee66e1acb34cc0dc0
F test/atof1.test 9bf1d25180a2e05fc12ce3940cc8003033642f68
F test/attach.test 0d112b7713611fdf0340260192749737135fda5f
F test/attach2.test e54436ed956d3d88bdee61221da59bf3935a0966
F test/attach2.test 0ec5defa340363de6cd50fd595046465e9aaba2d
F test/attach3.test d89ccfe4fe6e2b5e368d480fcdfe4b496c54cf4e
F test/attach4.test 53bf502f17647c6d6c5add46dda6bac8b6f4665c
F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
@@ -414,7 +416,7 @@ F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F test/createtab.test b5de160630b209c4b8925bdcbbaf48cc90b67fe8
F test/cse.test 277350a26264495e86b1785f34d2d0c8600e021c
F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test 502ddcbaaac9ce103bcd76d8e9d9bc8aa04e61b0
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
F test/dbstatus.test aee30c3f337e6c217ff06df59fb8fe6e6448dce2
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
@@ -437,7 +439,7 @@ F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 291e056e1a442a5e5166a989a8a03a46e38225ca
F test/e_reindex.test e175794fc41f8e8aef34772e87a7d7b7a9251dd3
F test/e_resolve.test dcce9308fb13b934ce29591105d031d3e14fbba6
F test/e_select.test f2358d074bd82240bc79a8348f284a2a8909dc1f
F test/e_select.test d3226cb94fae4af3f198e68e71f655e106d0be47
F test/e_select2.test 22c660a7becf0712c95e1ca1b2d9e716a1261460
F test/e_update.test bea00499e43ee1da77b03cdb0b20c7c864c1ec5a
F test/e_uri.test a2c92d80093a7efdcfbb11093651cbea87097b6b
@@ -461,8 +463,8 @@ F test/fkey1.test e1d1fa84cde579185ea01358436839703e415a5b
F test/fkey2.test 06e0b4cc9e1b3271ae2ae6feeb19755468432111
F test/fkey3.test 5ec899d12b13bcf1e9ef40eff7fb692fdb91392e
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
F test/fkey5.test 0bf64f2d19ad80433ca0b24edbf604a18b353d5f
F test/fkey6.test c555f7fc45d842cc84b0d3ff93951ce2b8c25fc8
F test/fkey5.test 8a1fde4e7721ae00b05b3178888833726ca2df8d
F test/fkey6.test 18e8c024d39f68f8d4bb1177c992bcffdc273464
F test/fkey7.test e31d0e71a41c1d29349a16448d6c420e2c53a8fc
F test/fkey_malloc.test bb74c9cb8f8fceed03b58f8a7ef2df98520bbd51
F test/format4.test 1f0cac8ff3895e9359ed87e41aaabee982a812eb
@@ -521,6 +523,7 @@ F test/fts3ao.test 71b0675e3df5c512a5a03daaa95ee1916de23dda
F test/fts3atoken.test fca30fd86db9241d571c637751e9a8a2f50f1451
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221
F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
@@ -556,18 +559,19 @@ F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4incr.test 2fae04582c2329a038b2b1f985e702478fb94888
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/fts4unicode.test ebd937061e1ce096240d2352feb424587f2187b9
F test/fts4unicode.test e28ba1a14181e709dcdf47455f207adf14c7cfe0
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test cd25cf605c5a345d038dc7b84232204c6a901c84
F test/func.test c7e80a44eebac8604397eb2ad83d0d5d9d541237
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test 001021e5b88bd02a3b365a5c5fd8f6f49d39744a
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
F test/func4.test cb3f888a1cafad195a1f8d396875bdb11dc4faf9
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
@@ -608,7 +612,7 @@ F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 87f6798f31d60c4e177622fcc3663367e6ecbd90
F test/insert5.test 394f96728d1258f406fe5f5aeb0aaf29487c39a6
F test/instr.test a34e1d46a9eefb098a7167ef0e730a4a3d82fba0
F test/instr.test 737bbf80685232033f3abedc6ae92f75860b5dd2
F test/intarray.test 066b7d7ac38d25bf96f87f1b017bfc687551cdd4
F test/interrupt.test dfe9a67a94b0b2d8f70545ba1a6cca10780d71cc
F test/intpkey.test a9674fc6195e0952e4e6105a9981ce1e48e7f215
@@ -723,9 +727,9 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test 72f4f8881d388163ddbbeec0a6ed812e863ea2e6
F test/pragma.test de128f0253ee42a1edf6c80f21813babfb19bd3b
F test/pragma2.test 224f0381f9411a78ae685cac24c13656a62021b7
F test/permutations.test e154f5ed66d4d4913a99a110e870c9407f75b055
F test/pragma.test 5e7de6c32a5d764f09437d2025f07e4917b9e178
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
F test/progress.test a282973d1d17f08071bc58a77d6b80f2a81c354d
F test/ptrchng.test ef1aa72d6cf35a2bbd0869a649b744e9d84977fc
@@ -761,7 +765,7 @@ F test/schema4.test e6a66e20cc69f0e306667c08be7fda3d11707dc5
F test/schema5.test 0103e4c0313b3725b5ae5600bdca53006ab53db3
F test/securedel.test 87a2561151af1f1e349071a89fdd77059f50113c
F test/securedel2.test 2d54c28e46eb1fd6902089958b20b1b056c6f1c5
F test/select1.test deba017eed9daa5af33de868676c997e7eebb931
F test/select1.test fc2a61f226a649393664ad54bc5376631801517c
F test/select2.test 352480e0e9c66eda9c3044e412abdf5be0215b56
F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054
F test/select4.test 00179be44e531fe04c1c3f15df216439dff2519d
@@ -781,7 +785,7 @@ F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test fcd65cb11d189eff5f5c85cc4fad246fb0933108
F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F test/shared7.test 960760bc8d03e1419e70dea69cf41db62853616e
F test/shared7.test a81e99f83e6c51b02ac99c96fb3a2a7b5978c956
F test/shared8.test 00a07bf5e1337ecf72e94542bdefdc330d7a2538
F test/shared9.test 5f2a8f79b4d6c7d107a01ffa1ed05ae7e6333e21
F test/sharedA.test 0cdf1a76dfa00e6beee66af5b534b1e8df2720f5
@@ -1083,22 +1087,23 @@ F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439
F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 323e54ac86fb2393f9950219224e304620d2fb12
F tool/lemon.c 796930d5fc2036c7636f3f1ee12f9ae03719a2eb
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/logest.c 7ad625cac3d54012b27d468b7af6612f78b9ba75
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
F tool/mkkeywordhash.c bb52064aa614e1426445e4b2b9b00eeecd23cc79
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl ceaaeebcd882864caefe4176592ca6fa4648fab1
F tool/mkpragmatab.tcl 3fc52e00a234750675e8a569d2919ff48558e9eb
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 8bce31074e4cbe631bb7676526a048335f4c9f02
F tool/mksqlite3c.tcl d344cc3144a0271cd853c5e3df36e9f31d78d619
F tool/mksqlite3c.tcl d8dc444d403019167260e5578f5c362741f03696
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
F tool/mkvsix.tcl f3312df26fd9938a27fa0a845ec96bea84b0c16b
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 4665982e95a6e5c1bd806cf7bc3dea95be422d77
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
F tool/pagesig.c ff0ca355fd3c2398e933da5e22439bbff89b803b
F tool/restore_jrnl.tcl 6957a34f8f1f0f8285e07536225ec3b292a9024a
F tool/rollback-test.c 9fc98427d1e23e84429d7e6d07d9094fbdec65a5
F tool/showdb.c 525ecc443578647703051308ad50a93de6ba2c4b
@@ -1119,12 +1124,12 @@ F tool/symbols.sh fec58532668296d7c7dc48be9c87f75ccdb5814f
F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 1d7b2dc0eae70c0c0e523b715acf758bb4cfa9ac
R faf619696f929769ec0cefbeba9e27c2
T *branch * log-stats
T *sym-log-stats *
T -sym-row-size-est *
U drh
Z 72baf94bdfc7ce8839761e1732e0e2d4
P 891df358e51075fb937f34952ce43bf51130b0d0
R 220c145b0b7752ec81af9a6d3dc55290
T *branch * wince-fixes
T *sym-wince-fixes *
T -sym-trunk *
U mistachkin
Z cf86f3f77bb8f85bf54a57b7b4d91994
+1 -1
View File
@@ -1 +1 @@
8e78557a40a6b97009852f5b72e68d6483fb00fc
2470d1bb08b2661bcfde7a605208eb6044836d5c
+47 -30
View File
@@ -31,7 +31,7 @@
** SQLITE_ENABLE_STAT3 defined. The functionality of sqlite_stat3
** is a superset of sqlite_stat2. The sqlite_stat4 is an enhanced
** version of sqlite_stat3 and is only available when compiled with
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.0 and later. It is
** SQLITE_ENABLE_STAT4 and in SQLite versions 3.8.1 and later. It is
** not possible to enable both STAT3 and STAT4 at the same time. If they
** are both enabled, then STAT4 takes precedence.
**
@@ -107,12 +107,12 @@
** The idx column names the index and the tbl column is the table of the
** index. If the idx and tbl columns are the same, then the sample is
** of the INTEGER PRIMARY KEY. The sample column is a blob which is the
** binary encoding of a key from the index, with the trailing rowid
** omitted. The nEq column is a list of integers. The first integer
** is the approximate number of entries in the index whose left-most
** column exactly matches the left-most column of the sample. The second
** integer in nEq is the approximate number of entries in the index where
** the first two columns match the first two columns of the sample.
** binary encoding of a key from the index. The nEq column is a
** list of integers. The first integer is the approximate number
** of entries in the index whose left-most column exactly matches
** the left-most column of the sample. The second integer in nEq
** is the approximate number of entries in the index where the
** first two columns match the first two columns of the sample.
** And so forth. nLt is another list of integers that show the approximate
** number of entries that are strictly less than the sample. The first
** integer in nLt contains the number of entries in the index where the
@@ -444,7 +444,7 @@ static int sampleIsBetter(
/*
** Copy the contents of object (*pFrom) into (*pTo).
*/
void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
static void sampleCopy(Stat4Accum *p, Stat4Sample *pTo, Stat4Sample *pFrom){
pTo->iRowid = pFrom->iRowid;
pTo->isPSample = pFrom->isPSample;
pTo->iCol = pFrom->iCol;
@@ -589,6 +589,11 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
}
}
#endif
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
UNUSED_PARAMETER( p );
UNUSED_PARAMETER( iChng );
#endif
}
/*
@@ -614,6 +619,8 @@ static void statPush(
Stat4Accum *p = (Stat4Accum*)sqlite3_value_blob(argv[0]);
int iChng = sqlite3_value_int(argv[1]);
UNUSED_PARAMETER( argc );
UNUSED_PARAMETER( context );
assert( p->nCol>1 ); /* Includes rowid field */
assert( iChng<p->nCol );
@@ -743,12 +750,12 @@ static void statGet(
return;
}
sqlite3_snprintf(24, zRet, "%lld", p->nRow);
sqlite3_snprintf(24, zRet, "%llu", (u64)p->nRow);
z = zRet + sqlite3Strlen30(zRet);
for(i=0; i<(p->nCol-1); i++){
i64 nDistinct = p->current.anDLt[i] + 1;
i64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
sqlite3_snprintf(24, z, " %lld", iVal);
u64 nDistinct = p->current.anDLt[i] + 1;
u64 iVal = (p->nRow + nDistinct - 1) / nDistinct;
sqlite3_snprintf(24, z, " %llu", iVal);
z += sqlite3Strlen30(z);
assert( p->current.anEq[i] );
}
@@ -789,7 +796,7 @@ static void statGet(
int i;
char *z = zRet;
for(i=0; i<p->nCol; i++){
sqlite3_snprintf(24, z, "%lld ", aCnt[i]);
sqlite3_snprintf(24, z, "%llu ", (u64)aCnt[i]);
z += sqlite3Strlen30(z);
}
assert( z[0]=='\0' && z>zRet );
@@ -799,6 +806,9 @@ static void statGet(
}
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER( argc );
#endif
}
static const FuncDef statGetFuncdef = {
1+IsStat34, /* nArg */
@@ -817,8 +827,10 @@ static void callStatGet(Vdbe *v, int regStat4, int iParam, int regOut){
assert( regOut!=regStat4 && regOut!=regStat4+1 );
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
sqlite3VdbeAddOp2(v, OP_Integer, iParam, regStat4+1);
#else
#elif SQLITE_DEBUG
assert( iParam==STAT_GET_STAT1 );
#else
UNUSED_PARAMETER( iParam );
#endif
sqlite3VdbeAddOp3(v, OP_Function, 0, regStat4, regOut);
sqlite3VdbeChangeP4(v, -1, (char*)&statGetFuncdef, P4_FUNCDEF);
@@ -1252,13 +1264,13 @@ struct analysisInfo {
static void decodeIntArray(
char *zIntArray, /* String containing int array to decode */
int nOut, /* Number of slots in aOut[] */
LogEst *aOut, /* Convert values to 10*log2() and store here */
tRowcnt *aOut, /* Store integers here */
Index *pIndex /* Handle extra flags for this index, if not NULL */
){
char *z = zIntArray;
int c;
int i;
u64 v;
tRowcnt v;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( z==0 ) z = "";
@@ -1271,10 +1283,15 @@ static void decodeIntArray(
v = v*10 + c - '0';
z++;
}
aOut[i] = sqlite3LogEst(v);
aOut[i] = v;
if( *z==' ' ) z++;
}
if( pIndex ){
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
assert( pIndex!=0 );
#else
if( pIndex )
#endif
{
if( strcmp(z, "unordered")==0 ){
pIndex->bUnordered = 1;
}else if( sqlite3_strglob("sz=[0-9]*", z)==0 ){
@@ -1368,10 +1385,10 @@ static void initAvgEq(Index *pIdx){
int iCol;
for(iCol=0; iCol<pIdx->nColumn; iCol++){
int i; /* Used to iterate through samples */
u64 sumEq = 0; /* Sum of the nEq values */
u64 nSum = 0; /* Number of terms contributing to sumEq */
u64 avgEq = 0;
u64 nDLt = sqlite3LogEstToInt(pFinal->anDLt[iCol]);
tRowcnt sumEq = 0; /* Sum of the nEq values */
tRowcnt nSum = 0; /* Number of terms contributing to sumEq */
tRowcnt avgEq = 0;
tRowcnt nDLt = pFinal->anDLt[iCol];
/* Set nSum to the number of distinct (iCol+1) field prefixes that
** occur in the stat4 table for this index before pFinal. Set
@@ -1380,15 +1397,15 @@ static void initAvgEq(Index *pIdx){
** prefixes). */
for(i=0; i<(pIdx->nSample-1); i++){
if( aSample[i].anDLt[iCol]!=aSample[i+1].anDLt[iCol] ){
sumEq += sqlite3LogEstToInt(aSample[i].anEq[iCol]);
sumEq += aSample[i].anEq[iCol];
nSum++;
}
}
if( nDLt>nSum ){
avgEq = (sqlite3LogEstToInt(pFinal->anLt[iCol]) - sumEq)/(nDLt - nSum);
avgEq = (pFinal->anLt[iCol] - sumEq)/(nDLt - nSum);
}
if( avgEq<=0 ) avgEq = 1;
pIdx->aAvgEq[iCol] = sqlite3LogEst(avgEq);
if( avgEq==0 ) avgEq = 1;
pIdx->aAvgEq[iCol] = avgEq;
if( pIdx->nSampleCol==1 ) break;
}
}
@@ -1438,7 +1455,7 @@ static int loadStatTbl(
int nSample; /* Number of samples */
int nByte; /* Bytes of space required */
int i; /* Bytes of space required */
LogEst *pSpace;
tRowcnt *pSpace;
zIndex = (char *)sqlite3_column_text(pStmt, 0);
if( zIndex==0 ) continue;
@@ -1454,15 +1471,15 @@ static int loadStatTbl(
}
pIdx->nSampleCol = nIdxCol;
nByte = sizeof(IndexSample) * nSample;
nByte += sizeof(LogEst) * nIdxCol * 3 * nSample;
nByte += nAvgCol * sizeof(LogEst); /* Space for Index.aAvgEq[] */
nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample;
nByte += nAvgCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */
pIdx->aSample = sqlite3DbMallocZero(db, nByte);
if( pIdx->aSample==0 ){
sqlite3_finalize(pStmt);
return SQLITE_NOMEM;
}
pSpace = (LogEst*)&pIdx->aSample[nSample];
pSpace = (tRowcnt*)&pIdx->aSample[nSample];
pIdx->aAvgEq = pSpace; pSpace += nAvgCol;
for(i=0; i<nSample; i++){
pIdx->aSample[i].anEq = pSpace; pSpace += nIdxCol;
+11 -12
View File
@@ -879,7 +879,7 @@ void sqlite3StartTable(
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
pTable->nRowEst = 200;
pTable->nRowEst = 1048576;
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -1113,7 +1113,7 @@ char sqlite3AffinityType(const char *zIn, u8 *pszEst){
if( zChar ){
while( zChar[0] ){
if( sqlite3Isdigit(zChar[0]) ){
int v;
int v = 0;
sqlite3GetInt32(zChar, &v);
v = v/4 + 1;
if( v>255 ) v = 255;
@@ -2722,7 +2722,7 @@ Index *sqlite3CreateIndex(
nCol = pList->nExpr;
pIndex = sqlite3DbMallocZero(db,
ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(LogEst)*(nCol+1)) + /* Index.aiRowEst */
ROUND8(sizeof(tRowcnt)*(nCol+1)) + /* Index.aiRowEst */
sizeof(char *)*nCol + /* Index.azColl */
sizeof(int)*nCol + /* Index.aiColumn */
sizeof(u8)*nCol + /* Index.aSortOrder */
@@ -2733,9 +2733,9 @@ Index *sqlite3CreateIndex(
goto exit_create_index;
}
zExtra = (char*)pIndex;
pIndex->aiRowEst = (LogEst*)&zExtra[ROUND8(sizeof(Index))];
pIndex->aiRowEst = (tRowcnt*)&zExtra[ROUND8(sizeof(Index))];
pIndex->azColl = (char**)
((char*)pIndex->aiRowEst + ROUND8(sizeof(LogEst)*nCol+1));
((char*)pIndex->aiRowEst + ROUND8(sizeof(tRowcnt)*nCol+1));
assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
pIndex->aiColumn = (int *)(&pIndex->azColl[nCol]);
@@ -3014,20 +3014,19 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
LogEst *a = pIdx->aiRowEst;
tRowcnt *a = pIdx->aiRowEst;
int i;
LogEst n;
tRowcnt n;
assert( a!=0 );
a[0] = pIdx->pTable->nRowEst;
assert( 33==sqlite3LogEst(10) );
if( a[0]<34 ){ a[0] = 34; }
n = 34;
if( a[0]<10 ) a[0] = 10;
n = 10;
for(i=1; i<=pIdx->nColumn; i++){
a[i] = n;
if( n>24 ) n -= 2;
if( n>5 ) n--;
}
if( pIdx->onError!=OE_None ){
a[pIdx->nColumn] = 0;
a[pIdx->nColumn] = 1;
}
}
+9
View File
@@ -426,6 +426,10 @@ static void clearYMD_HMS_TZ(DateTime *p){
**
** If the sqlite3GlobalConfig.bLocaltimeFault variable is true then this
** routine will always fail.
**
** EVIDENCE-OF: R-62172-00036 In this implementation, the standard C
** library function localtime_r() is used to assist in the calculation of
** local time.
*/
static int osLocaltime(time_t *t, struct tm *pTm){
int rc;
@@ -482,6 +486,11 @@ static sqlite3_int64 localtimeOffset(
x = *p;
computeYMD_HMS(&x);
if( x.Y<1971 || x.Y>=2038 ){
/* EVIDENCE-OF: R-55269-29598 The localtime_r() C function normally only
** works for years between 1970 and 2037. For dates outside this range,
** SQLite attempts to map the year into an equivalent year within this
** range, do the calculation, then map the year back.
*/
x.Y = 2000;
x.M = 1;
x.D = 1;
+13 -6
View File
@@ -656,7 +656,7 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
** when this statement is run. */
FKey *p;
for(p=pTab->pFKey; p; p=p->pNextFrom){
if( p->isDeferred ) break;
if( p->isDeferred || (db->flags & SQLITE_DeferFKs) ) break;
}
if( !p ) return;
iSkip = sqlite3VdbeMakeLabel(v);
@@ -670,11 +670,18 @@ void sqlite3FkDropTable(Parse *pParse, SrcList *pName, Table *pTab){
/* If the DELETE has generated immediate foreign key constraint
** violations, halt the VDBE and return an error at this point, before
** any modifications to the schema are made. This is because statement
** transactions are not able to rollback schema changes. */
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
OE_Abort, "foreign key constraint failed", P4_STATIC
);
** transactions are not able to rollback schema changes.
**
** If the SQLITE_DeferFKs flag is set, then this is not required, as
** the statement transaction will not be rolled back even if FK
** constraints are violated.
*/
if( (db->flags & SQLITE_DeferFKs)==0 ){
sqlite3VdbeAddOp2(v, OP_FkIfZero, 0, sqlite3VdbeCurrentAddr(v)+2);
sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_FOREIGNKEY,
OE_Abort, "foreign key constraint failed", P4_STATIC
);
}
if( iSkip ){
sqlite3VdbeResolveLabel(v, iSkip);
+8 -6
View File
@@ -682,7 +682,7 @@ static struct win_syscall {
#define osGetVersionExA ((BOOL(WINAPI*)( \
LPOSVERSIONINFOA))aSyscall[34].pCurrent)
#if defined(SQLITE_WIN32_HAS_WIDE)
#if !SQLITE_OS_WINRT && defined(SQLITE_WIN32_HAS_WIDE)
{ "GetVersionExW", (SYSCALL)GetVersionExW, 0 },
#else
{ "GetVersionExW", (SYSCALL)0, 0 },
@@ -2196,8 +2196,7 @@ static int winClose(sqlite3_file *id){
OSTRACE(("CLOSE file=%p\n", pFile->h));
#if SQLITE_MAX_MMAP_SIZE>0
rc = winUnmapfile(pFile);
if( rc!=SQLITE_OK ) return rc;
winUnmapfile(pFile);
#endif
do{
@@ -3003,7 +3002,7 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
if( newLimit>=0 && newLimit!=pFile->mmapSizeMax && pFile->nFetchOut==0 ){
pFile->mmapSizeMax = newLimit;
if( pFile->mmapSize>0 ){
(void)winUnmapfile(pFile);
winUnmapfile(pFile);
rc = winMapfile(pFile, -1);
}
}
@@ -4073,6 +4072,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
if( winIsDriveLetterAndColon(zDir) ){
zConverted = winConvertFromUtf8Filename(zDir);
if( !zConverted ){
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
@@ -4085,6 +4085,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
}else{
zConverted = sqlite3MallocZero( nBuf+1 );
if( !zConverted ){
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
@@ -4092,6 +4093,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
osIsNT() ? CCP_POSIX_TO_WIN_W : CCP_POSIX_TO_WIN_A, zDir,
zConverted, nBuf+1)<0 ){
sqlite3_free(zConverted);
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_CONVPATH\n"));
return winLogError(SQLITE_IOERR_CONVPATH, (DWORD)errno,
"winGetTempname1", zDir);
@@ -4105,6 +4107,7 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
char *zUtf8 = winUnicodeToUtf8(zConverted);
if( !zUtf8 ){
sqlite3_free(zConverted);
sqlite3_free(zBuf);
OSTRACE(("TEMP-FILENAME rc=SQLITE_IOERR_NOMEM\n"));
return SQLITE_IOERR_NOMEM;
}
@@ -4120,7 +4123,6 @@ static int winGetTempname(sqlite3_vfs *pVfs, char **pzBuf){
}
sqlite3_free(zConverted);
}
break;
}
}
#elif !SQLITE_OS_WINRT && !defined(__CYGWIN__)
@@ -4490,9 +4492,9 @@ static int winOpen(
#endif
{
sqlite3_free(zConverted);
sqlite3_free(zTmpname);
}
sqlite3_free(zTmpname);
pFile->pMethod = &winIoMethod;
pFile->pVfs = pVfs;
pFile->h = h;
+70 -38
View File
@@ -56,18 +56,19 @@
#define PragTyp_SECURE_DELETE 25
#define PragTyp_SHRINK_MEMORY 26
#define PragTyp_SOFT_HEAP_LIMIT 27
#define PragTyp_SYNCHRONOUS 28
#define PragTyp_TABLE_INFO 29
#define PragTyp_TEMP_STORE 30
#define PragTyp_TEMP_STORE_DIRECTORY 31
#define PragTyp_WAL_AUTOCHECKPOINT 32
#define PragTyp_WAL_CHECKPOINT 33
#define PragTyp_ACTIVATE_EXTENSIONS 34
#define PragTyp_HEXKEY 35
#define PragTyp_KEY 36
#define PragTyp_REKEY 37
#define PragTyp_LOCK_STATUS 38
#define PragTyp_PARSER_TRACE 39
#define PragTyp_STATS 28
#define PragTyp_SYNCHRONOUS 29
#define PragTyp_TABLE_INFO 30
#define PragTyp_TEMP_STORE 31
#define PragTyp_TEMP_STORE_DIRECTORY 32
#define PragTyp_WAL_AUTOCHECKPOINT 33
#define PragTyp_WAL_CHECKPOINT 34
#define PragTyp_ACTIVATE_EXTENSIONS 35
#define PragTyp_HEXKEY 36
#define PragTyp_KEY 37
#define PragTyp_REKEY 38
#define PragTyp_LOCK_STATUS 39
#define PragTyp_PARSER_TRACE 40
#define PragFlag_NeedSchema 0x01
static const struct sPragmaNames {
const char *const zName; /* Name of pragma */
@@ -359,6 +360,12 @@ static const struct sPragmaNames {
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_SqlTrace },
#endif
#if !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
{ /* zName: */ "stats",
/* ePragTyp: */ PragTyp_STATS,
/* ePragFlag: */ PragFlag_NeedSchema,
/* iArg: */ 0 },
#endif
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS)
{ /* zName: */ "synchronous",
/* ePragTyp: */ PragTyp_SYNCHRONOUS,
@@ -420,7 +427,7 @@ static const struct sPragmaNames {
/* ePragFlag: */ 0,
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
};
/* Number of pragmas: 55 on by default, 67 total. */
/* Number of pragmas: 56 on by default, 68 total. */
/* End of the automatically generated pragma table.
***************************************************************************/
@@ -1425,6 +1432,36 @@ void sqlite3Pragma(
}
break;
case PragTyp_STATS: {
Index *pIdx;
HashElem *i;
v = sqlite3GetVdbe(pParse);
sqlite3VdbeSetNumCols(v, 4);
pParse->nMem = 4;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "table", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "index", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "width", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "height", SQLITE_STATIC);
for(i=sqliteHashFirst(&pDb->pSchema->tblHash); i; i=sqliteHashNext(i)){
Table *pTab = sqliteHashData(i);
sqlite3VdbeAddOp4(v, OP_String8, 0, 1, 0, pTab->zName, 0);
sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pTab->szTabRow), 3);
sqlite3VdbeAddOp2(v, OP_Integer, (int)pTab->nRowEst, 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pIdx->szIdxRow), 3);
sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
}
}
}
break;
case PragTyp_INDEX_INFO: if( zRight ){
Index *pIdx;
Table *pTab;
@@ -1457,26 +1494,17 @@ void sqlite3Pragma(
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
v = sqlite3GetVdbe(pParse);
sqlite3VdbeSetNumCols(v, 4);
pParse->nMem = 4;
sqlite3VdbeSetNumCols(v, 3);
pParse->nMem = 3;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "avgrowsize", SQLITE_STATIC);
sqlite3VdbeAddOp2(v, OP_Integer, 0, 1);
sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
sqlite3VdbeAddOp2(v, OP_Integer, 1, 3);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pTab->szTabRow), 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
for(pIdx=pTab->pIndex, i=1; pIdx; pIdx=pIdx->pNext, i++){
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
sqlite3VdbeAddOp2(v, OP_Integer, pIdx->onError!=OE_None, 3);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pIdx->szIdxRow), 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
}
}
}
@@ -1610,8 +1638,8 @@ void sqlite3Pragma(
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult, 0, pTab->zName,
P4_TRANSIENT);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
if( pParent==0 ) break;
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
if( pParent==0 ) continue;
pIdx = 0;
sqlite3TableLock(pParse, iDb, pParent->tnum, 0, pParent->zName);
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, 0);
@@ -1628,18 +1656,20 @@ void sqlite3Pragma(
break;
}
}
assert( pParse->nErr>0 || pFK==0 );
if( pFK ) break;
if( pParse->nTab<i ) pParse->nTab = i;
addrTop = sqlite3VdbeAddOp1(v, OP_Rewind, 0);
for(i=1, pFK=pTab->pFKey; pFK; i++, pFK=pFK->pNextFrom){
pParent = sqlite3LocateTable(pParse, 0, pFK->zTo, zDb);
assert( pParent!=0 );
pParent = sqlite3FindTable(db, pFK->zTo, zDb);
pIdx = 0;
aiCols = 0;
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
assert( x==0 );
if( pParent ){
x = sqlite3FkLocateIndex(pParse, pParent, pFK, &pIdx, &aiCols);
assert( x==0 );
}
addrOk = sqlite3VdbeMakeLabel(v);
if( pIdx==0 ){
if( pParent && pIdx==0 ){
int iKey = pFK->aCol[0].iFrom;
assert( iKey>=0 && iKey<pTab->nCol );
if( iKey!=pTab->iPKey ){
@@ -1657,13 +1687,15 @@ void sqlite3Pragma(
}else{
for(j=0; j<pFK->nCol; j++){
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
aiCols ? aiCols[j] : pFK->aCol[0].iFrom, regRow+j);
aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
sqlite3VdbeChangeP4(v, -1,
sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
if( pParent ){
sqlite3VdbeAddOp3(v, OP_MakeRecord, regRow, pFK->nCol, regKey);
sqlite3VdbeChangeP4(v, -1,
sqlite3IndexAffinityStr(v,pIdx), P4_TRANSIENT);
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
}
}
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
sqlite3VdbeAddOp4(v, OP_String8, 0, regResult+2, 0,
+4
View File
@@ -707,6 +707,10 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pNC->nErr++;
}
}else{
/* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
** likelihood(X, 0.0625).
** EVIDENCE-OF: R-35738-39582 The unlikely(X) fucntion is short-hand for
** likelihood(X,0.0625). */
pExpr->iTable = 62; /* TUNING: Default 2nd arg to unlikely() is 0.0625 */
}
}
+66 -33
View File
@@ -1061,6 +1061,9 @@ static void generateSortTail(
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
** Also try to estimate the size of the returned value and return that
** result in *pEstWidth.
**
** The declaration type is the exact datatype definition extracted from the
** original CREATE TABLE statement if the expression is a column. The
** declaration type for a ROWID field is INTEGER. Exactly when an expression
@@ -1074,21 +1077,36 @@ static void generateSortTail(
** SELECT abc FROM (SELECT col AS abc FROM tbl);
**
** The declaration type for any expression other than a column is NULL.
**
** This routine has either 3 or 6 parameters depending on whether or not
** the SQLITE_ENABLE_COLUMN_METADATA compile-time option is used.
*/
static const char *columnType(
#ifdef SQLITE_ENABLE_COLUMN_METADATA
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,C,D,E,F)
static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
const char **pzOriginDb,
const char **pzOriginTab,
const char **pzOriginCol
const char **pzOrigDb,
const char **pzOrigTab,
const char **pzOrigCol,
u8 *pEstWidth
){
char const *zOrigDb = 0;
char const *zOrigTab = 0;
char const *zOrigCol = 0;
#else /* if !defined(SQLITE_ENABLE_COLUMN_METADATA) */
# define columnType(A,B,C,D,E,F) columnTypeImpl(A,B,F)
static const char *columnTypeImpl(
NameContext *pNC,
Expr *pExpr,
u8 *pEstWidth
){
#endif /* !defined(SQLITE_ENABLE_COLUMN_METADATA) */
char const *zType = 0;
char const *zOriginDb = 0;
char const *zOriginTab = 0;
char const *zOriginCol = 0;
int j;
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
u8 estWidth = 1;
if( NEVER(pExpr==0) || pNC->pSrcList==0 ) return 0;
switch( pExpr->op ){
case TK_AGG_COLUMN:
case TK_COLUMN: {
@@ -1149,25 +1167,35 @@ static const char *columnType(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
zType = columnType(&sNC, p,&zOrigDb,&zOrigTab,&zOrigCol, &estWidth);
}
}else if( ALWAYS(pTab->pSchema) ){
/* A real table */
assert( !pS );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
#ifdef SQLITE_ENABLE_COLUMN_METADATA
if( iCol<0 ){
zType = "INTEGER";
zOriginCol = "rowid";
zOrigCol = "rowid";
}else{
zType = pTab->aCol[iCol].zType;
zOriginCol = pTab->aCol[iCol].zName;
zOrigCol = pTab->aCol[iCol].zName;
estWidth = pTab->aCol[iCol].szEst;
}
zOriginTab = pTab->zName;
zOrigTab = pTab->zName;
if( pNC->pParse ){
int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);
zOriginDb = pNC->pParse->db->aDb[iDb].zName;
zOrigDb = pNC->pParse->db->aDb[iDb].zName;
}
#else
if( iCol<0 ){
zType = "INTEGER";
}else{
zType = pTab->aCol[iCol].zType;
estWidth = pTab->aCol[iCol].szEst;
}
#endif
}
break;
}
@@ -1184,18 +1212,21 @@ static const char *columnType(
sNC.pSrcList = pS->pSrc;
sNC.pNext = pNC;
sNC.pParse = pNC->pParse;
zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, &estWidth);
break;
}
#endif
}
if( pzOriginDb ){
assert( pzOriginTab && pzOriginCol );
*pzOriginDb = zOriginDb;
*pzOriginTab = zOriginTab;
*pzOriginCol = zOriginCol;
#ifdef SQLITE_ENABLE_COLUMN_METADATA
if( pzOrigDb ){
assert( pzOrigTab && pzOrigCol );
*pzOrigDb = zOrigDb;
*pzOrigTab = zOrigTab;
*pzOrigCol = zOrigCol;
}
#endif
if( pEstWidth ) *pEstWidth = estWidth;
return zType;
}
@@ -1221,7 +1252,7 @@ static void generateColumnTypes(
const char *zOrigDb = 0;
const char *zOrigTab = 0;
const char *zOrigCol = 0;
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);
zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol, 0);
/* The vdbe must make its own copy of the column-type and other
** column specific strings, in case the schema is reset before this
@@ -1231,11 +1262,11 @@ static void generateColumnTypes(
sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, SQLITE_TRANSIENT);
sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, SQLITE_TRANSIENT);
#else
zType = columnType(&sNC, p, 0, 0, 0);
zType = columnType(&sNC, p, 0, 0, 0, 0);
#endif
sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, SQLITE_TRANSIENT);
}
#endif /* SQLITE_OMIT_DECLTYPE */
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
/*
@@ -1424,8 +1455,7 @@ static int selectColumnsFromExprList(
*/
static void selectAddColumnTypeAndCollation(
Parse *pParse, /* Parsing contexts */
int nCol, /* Number of columns */
Column *aCol, /* List of columns */
Table *pTab, /* Add column type information to this table */
Select *pSelect /* SELECT used to determine types and collations */
){
sqlite3 *db = pParse->db;
@@ -1435,17 +1465,19 @@ static void selectAddColumnTypeAndCollation(
int i;
Expr *p;
struct ExprList_item *a;
u64 szAll = 0;
assert( pSelect!=0 );
assert( (pSelect->selFlags & SF_Resolved)!=0 );
assert( nCol==pSelect->pEList->nExpr || db->mallocFailed );
assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed );
if( db->mallocFailed ) return;
memset(&sNC, 0, sizeof(sNC));
sNC.pSrcList = pSelect->pSrc;
a = pSelect->pEList->a;
for(i=0, pCol=aCol; i<nCol; i++, pCol++){
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
p = a[i].pExpr;
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p, 0, 0, 0));
pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
pColl = sqlite3ExprCollSeq(pParse, p);
@@ -1453,6 +1485,7 @@ static void selectAddColumnTypeAndCollation(
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
}
}
pTab->szTabRow = sqlite3LogEst(szAll*4);
}
/*
@@ -1480,9 +1513,9 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
assert( db->lookaside.bEnabled==0 );
pTab->nRef = 1;
pTab->zName = 0;
pTab->nRowEst = 200;
pTab->nRowEst = 1048576;
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSelect);
selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1;
if( db->mallocFailed ){
sqlite3DeleteTable(db, pTab);
@@ -3394,11 +3427,11 @@ static int selectExpander(Walker *pWalker, Select *p){
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
pTab->nRef = 1;
pTab->zName = sqlite3MPrintf(db, "sqlite_subquery_%p_", (void*)pTab);
pTab->zName = sqlite3MPrintf(db, "sqlite_sq_%p", (void*)pTab);
while( pSel->pPrior ){ pSel = pSel->pPrior; }
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
pTab->iPKey = -1;
pTab->nRowEst = 200;
pTab->nRowEst = 1048576;
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
@@ -3682,7 +3715,7 @@ static int selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){
Select *pSel = pFrom->pSelect;
assert( pSel );
while( pSel->pPrior ) pSel = pSel->pPrior;
selectAddColumnTypeAndCollation(pParse, pTab->nCol, pTab->aCol, pSel);
selectAddColumnTypeAndCollation(pParse, pTab, pSel);
}
}
}
+1 -1
View File
@@ -1204,7 +1204,7 @@ static int shell_exec(
/* extract the data and data types */
for(i=0; i<nCol; i++){
aiTypes[i] = x = sqlite3_column_type(pStmt, i);
if( x==SQLITE_BLOB && pArg->mode==MODE_Insert ){
if( x==SQLITE_BLOB && pArg && pArg->mode==MODE_Insert ){
azVals[i] = "";
}else{
azVals[i] = (char*)sqlite3_column_text(pStmt, i);
+13 -13
View File
@@ -1612,27 +1612,27 @@ struct sqlite3_mem_methods {
** function must be threadsafe. </dd>
**
** [[SQLITE_CONFIG_URI]] <dt>SQLITE_CONFIG_URI
** <dd> This option takes a single argument of type int. If non-zero, then
** <dd>^(This option takes a single argument of type int. If non-zero, then
** URI handling is globally enabled. If the parameter is zero, then URI handling
** is globally disabled. If URI handling is globally enabled, all filenames
** is globally disabled.)^ ^If URI handling is globally enabled, all filenames
** passed to [sqlite3_open()], [sqlite3_open_v2()], [sqlite3_open16()] or
** specified as part of [ATTACH] commands are interpreted as URIs, regardless
** of whether or not the [SQLITE_OPEN_URI] flag is set when the database
** connection is opened. If it is globally disabled, filenames are
** connection is opened. ^If it is globally disabled, filenames are
** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the
** database connection is opened. By default, URI handling is globally
** database connection is opened. ^(By default, URI handling is globally
** disabled. The default value may be changed by compiling with the
** [SQLITE_USE_URI] symbol defined.
** [SQLITE_USE_URI] symbol defined.)^
**
** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN
** <dd> This option takes a single integer argument which is interpreted as
** <dd>^This option takes a single integer argument which is interpreted as
** a boolean in order to enable or disable the use of covering indices for
** full table scans in the query optimizer. The default setting is determined
** full table scans in the query optimizer. ^The default setting is determined
** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on"
** if that compile-time option is omitted.
** The ability to disable the use of covering indices for full table scans
** is because some incorrectly coded legacy applications might malfunction
** malfunction when the optimization is enabled. Providing the ability to
** when the optimization is enabled. Providing the ability to
** disable the optimization allows the older, buggy application code to work
** without change even with newer versions of SQLite.
**
@@ -1661,16 +1661,16 @@ struct sqlite3_mem_methods {
**
** [[SQLITE_CONFIG_MMAP_SIZE]]
** <dt>SQLITE_CONFIG_MMAP_SIZE
** <dd>SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
** <dd>^SQLITE_CONFIG_MMAP_SIZE takes two 64-bit integer (sqlite3_int64) values
** that are the default mmap size limit (the default setting for
** [PRAGMA mmap_size]) and the maximum allowed mmap size limit.
** The default setting can be overridden by each database connection using
** ^The default setting can be overridden by each database connection using
** either the [PRAGMA mmap_size] command, or by using the
** [SQLITE_FCNTL_MMAP_SIZE] file control. The maximum allowed mmap size
** [SQLITE_FCNTL_MMAP_SIZE] file control. ^(The maximum allowed mmap size
** cannot be changed at run-time. Nor may the maximum allowed mmap size
** exceed the compile-time maximum mmap size set by the
** [SQLITE_MAX_MMAP_SIZE] compile-time option.
** If either argument to this option is negative, then that argument is
** [SQLITE_MAX_MMAP_SIZE] compile-time option.)^
** ^If either argument to this option is negative, then that argument is
** changed to its compile-time default.
** </dl>
*/
+10 -10
View File
@@ -12,6 +12,7 @@
** Internal interface definitions for SQLite.
**
*/
#include "sqlite3.h"
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -305,7 +306,6 @@
#define likely(X) (X)
#define unlikely(X) (X)
#include "sqlite3.h"
#include "hash.h"
#include "parse.h"
#include <stdio.h>
@@ -1382,11 +1382,11 @@ struct Table {
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
tRowcnt nRowEst; /* Estimated rows in table - from sqlite_stat1 table */
int tnum; /* Root BTree node for this table (see note above) */
i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
i16 nCol; /* Number of columns in this table */
u16 nRef; /* Number of pointers to this Table */
LogEst nRowEst; /* Estimated number of rows in the table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
u8 tabFlags; /* Mask of TF_* values */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
@@ -1577,7 +1577,7 @@ struct UnpackedRecord {
struct Index {
char *zName; /* Name of this index */
int *aiColumn; /* Which columns are used by this index. 1st is 0 */
LogEst *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
tRowcnt *aiRowEst; /* From ANALYZE: Est. rows selected by each column */
Table *pTable; /* The SQL table being indexed */
char *zColAff; /* String defining the affinity of each column */
Index *pNext; /* The next index associated with the same table */
@@ -1595,7 +1595,7 @@ struct Index {
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
int nSample; /* Number of elements in aSample[] */
int nSampleCol; /* Size of IndexSample.anEq[] and so on */
LogEst *aAvgEq; /* Average nEq values for keys not in aSample */
tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */
IndexSample *aSample; /* Samples of the left-most key */
#endif
};
@@ -1608,9 +1608,9 @@ struct Index {
struct IndexSample {
void *p; /* Pointer to sampled record */
int n; /* Size of record in bytes */
LogEst *anEq; /* Est. number of rows where the key equals this sample */
LogEst *anLt; /* Est. number of rows where key is less than this sample */
LogEst *anDLt; /* Est. number of distinct keys less than this sample */
tRowcnt *anEq; /* Est. number of rows where the key equals this sample */
tRowcnt *anLt; /* Est. number of rows where key is less than this sample */
tRowcnt *anDLt; /* Est. number of distinct keys less than this sample */
};
/*
@@ -3248,10 +3248,10 @@ const char *sqlite3JournalModename(int);
FKey *sqlite3FkReferences(Table *);
#else
#define sqlite3FkActions(a,b,c,d,e,f)
#define sqlite3FkCheck(a,b,c,d)
#define sqlite3FkCheck(a,b,c,d,e,f)
#define sqlite3FkDropTable(a,b,c)
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d,e,f) 0
#define sqlite3FkOldmask(a,b) 0
#define sqlite3FkRequired(a,b,c,d) 0
#endif
#ifndef SQLITE_OMIT_FOREIGN_KEY
void sqlite3FkDelete(sqlite3 *, Table*);
+2
View File
@@ -6160,6 +6160,7 @@ static int tclLoadStaticExtensionCmd(
extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
static const struct {
const char *zExtName;
@@ -6173,6 +6174,7 @@ static int tclLoadStaticExtensionCmd(
{ "percentile", sqlite3_percentile_init },
{ "regexp", sqlite3_regexp_init },
{ "spellfix", sqlite3_spellfix_init },
{ "totype", sqlite3_totype_init },
{ "wholenumber", sqlite3_wholenumber_init },
};
sqlite3 *db;
+2 -2
View File
@@ -133,9 +133,9 @@ struct CrashFile {
** OsFileSize() calls. Although both could be done by traversing the
** write-list, in practice this is impractically slow.
*/
int iSize; /* Size of file in bytes */
int nData; /* Size of buffer allocated at zData */
u8 *zData; /* Buffer containing file contents */
int nData; /* Size of buffer allocated at zData */
i64 iSize; /* Size of file in bytes */
};
struct CrashGlobal {
+17 -1
View File
@@ -40,6 +40,7 @@ int sqlite3_client_finalize(sqlite3_stmt*);
int sqlite3_client_close(sqlite3*);
int sqlite3_server_start(void);
int sqlite3_server_stop(void);
void sqlite3_server_start2(int *pnDecr);
/*
** Each thread is controlled by an instance of the following
@@ -68,6 +69,13 @@ struct Thread {
int argc; /* number of columns in result */
const char *argv[100]; /* result columns */
const char *colv[100]; /* result column names */
/* Initialized to 1 by the supervisor thread when the client is
** created, and then deemed read-only to the supervisor thread.
** Is set to 0 by the server thread belonging to this client
** just before it exits.
*/
int nServer; /* Number of server threads running */
};
/*
@@ -175,7 +183,10 @@ static int tcl_client_create(
return TCL_ERROR;
}
pthread_detach(x);
sqlite3_server_start();
if( threadset[i].nServer==0 ){
threadset[i].nServer = 1;
sqlite3_server_start2(&threadset[i].nServer);
}
return TCL_OK;
}
@@ -268,6 +279,11 @@ static int tcl_client_halt(
for(i=0; i<N_THREAD && threadset[i].busy==0; i++){}
if( i>=N_THREAD ){
sqlite3_server_stop();
while( 1 ){
for(i=0; i<N_THREAD && threadset[i].nServer==0; i++);
if( i==N_THREAD ) break;
sched_yield();
}
}
return TCL_OK;
}
+26
View File
@@ -472,6 +472,32 @@ void sqlite3_server_start(void){
}
}
/*
** A wrapper around sqlite3_server() that decrements the int variable
** pointed to by the first argument after the sqlite3_server() call
** returns.
*/
static void *serverWrapper(void *pnDecr){
void *p = sqlite3_server(0);
(*(int*)pnDecr)--;
return p;
}
/*
** This function is the similar to sqlite3_server_start(), except that
** the integer pointed to by the first argument is decremented when
** the server thread exits.
*/
void sqlite3_server_start2(int *pnDecr){
pthread_t x;
int rc;
g.serverHalt = 0;
rc = pthread_create(&x, 0, serverWrapper, (void*)pnDecr);
if( rc==0 ){
pthread_detach(x);
}
}
/*
** If a server thread is running, then stop it. If no server is
** running, this routine is effectively a no-op.
+1
View File
@@ -1213,6 +1213,7 @@ void sqlite3FileSuffix3(const char *zBaseFilename, char *z){
** Find (an approximate) sum of two LogEst values. This computation is
** not a simple "+" operator because LogEst is stored as a logarithmic
** value.
**
*/
LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
static const unsigned char x[] = {
+5 -2
View File
@@ -1059,7 +1059,9 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
pRec->nField = p->iVal+1;
return &pRec->aMem[p->iVal];
}
#endif
#else
UNUSED_PARAMETER(p);
#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
return sqlite3ValueNew(db);
}
@@ -1073,7 +1075,7 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
** NULL, it is assumed that the caller will free any allocated object
** in all cases.
*/
int valueFromExpr(
static int valueFromExpr(
sqlite3 *db, /* The database connection */
Expr *pExpr, /* The expression to evaluate */
u8 enc, /* Encoding to use */
@@ -1230,6 +1232,7 @@ static void recordFunc(
sqlite3 *db;
u8 *aRet;
UNUSED_PARAMETER( argc );
iSerial = sqlite3VdbeSerialType(argv[0], file_format);
nSerial = sqlite3VarintLen(iSerial);
nVal = sqlite3VdbeSerialTypeLen(iSerial);
+71 -62
View File
@@ -2328,7 +2328,7 @@ static void whereKeyStats(
Index *pIdx, /* Index to consider domain of */
UnpackedRecord *pRec, /* Vector of values to consider */
int roundUp, /* Round up if true. Round down if false */
LogEst *aStat /* OUT: stats written here */
tRowcnt *aStat /* OUT: stats written here */
){
IndexSample *aSample = pIdx->aSample;
int iCol; /* Index of required stats in anEq[] etc. */
@@ -2337,6 +2337,9 @@ static void whereKeyStats(
int iTest; /* Next sample to test */
int res; /* Result of comparison operation */
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER( pParse );
#endif
assert( pRec!=0 || pParse->db->mallocFailed );
if( pRec==0 ) return;
iCol = pRec->nField - 1;
@@ -2381,16 +2384,15 @@ static void whereKeyStats(
aStat[0] = aSample[i].anLt[iCol];
aStat[1] = aSample[i].anEq[iCol];
}else{
LogEst iLower, iUpper, iGap;
tRowcnt iLower, iUpper, iGap;
if( i==0 ){
iLower = 0;
iUpper = aSample[0].anLt[iCol];
}else{
iUpper = i>=pIdx->nSample ? pIdx->aiRowEst[0] : aSample[i].anLt[iCol];
iLower = sqlite3LogEstAdd(aSample[i-1].anEq[iCol],
aSample[i-1].anLt[iCol]);
iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
}
aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 0);
aStat[1] = (pIdx->nColumn>iCol ? pIdx->aAvgEq[iCol] : 1);
if( iLower>=iUpper ){
iGap = 0;
}else{
@@ -2451,15 +2453,15 @@ static int whereRangeScanEst(
WhereLoopBuilder *pBuilder,
WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */
WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */
LogEst *pnOut /* IN/OUT: Number of rows visited */
WhereLoop *pLoop /* Modify the .nOut and maybe .rRun fields */
){
int rc = SQLITE_OK;
int nOut = (int)*pnOut;
int nOut = pLoop->nOut;
LogEst nNew;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
Index *p = pBuilder->pNew->u.btree.pIndex;
int nEq = pBuilder->pNew->u.btree.nEq;
Index *p = pLoop->u.btree.pIndex;
int nEq = pLoop->u.btree.nEq;
if( p->nSample>0
&& nEq==pBuilder->nRecValid
@@ -2467,7 +2469,7 @@ static int whereRangeScanEst(
&& OptimizationEnabled(pParse->db, SQLITE_Stat3)
){
UnpackedRecord *pRec = pBuilder->pRec;
LogEst a[2];
tRowcnt a[2];
u8 aff;
/* Variable iLower will be set to the estimate of the number of rows in
@@ -2487,8 +2489,8 @@ static int whereRangeScanEst(
** is either ($P) or ($P:$U). Again, even if $U is available, both values
** of iUpper are requested of whereKeyStats() and the smaller used.
*/
LogEst iLower;
LogEst iUpper;
tRowcnt iLower;
tRowcnt iUpper;
if( nEq==p->nColumn ){
aff = SQLITE_AFF_INTEGER;
@@ -2504,7 +2506,7 @@ static int whereRangeScanEst(
** have been requested when testing key $P in whereEqualScanEst(). */
whereKeyStats(pParse, p, pRec, 0, a);
iLower = a[0];
iUpper = sqlite3LogEstAdd(a[0],a[1]);
iUpper = a[0] + a[1];
}
/* If possible, improve on the iLower estimate using ($P:$L). */
@@ -2514,9 +2516,9 @@ static int whereRangeScanEst(
assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
LogEst iNew;
tRowcnt iNew;
whereKeyStats(pParse, p, pRec, 0, a);
iNew = sqlite3LogEstAdd(a[0],((pLower->eOperator & WO_GT) ? a[1] : 0));
iNew = a[0] + ((pLower->eOperator & WO_GT) ? a[1] : 0);
if( iNew>iLower ) iLower = iNew;
nOut--;
}
@@ -2529,9 +2531,9 @@ static int whereRangeScanEst(
assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);
if( rc==SQLITE_OK && bOk ){
LogEst iNew;
tRowcnt iNew;
whereKeyStats(pParse, p, pRec, 1, a);
iNew = sqlite3LogEstAdd(a[0],((pUpper->eOperator & WO_LE) ? a[1] : 0));
iNew = a[0] + ((pUpper->eOperator & WO_LE) ? a[1] : 0);
if( iNew<iUpper ) iUpper = iNew;
nOut--;
}
@@ -2539,17 +2541,17 @@ static int whereRangeScanEst(
pBuilder->pRec = pRec;
if( rc==SQLITE_OK ){
if( iUpper<=iLower ) iUpper = iLower+1;
nNew = sqlite3LogEst(sqlite3LogEstToInt(iUpper)
- sqlite3LogEstToInt(iLower));
if( iUpper>iLower ){
nNew = sqlite3LogEst(iUpper - iLower);
}else{
nNew = 10; assert( 10==sqlite3LogEst(2) );
}
if( nNew<nOut ){
nOut = nNew;
}
*pnOut = (LogEst)nOut;
WHERETRACE(0x100, ("range scan regions: %llu..%llu est=%d\n",
sqlite3LogEstToInt(iLower),
sqlite3LogEstToInt(iUpper),
nOut));
pLoop->nOut = (LogEst)nOut;
WHERETRACE(0x100, ("range scan regions: %u..%u est=%d\n",
(u32)iLower, (u32)iUpper, nOut));
return SQLITE_OK;
}
}
@@ -2571,7 +2573,7 @@ static int whereRangeScanEst(
}
if( nNew<10 ) nNew = 10;
if( nNew<nOut ) nOut = nNew;
*pnOut = (LogEst)nOut;
pLoop->nOut = (LogEst)nOut;
return rc;
}
@@ -2597,14 +2599,14 @@ static int whereEqualScanEst(
Parse *pParse, /* Parsing & code generating context */
WhereLoopBuilder *pBuilder,
Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */
LogEst *pnRow /* Write the revised row estimate here */
tRowcnt *pnRow /* Write the revised row estimate here */
){
Index *p = pBuilder->pNew->u.btree.pIndex;
int nEq = pBuilder->pNew->u.btree.nEq;
UnpackedRecord *pRec = pBuilder->pRec;
u8 aff; /* Column affinity */
int rc; /* Subfunction return code */
LogEst a[2]; /* Statistics */
tRowcnt a[2]; /* Statistics */
int bOk;
assert( nEq>=1 );
@@ -2634,8 +2636,7 @@ static int whereEqualScanEst(
pBuilder->nRecValid = nEq;
whereKeyStats(pParse, p, pRec, 0, a);
WHERETRACE(0x100,("equality scan regions: %d (%llu)\n", a[1],
sqlite3LogEstToInt(a[1])));
WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
*pnRow = a[1];
return rc;
@@ -2663,28 +2664,27 @@ static int whereInScanEst(
Parse *pParse, /* Parsing & code generating context */
WhereLoopBuilder *pBuilder,
ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */
LogEst *pnRow /* Write the revised row estimate here */
tRowcnt *pnRow /* Write the revised row estimate here */
){
Index *p = pBuilder->pNew->u.btree.pIndex;
int nRecValid = pBuilder->nRecValid;
int rc = SQLITE_OK; /* Subfunction return code */
LogEst nEst; /* Number of rows for a single term */
u64 nRowEst = 0; /* New estimate of the number of rows */
tRowcnt nEst; /* Number of rows for a single term */
tRowcnt nRowEst = 0; /* New estimate of the number of rows */
int i; /* Loop counter */
assert( p->aSample!=0 );
for(i=0; rc==SQLITE_OK && i<pList->nExpr; i++){
nEst = p->aiRowEst[0];
rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst);
nRowEst += sqlite3LogEstToInt(nEst);
nRowEst += nEst;
pBuilder->nRecValid = nRecValid;
}
if( rc==SQLITE_OK ){
nEst = sqlite3LogEst(nRowEst);
if( nEst > p->aiRowEst[0] ) nEst = p->aiRowEst[0];
*pnRow = nEst;
WHERETRACE(0x100,("IN row estimate: est=%d (%llu)\n", nEst, nRowEst));
if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0];
*pnRow = nRowEst;
WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst));
}
assert( pBuilder->nRecValid==nRecValid );
return rc;
@@ -4185,7 +4185,7 @@ whereLoopInsert_noop:
** the number of output rows by a factor of 10 and each additional term
** reduces the number of output rows by sqrt(2).
*/
static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop, int iCur){
static void whereLoopOutputAdjust(WhereClause *pWC, WhereLoop *pLoop){
WhereTerm *pTerm, *pX;
Bitmask notAllowed = ~(pLoop->prereq|pLoop->maskSelf);
int i, j;
@@ -4254,8 +4254,8 @@ static int whereLoopAddBtreeIndex(
assert( pNew->u.btree.nEq<=pProbe->nColumn );
if( pNew->u.btree.nEq < pProbe->nColumn ){
iCol = pProbe->aiColumn[pNew->u.btree.nEq];
nRowEst = pProbe->aiRowEst[pNew->u.btree.nEq+1];
if( nRowEst<10 && pProbe->onError==OE_None ) nRowEst = 10;
nRowEst = sqlite3LogEst(pProbe->aiRowEst[pNew->u.btree.nEq+1]);
if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1;
}else{
iCol = -1;
nRowEst = 0;
@@ -4268,7 +4268,7 @@ static int whereLoopAddBtreeIndex(
saved_prereq = pNew->prereq;
saved_nOut = pNew->nOut;
pNew->rSetup = 0;
rLogSize = estLog(pProbe->aiRowEst[0]);
rLogSize = estLog(sqlite3LogEst(pProbe->aiRowEst[0]));
for(; rc==SQLITE_OK && pTerm!=0; pTerm = whereScanNext(&scan)){
int nIn = 0;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
@@ -4340,7 +4340,7 @@ static int whereLoopAddBtreeIndex(
if( pNew->wsFlags & WHERE_COLUMN_RANGE ){
/* Adjust nOut and rRun for STAT3 range values */
assert( pNew->nOut==saved_nOut );
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, &pNew->nOut);
whereRangeScanEst(pParse, pBuilder, pBtm, pTop, pNew);
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( nInMul==0
@@ -4349,7 +4349,7 @@ static int whereLoopAddBtreeIndex(
&& OptimizationEnabled(db, SQLITE_Stat3)
){
Expr *pExpr = pTerm->pExpr;
LogEst nOut = pNew->nOut;
tRowcnt nOut = 0;
if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){
testcase( pTerm->eOperator & WO_EQ );
testcase( pTerm->eOperator & WO_ISNULL );
@@ -4358,8 +4358,11 @@ static int whereLoopAddBtreeIndex(
&& !ExprHasProperty(pExpr, EP_xIsSelect) ){
rc = whereInScanEst(pParse, pBuilder, pExpr->x.pList, &nOut);
}
assert( nOut==pNew->nOut || rc==SQLITE_OK );
if( nOut<pNew->nOut ) pNew->nOut = nOut;
assert( nOut==0 || rc==SQLITE_OK );
if( nOut ){
pNew->nOut = sqlite3LogEst(nOut);
if( pNew->nOut>saved_nOut ) pNew->nOut = saved_nOut;
}
}
#endif
if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){
@@ -4369,7 +4372,7 @@ static int whereLoopAddBtreeIndex(
}
/* Step cost for each output row */
pNew->rRun = sqlite3LogEstAdd(pNew->rRun, pNew->nOut);
whereLoopOutputAdjust(pBuilder->pWC, pNew, pSrc->iCursor);
whereLoopOutputAdjust(pBuilder->pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0
&& pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0))
@@ -4460,7 +4463,7 @@ static int whereLoopAddBtree(
WhereInfo *pWInfo; /* WHERE analysis context */
Index *pProbe; /* An index we are evaluating */
Index sPk; /* A fake index object for the primary key */
LogEst aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */
int aiColumnPk = -1; /* The aColumn[] value for the sPk index */
SrcList *pTabList; /* The FROM clause */
struct SrcList_item *pSrc; /* The FROM clause btree term to add */
@@ -4471,11 +4474,13 @@ static int whereLoopAddBtree(
LogEst rSize; /* number of rows in the table */
LogEst rLogSize; /* Logarithm of the number of rows in the table */
WhereClause *pWC; /* The parsed WHERE clause */
Table *pTab; /* Table being queried */
pNew = pBuilder->pNew;
pWInfo = pBuilder->pWInfo;
pTabList = pWInfo->pTabList;
pSrc = pTabList->a + pNew->iTab;
pTab = pSrc->pTab;
pWC = pBuilder->pWC;
assert( !IsVirtual(pSrc->pTab) );
@@ -4493,9 +4498,9 @@ static int whereLoopAddBtree(
sPk.aiColumn = &aiColumnPk;
sPk.aiRowEst = aiRowEstPk;
sPk.onError = OE_Replace;
sPk.pTable = pSrc->pTab;
aiRowEstPk[0] = pSrc->pTab->nRowEst;
aiRowEstPk[1] = 0;
sPk.pTable = pTab;
aiRowEstPk[0] = pTab->nRowEst;
aiRowEstPk[1] = 1;
pFirst = pSrc->pTab->pIndex;
if( pSrc->notIndexed==0 ){
/* The real indices of the table are only considered if the
@@ -4504,7 +4509,7 @@ static int whereLoopAddBtree(
}
pProbe = &sPk;
}
rSize = pSrc->pTab->nRowEst;
rSize = sqlite3LogEst(pTab->nRowEst);
rLogSize = estLog(rSize);
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
@@ -4571,7 +4576,7 @@ static int whereLoopAddBtree(
** + The extra 3 factor is to encourage the use of indexed lookups
** over full scans. FIXME */
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 16;
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
whereLoopOutputAdjust(pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
@@ -4583,6 +4588,7 @@ static int whereLoopAddBtree(
if( b
|| ( m==0
&& pProbe->bUnordered==0
&& pProbe->szIdxRow<pTab->szTabRow
&& (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0
&& sqlite3GlobalConfig.bUseCis
&& OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
@@ -4591,18 +4597,19 @@ static int whereLoopAddBtree(
pNew->iSortIdx = b ? iSortIdx : 0;
if( m==0 ){
/* TUNING: Cost of a covering index scan is K*(N + log2(N)).
** + The extra factor K of between 1.1 (iScanRatio between 0
** and 9) and 2.8 (iScanRatio between 126 and 127) is added
** to encourage the use of indexed lookups. FIXME
** + The extra factor K of between 1.1 and 3.0 that depends
** on the relative sizes of the table and the index. K
** is smaller for smaller indices, thus favoring them.
*/
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 10;
pNew->rRun = sqlite3LogEstAdd(rSize,rLogSize) + 1 +
(15*pProbe->szIdxRow)/pTab->szTabRow;
}else{
assert( b!=0 );
/* TUNING: Cost of scanning a non-covering index is (N+1)*log2(N)
** which we will simplify to just N*log2(N) */
pNew->rRun = rSize + rLogSize;
}
whereLoopOutputAdjust(pWC, pNew, pSrc->iCursor);
whereLoopOutputAdjust(pWC, pNew);
rc = whereLoopInsert(pBuilder, pNew);
pNew->nOut = rSize;
if( rc ) break;
@@ -4812,6 +4819,8 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
pWCEnd = pWC->a + pWC->nTerm;
pNew = pBuilder->pNew;
memset(&sSum, 0, sizeof(sSum));
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE_OK; pTerm++){
if( (pTerm->eOperator & WO_OR)!=0
@@ -4823,8 +4832,6 @@ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){
int once = 1;
int i, j;
pItem = pWInfo->pTabList->a + pNew->iTab;
iCur = pItem->iCursor;
sSubBuild = *pBuilder;
sSubBuild.pOrderBy = 0;
sSubBuild.pOrSet = &sCur;
@@ -5262,8 +5269,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
if( pWInfo->pOrderBy==0 || nRowEst==0 ){
aFrom[0].isOrderedValid = 1;
}else{
/* TUNING: Estimated cost of sorting is N*log2(N) where N is the
** number of output rows. */
/* TUNING: Estimated cost of sorting is 48*N*log2(N) where N is the
** number of output rows. The 48 is the expected size of a row to sort.
** FIXME: compute a better estimate of the 48 multiplier based on the
** result set expressions. */
rSortCost = nRowEst + estLog(nRowEst);
WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost));
}
+3
View File
@@ -377,6 +377,9 @@ do_test attach2-6.2 {
}
} {1 {cannot ATTACH database within transaction}}
# EVIDENCE-OF: R-59740-55581 This statement will fail if SQLite is in
# the middle of a transaction.
#
do_test attach2-6.3 {
catchsql {
DETACH aux;
+4
View File
@@ -532,6 +532,10 @@ if {0==[sqlite3 -has-codec]} {
# Verify that multiple calls to date functions with 'now' return the
# same answer.
#
# EVIDENCE-OF: R-34818-13664 The 'now' argument to date and time
# functions always returns exactly the same value for multiple
# invocations within the same sqlite3_step() call.
#
proc sleeper {} {after 100}
do_test date-15.1 {
db func sleeper sleeper
+7 -7
View File
@@ -450,17 +450,17 @@ do_join_test e_select-1.4.1.4 {
# left-hand and right-hand datasets.
#
do_join_test e_select-1.4.2.1 {
SELECT * FROM x2 %JOIN% x3
SELECT * FROM x2 %JOIN% x3 ORDER BY +c, +f
} [list -60.06 {} {} -39.24 {} encompass -1 \
-60.06 {} {} presenting 51 reformation dignified \
-60.06 {} {} conducting -87.24 37.56 {} \
-60.06 {} {} coldest -96 dramatists 82.3 \
-60.06 {} {} alerting {} -93.79 {} \
-60.06 {} {} coldest -96 dramatists 82.3 \
-60.06 {} {} conducting -87.24 37.56 {} \
-60.06 {} {} presenting 51 reformation dignified \
-58 {} 1.21 -39.24 {} encompass -1 \
-58 {} 1.21 presenting 51 reformation dignified \
-58 {} 1.21 conducting -87.24 37.56 {} \
-58 {} 1.21 coldest -96 dramatists 82.3 \
-58 {} 1.21 alerting {} -93.79 {} \
-58 {} 1.21 coldest -96 dramatists 82.3 \
-58 {} 1.21 conducting -87.24 37.56 {} \
-58 {} 1.21 presenting 51 reformation dignified \
]
# TODO: Come back and add a few more like the above.
+53
View File
@@ -12,9 +12,12 @@
#
# This file tests the PRAGMA foreign_key_check command.
#
# EVIDENCE-OF: R-05426-18119 PRAGMA foreign_key_check; PRAGMA
# foreign_key_check(table-name);
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fkey5
ifcapable {!foreignkey} {
finish_test
@@ -82,6 +85,20 @@ do_test fkey5-1.4 {
}
} {}
# EVIDENCE-OF: R-45728-08709 There are four columns in each result row.
#
# EVIDENCE-OF: R-55672-01620 The first column is the name of the table
# that contains the REFERENCES clause.
#
# EVIDENCE-OF: R-25219-25618 The second column is the rowid of the row
# that contains the invalid REFERENCES clause.
#
# EVIDENCE-OF: R-40482-20265 The third column is the name of the table
# that is referred to.
#
# EVIDENCE-OF: R-62839-07969 The fourth column is the index of the
# specific foreign key constraint that failed.
#
do_test fkey5-2.0 {
db eval {
INSERT INTO c5 SELECT x FROM c1;
@@ -99,6 +116,9 @@ do_test fkey5-2.2 {
PRAGMA foreign_key_check(c1);
}
} {}
do_execsql_test fkey5-2.3 {
PRAGMA foreign_key_list(c5);
} {0 0 p1 x {} {NO ACTION} {NO ACTION} NONE}
do_test fkey5-3.0 {
db eval {
@@ -306,5 +326,38 @@ do_test fkey5-8.7 {
} {}
#-------------------------------------------------------------------------
# Tests 9.* verify that missing parent tables are handled correctly.
#
do_execsql_test 9.1.1 {
CREATE TABLE k1(x REFERENCES s1);
PRAGMA foreign_key_check(k1);
} {}
do_execsql_test 9.1.2 {
INSERT INTO k1 VALUES(NULL);
PRAGMA foreign_key_check(k1);
} {}
do_execsql_test 9.1.3 {
INSERT INTO k1 VALUES(1);
PRAGMA foreign_key_check(k1);
} {k1 2 s1 0}
do_execsql_test 9.2.1 {
CREATE TABLE k2(x, y, FOREIGN KEY(x, y) REFERENCES s1(a, b));
PRAGMA foreign_key_check(k2);
} {}
do_execsql_test 9.2 {
INSERT INTO k2 VALUES(NULL, 'five');
PRAGMA foreign_key_check(k2);
} {}
do_execsql_test 9.3 {
INSERT INTO k2 VALUES('one', NULL);
PRAGMA foreign_key_check(k2);
} {}
do_execsql_test 9.4 {
INSERT INTO k2 VALUES('six', 'seven');
PRAGMA foreign_key_check(k2);
} {k2 3 s1 0}
finish_test
+79 -6
View File
@@ -13,6 +13,13 @@
# This file tests the PRAGMA defer_foreign_keys and
# SQLITE_DBSTATUS_DEFERRED_FKS
#
# EVIDENCE-OF: R-18981-16292 When the defer_foreign_keys PRAGMA is on,
# enforcement of all foreign key constraints is delayed until the
# outermost transaction is committed.
#
# EVIDENCE-OF: R-28911-57501 The defer_foreign_keys pragma defaults to
# OFF so that foreign key constraints are only deferred if they are
# created as "DEFERRABLE INITIALLY DEFERRED".
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -22,6 +29,10 @@ ifcapable {!foreignkey} {
return
}
do_execsql_test fkey6-1.0 {
PRAGMA defer_foreign_keys;
} {0}
do_execsql_test fkey6-1.1 {
PRAGMA foreign_keys=ON;
CREATE TABLE t1(x INTEGER PRIMARY KEY);
@@ -70,12 +81,23 @@ do_test fkey6-1.8 {
do_test fkey6-1.9 {
sqlite3_db_status db DBSTATUS_DEFERRED_FKS 0
} {0 1 0}
do_test fkey6-1.10 {
execsql {
ROLLBACK;
PRAGMA defer_foreign_keys=OFF;
BEGIN;
}
# EVIDENCE-OF: R-21752-26913 The defer_foreign_keys pragma is
# automatically switched off at each COMMIT or ROLLBACK. Hence, the
# defer_foreign_keys pragma must be separately enabled for each
# transaction.
do_execsql_test fkey6-1.10.1 {
PRAGMA defer_foreign_keys;
ROLLBACK;
PRAGMA defer_foreign_keys;
BEGIN;
PRAGMA defer_foreign_keys=ON;
PRAGMA defer_foreign_keys;
COMMIT;
PRAGMA defer_foreign_keys;
BEGIN;
} {1 0 1 0}
do_test fkey6-1.10.2 {
catchsql {DELETE FROM t1 WHERE x=3}
} {1 {foreign key constraint failed}}
db eval {ROLLBACK}
@@ -99,5 +121,56 @@ do_test fkey6-1.22 {
}
} {}
do_execsql_test fkey6-2.1 {
CREATE TABLE p1(a PRIMARY KEY);
INSERT INTO p1 VALUES('one'), ('two');
CREATE TABLE c1(x REFERENCES p1);
INSERT INTO c1 VALUES('two'), ('one');
}
do_execsql_test fkey6-2.2 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
DELETE FROM p1;
ROLLBACK;
PRAGMA defer_foreign_keys;
} {0}
do_execsql_test fkey6-2.3 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
DROP TABLE p1;
PRAGMA vdbe_trace = 0;
ROLLBACK;
PRAGMA defer_foreign_keys;
} {0}
do_execsql_test fkey6-2.4 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
DELETE FROM p1;
DROP TABLE c1;
COMMIT;
PRAGMA defer_foreign_keys;
} {0}
do_execsql_test fkey6-2.5 {
DROP TABLE p1;
CREATE TABLE p1(a PRIMARY KEY);
INSERT INTO p1 VALUES('one'), ('two');
CREATE TABLE c1(x REFERENCES p1);
INSERT INTO c1 VALUES('two'), ('one');
}
do_execsql_test fkey6-2.6 {
BEGIN;
PRAGMA defer_foreign_keys = 1;
INSERT INTO c1 VALUES('three');
DROP TABLE c1;
COMMIT;
PRAGMA defer_foreign_keys;
} {0}
finish_test
+144
View File
@@ -0,0 +1,144 @@
# 2011 January 27
#
# 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
ifcapable !fts3 { finish_test ; return }
set ::testprefix fts3aux2
do_execsql_test 1.1 {
CREATE VIRTUAL TABLE t1 USING fts4(a, b, languageid=l);
INSERT INTO t1(a, b, l) VALUES
('zero zero', 'zero zero', 0),
('one two', 'three four', 1),
('five six', 'seven eight', 2)
;
CREATE VIRTUAL TABLE terms USING fts4aux(t1);
} {}
do_execsql_test 1.2.1 {
SELECT term, documents, occurrences, languageid FROM terms WHERE col = '*';
} {zero 1 4 0}
do_execsql_test 1.2.2 {
SELECT * FROM terms;
} {zero * 1 4 zero 0 1 2 zero 1 1 2}
do_execsql_test 1.2.3 {
SELECT * FROM terms WHERE languageid='';
} {}
do_execsql_test 1.2.4 {
SELECT * FROM terms WHERE languageid=-1;
} {}
do_execsql_test 1.2.5 {
SELECT * FROM terms WHERE languageid=9223372036854775807;
} {}
do_execsql_test 1.2.6 {
SELECT * FROM terms WHERE languageid=-9223372036854775808;
} {}
do_execsql_test 1.2.7 {
SELECT * FROM terms WHERE languageid=NULL;
} {}
do_execsql_test 1.3.1 {
SELECT term, documents, occurrences, languageid
FROM terms WHERE col = '*' AND languageid=1;
} {
four 1 1 1 one 1 1 1 three 1 1 1 two 1 1 1
}
do_execsql_test 1.3.2 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE languageid=1;
} {
four * 1 1 1 four 1 1 1 1
one * 1 1 1 one 0 1 1 1
three * 1 1 1 three 1 1 1 1
two * 1 1 1 two 0 1 1 1
}
do_execsql_test 1.3.3 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE languageid=1 AND term='zero'
} {
}
do_execsql_test 1.3.4 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE languageid='1' AND term='two'
} {
two * 1 1 1 two 0 1 1 1
}
do_execsql_test 1.3.5 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE languageid='+1' AND term>'four'
} {
one * 1 1 1 one 0 1 1 1
three * 1 1 1 three 1 1 1 1
two * 1 1 1 two 0 1 1 1
}
do_execsql_test 1.4.1 {
SELECT term, documents, occurrences, languageid
FROM terms WHERE col = '*' AND languageid=2;
} {
eight 1 1 2 five 1 1 2 seven 1 1 2 six 1 1 2
}
do_execsql_test 1.4.2 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE languageid=2;
} {
eight * 1 1 2 eight 1 1 1 2
five * 1 1 2 five 0 1 1 2
seven * 1 1 2 seven 1 1 1 2
six * 1 1 2 six 0 1 1 2
}
do_execsql_test 1.4.3 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE languageid=2 AND term='five';
} {
five * 1 1 2 five 0 1 1 2
}
do_execsql_test 1.4.4 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE term='five' AND languageid=2
} {
five * 1 1 2 five 0 1 1 2
}
do_execsql_test 1.4.5 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE term>='seven' AND languageid=2
} {
seven * 1 1 2 seven 1 1 1 2
six * 1 1 2 six 0 1 1 2
}
do_execsql_test 1.4.6 {
SELECT term, col, documents, occurrences, languageid
FROM terms WHERE term>='e' AND term<'seven' AND languageid=2
} {
eight * 1 1 2 eight 1 1 1 2
five * 1 1 2 five 0 1 1 2
}
finish_test
+22
View File
@@ -50,4 +50,26 @@ foreach {tn q res} {
puts "with optimization: $t(0) without: $t(1)"
}
do_test 2.1 {
execsql {
CREATE VIRTUAL TABLE t2 USING fts4(order=DESC);
}
set num [list one two three four five six seven eight nine ten]
execsql BEGIN
for {set i 0} {$i < 10000} {incr i} {
set x "[lindex $num [expr $i%10]] zero"
execsql { INSERT INTO t2(docid, content) VALUES($i, $x) }
}
execsql COMMIT
execsql { INSERT INTO t2(t2) VALUES('optimize') }
} {}
do_execsql_test 2.2 {
SELECT count(*) FROM t2 WHERE t2 MATCH '"never zero"'
} {0}
do_execsql_test 2.3 {
SELECT count(*) FROM t2 WHERE t2 MATCH '"two zero"'
} {1000}
finish_test
+20 -15
View File
@@ -44,31 +44,36 @@ proc do_unicode_token_test3 {tn args} {
}
do_unicode_token_test 1.0 {a B c D} {0 a a 1 b B 2 c c 3 d D}
do_unicode_token_test 1.1 {Ä Ö Ü} {0 ä Ä 1 ö Ö 2 ü Ü}
do_unicode_token_test 1.2 {xÄx xÖx xÜx} {0 xäx xÄx 1 xöx xÖx 2 xüx xÜx}
do_unicode_token_test 1.1 "\uC4 \uD6 \uDC" \
"0 \uE4 \uC4 1 \uF6 \uD6 2 \uFC \uDC"
do_unicode_token_test 1.2 "x\uC4x x\uD6x x\uDCx" \
"0 x\uE4x x\uC4x 1 x\uF6x x\uD6x 2 x\uFCx x\uDCx"
# 0x00DF is a small "sharp s". 0x1E9E is a capital sharp s.
do_unicode_token_test 1.3 "\uDF" "0 \uDF \uDF"
do_unicode_token_test 1.4 "\u1E9E" "0 ß \u1E9E"
do_unicode_token_test 1.5 "\u1E9E" "0 \uDF \u1E9E"
do_unicode_token_test 1.4 "\u1E9E" "0 \uDF \u1E9E"
do_unicode_token_test 1.6 "The quick brown fox" {
do_unicode_token_test 1.5 "The quick brown fox" {
0 the The 1 quick quick 2 brown brown 3 fox fox
}
do_unicode_token_test 1.7 "The\u00bfquick\u224ebrown\u2263fox" {
do_unicode_token_test 1.6 "The\u00bfquick\u224ebrown\u2263fox" {
0 the The 1 quick quick 2 brown brown 3 fox fox
}
do_unicode_token_test2 1.8 {a B c D} {0 a a 1 b B 2 c c 3 d D}
do_unicode_token_test2 1.9 {Ä Ö Ü} {0 a Ä 1 o Ö 2 u Ü}
do_unicode_token_test2 1.10 {xÄx xÖx xÜx} {0 xax xÄx 1 xox xÖx 2 xux xÜx}
do_unicode_token_test2 1.7 {a B c D} {0 a a 1 b B 2 c c 3 d D}
do_unicode_token_test2 1.8 "\uC4 \uD6 \uDC" "0 a \uC4 1 o \uD6 2 u \uDC"
do_unicode_token_test2 1.9 "x\uC4x x\uD6x x\uDCx" \
"0 xax x\uC4x 1 xox x\uD6x 2 xux x\uDCx"
# Check that diacritics are removed if remove_diacritics=1 is specified.
# And that they do not break tokens.
do_unicode_token_test2 1.11 "xx\u0301xx" "0 xxxx xx\u301xx"
do_unicode_token_test2 1.10 "xx\u0301xx" "0 xxxx xx\u301xx"
# Title-case mappings work
do_unicode_token_test 1.12 "\u01c5" "0 \u01c6 \u01c5"
do_unicode_token_test 1.11 "\u01c5" "0 \u01c6 \u01c5"
#-------------------------------------------------------------------------
#
@@ -378,10 +383,10 @@ foreach T $tokenizers {
do_isspace_test 6.$T.18 $T 12288
do_isspace_test 6.$T.19 $T {32 160 5760 6158}
do_isspace_test 6.$T.19 $T {8192 8193 8194 8195}
do_isspace_test 6.$T.19 $T {8196 8197 8198 8199}
do_isspace_test 6.$T.19 $T {8200 8201 8202 8239}
do_isspace_test 6.$T.19 $T {8287 12288}
do_isspace_test 6.$T.20 $T {8192 8193 8194 8195}
do_isspace_test 6.$T.21 $T {8196 8197 8198 8199}
do_isspace_test 6.$T.22 $T {8200 8201 8202 8239}
do_isspace_test 6.$T.23 $T {8287 12288}
}
#-------------------------------------------------------------------------
+8
View File
@@ -1319,6 +1319,14 @@ do_test func-29.6 {
set x
} {1}
# EVIDENCE-OF: R-29701-50711 The unicode(X) function returns the numeric
# unicode code point corresponding to the first character of the string
# X.
#
# EVIDENCE-OF: R-55469-62130 The char(X1,X2,...,XN) function returns a
# string composed of characters having the unicode code point values of
# integers X1 through XN, respectively.
#
do_execsql_test func-30.1 {SELECT unicode('$');} 36
do_execsql_test func-30.2 [subst {SELECT unicode('\u00A2');}] 162
do_execsql_test func-30.3 [subst {SELECT unicode('\u20AC');}] 8364
+83
View File
@@ -70,4 +70,87 @@ do_test func3-4.1 {
} {1 SQLITE_MISUSE}
do_test func3-4.2 { set destroyed } 1
# EVIDENCE-OF: R-41921-05214 The likelihood(X,Y) function returns
# argument X unchanged.
#
do_execsql_test func3-5.1 {
SELECT likelihood(9223372036854775807, 0.5);
} {9223372036854775807}
do_execsql_test func3-5.2 {
SELECT likelihood(-9223372036854775808, 0.5);
} {-9223372036854775808}
do_execsql_test func3-5.3 {
SELECT likelihood(14.125, 0.5);
} {14.125}
do_execsql_test func3-5.4 {
SELECT likelihood(NULL, 0.5);
} {{}}
do_execsql_test func3-5.5 {
SELECT likelihood('test-string', 0.5);
} {test-string}
do_execsql_test func3-5.6 {
SELECT quote(likelihood(x'010203000405', 0.5));
} {X'010203000405'}
# EVIDENCE-OF: R-44133-61651 The value Y in likelihood(X,Y) must be a
# floating point constant between 0.0 and 1.0, inclusive.
#
do_execsql_test func3-5.7 {
SELECT likelihood(123, 1.0), likelihood(456, 0.0);
} {123 456}
do_test func3-5.8 {
catchsql {
SELECT likelihood(123, 1.000001);
}
} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}}
do_test func3-5.9 {
catchsql {
SELECT likelihood(123, -0.000001);
}
} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}}
do_test func3-5.10 {
catchsql {
SELECT likelihood(123, 0.5+0.3);
}
} {1 {second argument to likelihood() must be a constant between 0.0 and 1.0}}
# EVIDENCE-OF: R-28535-44631 The likelihood(X) function is a no-op that
# the code generator optimizes away so that it consumes no CPU cycles
# during run-time (that is, during calls to sqlite3_step()).
#
do_test func3-5.20 {
db eval {EXPLAIN SELECT likelihood(min(1.0+'2.0',4*11), 0.5)}
} [db eval {EXPLAIN SELECT min(1.0+'2.0',4*11)}]
# EVIDENCE-OF: R-11152-23456 The unlikely(X) function returns the
# argument X unchanged.
#
do_execsql_test func3-5.30 {
SELECT unlikely(9223372036854775807);
} {9223372036854775807}
do_execsql_test func3-5.31 {
SELECT unlikely(-9223372036854775808);
} {-9223372036854775808}
do_execsql_test func3-5.32 {
SELECT unlikely(14.125);
} {14.125}
do_execsql_test func3-5.33 {
SELECT unlikely(NULL);
} {{}}
do_execsql_test func3-5.34 {
SELECT unlikely('test-string');
} {test-string}
do_execsql_test func3-5.35 {
SELECT quote(unlikely(x'010203000405'));
} {X'010203000405'}
# EVIDENCE-OF: R-22887-63324 The unlikely(X) function is a no-op that
# the code generator optimizes away so that it consumes no CPU cycles at
# run-time (that is, during calls to sqlite3_step()).
#
do_test func3-5.40 {
db eval {EXPLAIN SELECT unlikely(min(1.0+'2.0',4*11))}
} [db eval {EXPLAIN SELECT min(1.0+'2.0',4*11)}]
finish_test
+758
View File
@@ -0,0 +1,758 @@
# 2013 March 10
#
# 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 tointeger() and toreal() functions.
#
# Several of the toreal() tests are disabled on platforms where floating
# point precision is not high enough to represent their constant integer
# expression arguments as double precision floating point values.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set saved_tcl_precision $tcl_precision
set tcl_precision 0
load_static_extension db totype
set highPrecision(1) [expr \
{[db eval {SELECT tointeger(9223372036854775807 + 1);}] eq {{}}}]
do_execsql_test func4-1.1 {
SELECT tointeger(NULL);
} {{}}
do_execsql_test func4-1.2 {
SELECT tointeger('');
} {{}}
do_execsql_test func4-1.3 {
SELECT tointeger(' ');
} {{}}
do_execsql_test func4-1.4 {
SELECT tointeger('1234');
} {1234}
do_execsql_test func4-1.5 {
SELECT tointeger(' 1234');
} {{}}
do_execsql_test func4-1.6 {
SELECT tointeger('bad');
} {{}}
do_execsql_test func4-1.7 {
SELECT tointeger('0xBAD');
} {{}}
do_execsql_test func4-1.8 {
SELECT tointeger('123BAD');
} {{}}
do_execsql_test func4-1.9 {
SELECT tointeger('0x123BAD');
} {{}}
do_execsql_test func4-1.10 {
SELECT tointeger('123NO');
} {{}}
do_execsql_test func4-1.11 {
SELECT tointeger('0x123NO');
} {{}}
do_execsql_test func4-1.12 {
SELECT tointeger('-0x1');
} {{}}
do_execsql_test func4-1.13 {
SELECT tointeger('-0x0');
} {{}}
do_execsql_test func4-1.14 {
SELECT tointeger('0x0');
} {{}}
do_execsql_test func4-1.15 {
SELECT tointeger('0x1');
} {{}}
do_execsql_test func4-1.16 {
SELECT tointeger(-1);
} {-1}
do_execsql_test func4-1.17 {
SELECT tointeger(-0);
} {0}
do_execsql_test func4-1.18 {
SELECT tointeger(0);
} {0}
do_execsql_test func4-1.19 {
SELECT tointeger(1);
} {1}
do_execsql_test func4-1.20 {
SELECT tointeger(-1.79769313486232e308 - 1);
} {{}}
do_execsql_test func4-1.21 {
SELECT tointeger(-1.79769313486232e308);
} {{}}
do_execsql_test func4-1.22 {
SELECT tointeger(-1.79769313486232e308 + 1);
} {{}}
do_execsql_test func4-1.23 {
SELECT tointeger(-9223372036854775808 - 1);
} {-9223372036854775808}
do_execsql_test func4-1.24 {
SELECT tointeger(-9223372036854775808);
} {-9223372036854775808}
do_execsql_test func4-1.25 {
SELECT tointeger(-9223372036854775808 + 1);
} {-9223372036854775807}
do_execsql_test func4-1.26 {
SELECT tointeger(-9223372036854775807 - 1);
} {-9223372036854775808}
do_execsql_test func4-1.27 {
SELECT tointeger(-9223372036854775807);
} {-9223372036854775807}
do_execsql_test func4-1.28 {
SELECT tointeger(-9223372036854775807 + 1);
} {-9223372036854775806}
do_execsql_test func4-1.29 {
SELECT tointeger(-2147483648 - 1);
} {-2147483649}
do_execsql_test func4-1.30 {
SELECT tointeger(-2147483648);
} {-2147483648}
do_execsql_test func4-1.31 {
SELECT tointeger(-2147483648 + 1);
} {-2147483647}
do_execsql_test func4-1.32 {
SELECT tointeger(2147483647 - 1);
} {2147483646}
do_execsql_test func4-1.33 {
SELECT tointeger(2147483647);
} {2147483647}
do_execsql_test func4-1.34 {
SELECT tointeger(2147483647 + 1);
} {2147483648}
do_execsql_test func4-1.35 {
SELECT tointeger(9223372036854775807 - 1);
} {9223372036854775806}
do_execsql_test func4-1.36 {
SELECT tointeger(9223372036854775807);
} {9223372036854775807}
if {$highPrecision(1)} {
do_execsql_test func4-1.37 {
SELECT tointeger(9223372036854775807 + 1);
} {{}}
}
do_execsql_test func4-1.38 {
SELECT tointeger(1.79769313486232e308 - 1);
} {{}}
do_execsql_test func4-1.39 {
SELECT tointeger(1.79769313486232e308);
} {{}}
do_execsql_test func4-1.40 {
SELECT tointeger(1.79769313486232e308 + 1);
} {{}}
do_execsql_test func4-1.41 {
SELECT tointeger(4503599627370496 - 1);
} {4503599627370495}
do_execsql_test func4-1.42 {
SELECT tointeger(4503599627370496);
} {4503599627370496}
do_execsql_test func4-1.43 {
SELECT tointeger(4503599627370496 + 1);
} {4503599627370497}
do_execsql_test func4-1.44 {
SELECT tointeger(9007199254740992 - 1);
} {9007199254740991}
do_execsql_test func4-1.45 {
SELECT tointeger(9007199254740992);
} {9007199254740992}
do_execsql_test func4-1.46 {
SELECT tointeger(9007199254740992 + 1);
} {9007199254740993}
do_execsql_test func4-1.47 {
SELECT tointeger(9223372036854775807 - 1);
} {9223372036854775806}
do_execsql_test func4-1.48 {
SELECT tointeger(9223372036854775807);
} {9223372036854775807}
if {$highPrecision(1)} {
do_execsql_test func4-1.49 {
SELECT tointeger(9223372036854775807 + 1);
} {{}}
do_execsql_test func4-1.50 {
SELECT tointeger(9223372036854775808 - 1);
} {{}}
do_execsql_test func4-1.51 {
SELECT tointeger(9223372036854775808);
} {{}}
do_execsql_test func4-1.52 {
SELECT tointeger(9223372036854775808 + 1);
} {{}}
}
do_execsql_test func4-1.53 {
SELECT tointeger(18446744073709551616 - 1);
} {{}}
do_execsql_test func4-1.54 {
SELECT tointeger(18446744073709551616);
} {{}}
do_execsql_test func4-1.55 {
SELECT tointeger(18446744073709551616 + 1);
} {{}}
ifcapable floatingpoint {
set highPrecision(2) [expr \
{[db eval {SELECT toreal(-9223372036854775808 + 1);}] eq {{}}}]
do_execsql_test func4-2.1 {
SELECT toreal(NULL);
} {{}}
do_execsql_test func4-2.2 {
SELECT toreal('');
} {{}}
do_execsql_test func4-2.3 {
SELECT toreal(' ');
} {{}}
do_execsql_test func4-2.4 {
SELECT toreal('1234');
} {1234.0}
do_execsql_test func4-2.5 {
SELECT toreal(' 1234');
} {{}}
do_execsql_test func4-2.6 {
SELECT toreal('bad');
} {{}}
do_execsql_test func4-2.7 {
SELECT toreal('0xBAD');
} {{}}
do_execsql_test func4-2.8 {
SELECT toreal('123BAD');
} {{}}
do_execsql_test func4-2.9 {
SELECT toreal('0x123BAD');
} {{}}
do_execsql_test func4-2.10 {
SELECT toreal('123NO');
} {{}}
do_execsql_test func4-2.11 {
SELECT toreal('0x123NO');
} {{}}
do_execsql_test func4-2.12 {
SELECT toreal('-0x1');
} {{}}
do_execsql_test func4-2.13 {
SELECT toreal('-0x0');
} {{}}
do_execsql_test func4-2.14 {
SELECT toreal('0x0');
} {{}}
do_execsql_test func4-2.15 {
SELECT toreal('0x1');
} {{}}
do_execsql_test func4-2.16 {
SELECT toreal(-1);
} {-1.0}
do_execsql_test func4-2.17 {
SELECT toreal(-0);
} {0.0}
do_execsql_test func4-2.18 {
SELECT toreal(0);
} {0.0}
do_execsql_test func4-2.19 {
SELECT toreal(1);
} {1.0}
do_execsql_test func4-2.20 {
SELECT toreal(-1.79769313486232e308 - 1);
} {-Inf}
do_execsql_test func4-2.21 {
SELECT toreal(-1.79769313486232e308);
} {-Inf}
do_execsql_test func4-2.22 {
SELECT toreal(-1.79769313486232e308 + 1);
} {-Inf}
do_execsql_test func4-2.23 {
SELECT toreal(-9223372036854775808 - 1);
} {-9.223372036854776e+18}
do_execsql_test func4-2.24 {
SELECT toreal(-9223372036854775808);
} {-9.223372036854776e+18}
if {$highPrecision(2)} {
do_execsql_test func4-2.25 {
SELECT toreal(-9223372036854775808 + 1);
} {{}}
}
do_execsql_test func4-2.26 {
SELECT toreal(-9223372036854775807 - 1);
} {-9.223372036854776e+18}
if {$highPrecision(2)} {
do_execsql_test func4-2.27 {
SELECT toreal(-9223372036854775807);
} {{}}
do_execsql_test func4-2.28 {
SELECT toreal(-9223372036854775807 + 1);
} {{}}
}
do_execsql_test func4-2.29 {
SELECT toreal(-2147483648 - 1);
} {-2147483649.0}
do_execsql_test func4-2.30 {
SELECT toreal(-2147483648);
} {-2147483648.0}
do_execsql_test func4-2.31 {
SELECT toreal(-2147483648 + 1);
} {-2147483647.0}
do_execsql_test func4-2.32 {
SELECT toreal(2147483647 - 1);
} {2147483646.0}
do_execsql_test func4-2.33 {
SELECT toreal(2147483647);
} {2147483647.0}
do_execsql_test func4-2.34 {
SELECT toreal(2147483647 + 1);
} {2147483648.0}
if {$highPrecision(2)} {
do_execsql_test func4-2.35 {
SELECT toreal(9223372036854775807 - 1);
} {{}}
if {$highPrecision(1)} {
do_execsql_test func4-2.36 {
SELECT toreal(9223372036854775807);
} {{}}
}
}
do_execsql_test func4-2.37 {
SELECT toreal(9223372036854775807 + 1);
} {9.223372036854776e+18}
do_execsql_test func4-2.38 {
SELECT toreal(1.79769313486232e308 - 1);
} {Inf}
do_execsql_test func4-2.39 {
SELECT toreal(1.79769313486232e308);
} {Inf}
do_execsql_test func4-2.40 {
SELECT toreal(1.79769313486232e308 + 1);
} {Inf}
do_execsql_test func4-2.41 {
SELECT toreal(4503599627370496 - 1);
} {4503599627370495.0}
do_execsql_test func4-2.42 {
SELECT toreal(4503599627370496);
} {4503599627370496.0}
do_execsql_test func4-2.43 {
SELECT toreal(4503599627370496 + 1);
} {4503599627370497.0}
do_execsql_test func4-2.44 {
SELECT toreal(9007199254740992 - 1);
} {9007199254740991.0}
do_execsql_test func4-2.45 {
SELECT toreal(9007199254740992);
} {9007199254740992.0}
if {$highPrecision(2)} {
do_execsql_test func4-2.46 {
SELECT toreal(9007199254740992 + 1);
} {{}}
}
do_execsql_test func4-2.47 {
SELECT toreal(9007199254740992 + 2);
} {9007199254740994.0}
do_execsql_test func4-2.48 {
SELECT toreal(tointeger(9223372036854775808) - 1);
} {{}}
if {$highPrecision(1)} {
do_execsql_test func4-2.49 {
SELECT toreal(tointeger(9223372036854775808));
} {{}}
do_execsql_test func4-2.50 {
SELECT toreal(tointeger(9223372036854775808) + 1);
} {{}}
}
do_execsql_test func4-2.51 {
SELECT toreal(tointeger(18446744073709551616) - 1);
} {{}}
do_execsql_test func4-2.52 {
SELECT toreal(tointeger(18446744073709551616));
} {{}}
do_execsql_test func4-2.53 {
SELECT toreal(tointeger(18446744073709551616) + 1);
} {{}}
}
ifcapable check {
do_execsql_test func4-3.1 {
CREATE TABLE t1(
x INTEGER CHECK(tointeger(x) IS NOT NULL)
);
} {}
do_test func4-3.2 {
catchsql {
INSERT INTO t1 (x) VALUES (NULL);
}
} {1 {constraint failed}}
do_test func4-3.3 {
catchsql {
INSERT INTO t1 (x) VALUES (NULL);
}
} {1 {constraint failed}}
do_test func4-3.4 {
catchsql {
INSERT INTO t1 (x) VALUES ('');
}
} {1 {constraint failed}}
do_test func4-3.5 {
catchsql {
INSERT INTO t1 (x) VALUES ('bad');
}
} {1 {constraint failed}}
do_test func4-3.6 {
catchsql {
INSERT INTO t1 (x) VALUES ('1234bad');
}
} {1 {constraint failed}}
do_test func4-3.7 {
catchsql {
INSERT INTO t1 (x) VALUES ('1234.56bad');
}
} {1 {constraint failed}}
do_test func4-3.8 {
catchsql {
INSERT INTO t1 (x) VALUES (1234);
}
} {0 {}}
do_test func4-3.9 {
catchsql {
INSERT INTO t1 (x) VALUES (1234.56);
}
} {1 {constraint failed}}
do_test func4-3.10 {
catchsql {
INSERT INTO t1 (x) VALUES ('1234');
}
} {0 {}}
do_test func4-3.11 {
catchsql {
INSERT INTO t1 (x) VALUES ('1234.56');
}
} {1 {constraint failed}}
do_test func4-3.12 {
catchsql {
INSERT INTO t1 (x) VALUES (ZEROBLOB(4));
}
} {1 {constraint failed}}
do_test func4-3.13 {
catchsql {
INSERT INTO t1 (x) VALUES (X'');
}
} {1 {constraint failed}}
do_test func4-3.14 {
catchsql {
INSERT INTO t1 (x) VALUES (X'1234');
}
} {1 {constraint failed}}
do_test func4-3.15 {
catchsql {
INSERT INTO t1 (x) VALUES (X'12345678');
}
} {1 {constraint failed}}
do_test func4-3.16 {
catchsql {
INSERT INTO t1 (x) VALUES ('1234.00');
}
} {1 {constraint failed}}
do_test func4-3.17 {
catchsql {
INSERT INTO t1 (x) VALUES (1234.00);
}
} {0 {}}
do_test func4-3.18 {
catchsql {
INSERT INTO t1 (x) VALUES ('-9223372036854775809');
}
} {1 {constraint failed}}
if {$highPrecision(1)} {
do_test func4-3.19 {
catchsql {
INSERT INTO t1 (x) VALUES (9223372036854775808);
}
} {1 {constraint failed}}
}
do_execsql_test func4-3.20 {
SELECT x FROM t1 ORDER BY x;
} {1234 1234 1234}
ifcapable floatingpoint {
do_execsql_test func4-4.1 {
CREATE TABLE t2(
x REAL CHECK(toreal(x) IS NOT NULL)
);
} {}
do_test func4-4.2 {
catchsql {
INSERT INTO t2 (x) VALUES (NULL);
}
} {1 {constraint failed}}
do_test func4-4.3 {
catchsql {
INSERT INTO t2 (x) VALUES (NULL);
}
} {1 {constraint failed}}
do_test func4-4.4 {
catchsql {
INSERT INTO t2 (x) VALUES ('');
}
} {1 {constraint failed}}
do_test func4-4.5 {
catchsql {
INSERT INTO t2 (x) VALUES ('bad');
}
} {1 {constraint failed}}
do_test func4-4.6 {
catchsql {
INSERT INTO t2 (x) VALUES ('1234bad');
}
} {1 {constraint failed}}
do_test func4-4.7 {
catchsql {
INSERT INTO t2 (x) VALUES ('1234.56bad');
}
} {1 {constraint failed}}
do_test func4-4.8 {
catchsql {
INSERT INTO t2 (x) VALUES (1234);
}
} {0 {}}
do_test func4-4.9 {
catchsql {
INSERT INTO t2 (x) VALUES (1234.56);
}
} {0 {}}
do_test func4-4.10 {
catchsql {
INSERT INTO t2 (x) VALUES ('1234');
}
} {0 {}}
do_test func4-4.11 {
catchsql {
INSERT INTO t2 (x) VALUES ('1234.56');
}
} {0 {}}
do_test func4-4.12 {
catchsql {
INSERT INTO t2 (x) VALUES (ZEROBLOB(4));
}
} {1 {constraint failed}}
do_test func4-4.13 {
catchsql {
INSERT INTO t2 (x) VALUES (X'');
}
} {1 {constraint failed}}
do_test func4-4.14 {
catchsql {
INSERT INTO t2 (x) VALUES (X'1234');
}
} {1 {constraint failed}}
do_test func4-4.15 {
catchsql {
INSERT INTO t2 (x) VALUES (X'12345678');
}
} {1 {constraint failed}}
do_execsql_test func4-4.16 {
SELECT x FROM t2 ORDER BY x;
} {1234.0 1234.0 1234.56 1234.56}
}
}
ifcapable floatingpoint {
do_execsql_test func4-5.1 {
SELECT tointeger(toreal('1234'));
} {1234}
do_execsql_test func4-5.2 {
SELECT tointeger(toreal(-1));
} {-1}
do_execsql_test func4-5.3 {
SELECT tointeger(toreal(-0));
} {0}
do_execsql_test func4-5.4 {
SELECT tointeger(toreal(0));
} {0}
do_execsql_test func4-5.5 {
SELECT tointeger(toreal(1));
} {1}
do_execsql_test func4-5.6 {
SELECT tointeger(toreal(-9223372036854775808 - 1));
} {-9223372036854775808}
do_execsql_test func4-5.7 {
SELECT tointeger(toreal(-9223372036854775808));
} {-9223372036854775808}
if {$highPrecision(2)} {
do_execsql_test func4-5.8 {
SELECT tointeger(toreal(-9223372036854775808 + 1));
} {{}}
}
do_execsql_test func4-5.9 {
SELECT tointeger(toreal(-2147483648 - 1));
} {-2147483649}
do_execsql_test func4-5.10 {
SELECT tointeger(toreal(-2147483648));
} {-2147483648}
do_execsql_test func4-5.11 {
SELECT tointeger(toreal(-2147483648 + 1));
} {-2147483647}
do_execsql_test func4-5.12 {
SELECT tointeger(toreal(2147483647 - 1));
} {2147483646}
do_execsql_test func4-5.13 {
SELECT tointeger(toreal(2147483647));
} {2147483647}
do_execsql_test func4-5.14 {
SELECT tointeger(toreal(2147483647 + 1));
} {2147483648}
do_execsql_test func4-5.15 {
SELECT tointeger(toreal(9223372036854775807 - 1));
} {{}}
if {$highPrecision(1)} {
do_execsql_test func4-5.16 {
SELECT tointeger(toreal(9223372036854775807));
} {{}}
do_execsql_test func4-5.17 {
SELECT tointeger(toreal(9223372036854775807 + 1));
} {{}}
}
do_execsql_test func4-5.18 {
SELECT tointeger(toreal(4503599627370496 - 1));
} {4503599627370495}
do_execsql_test func4-5.19 {
SELECT tointeger(toreal(4503599627370496));
} {4503599627370496}
do_execsql_test func4-5.20 {
SELECT tointeger(toreal(4503599627370496 + 1));
} {4503599627370497}
do_execsql_test func4-5.21 {
SELECT tointeger(toreal(9007199254740992 - 1));
} {9007199254740991}
do_execsql_test func4-5.22 {
SELECT tointeger(toreal(9007199254740992));
} {9007199254740992}
if {$highPrecision(2)} {
do_execsql_test func4-5.23 {
SELECT tointeger(toreal(9007199254740992 + 1));
} {{}}
}
do_execsql_test func4-5.24 {
SELECT tointeger(toreal(9007199254740992 + 2));
} {9007199254740994}
if {$highPrecision(1)} {
do_execsql_test func4-5.25 {
SELECT tointeger(toreal(9223372036854775808 - 1));
} {{}}
do_execsql_test func4-5.26 {
SELECT tointeger(toreal(9223372036854775808));
} {{}}
do_execsql_test func4-5.27 {
SELECT tointeger(toreal(9223372036854775808 + 1));
} {{}}
}
do_execsql_test func4-5.28 {
SELECT tointeger(toreal(18446744073709551616 - 1));
} {{}}
do_execsql_test func4-5.29 {
SELECT tointeger(toreal(18446744073709551616));
} {{}}
do_execsql_test func4-5.30 {
SELECT tointeger(toreal(18446744073709551616 + 1));
} {{}}
}
for {set i 0} {$i < 10} {incr i} {
if {$i == 8} continue
do_execsql_test func4-6.1.$i.1 [subst {
SELECT tointeger(x'[string repeat 01 $i]');
}] {{}}
ifcapable floatingpoint {
do_execsql_test func4-6.1.$i.2 [subst {
SELECT toreal(x'[string repeat 01 $i]');
}] {{}}
}
}
do_execsql_test func4-6.2.1 {
SELECT tointeger(x'0102030405060708');
} {578437695752307201}
do_execsql_test func4-6.2.2 {
SELECT tointeger(x'0807060504030201');
} {72623859790382856}
ifcapable floatingpoint {
do_execsql_test func4-6.3.1 {
SELECT toreal(x'ffefffffffffffff');
} {-1.7976931348623157e+308}
do_execsql_test func4-6.3.2 {
SELECT toreal(x'8010000000000000');
} {-2.2250738585072014e-308}
do_execsql_test func4-6.3.3 {
SELECT toreal(x'c000000000000000');
} {-2.0}
do_execsql_test func4-6.3.4 {
SELECT toreal(x'bff0000000000000');
} {-1.0}
do_execsql_test func4-6.3.5 {
SELECT toreal(x'8000000000000000');
} {-0.0}
do_execsql_test func4-6.3.6 {
SELECT toreal(x'0000000000000000');
} {0.0}
do_execsql_test func4-6.3.7 {
SELECT toreal(x'3ff0000000000000');
} {1.0}
do_execsql_test func4-6.3.8 {
SELECT toreal(x'4000000000000000');
} {2.0}
do_execsql_test func4-6.3.9 {
SELECT toreal(x'0010000000000000');
} {2.2250738585072014e-308}
do_execsql_test func4-6.3.10 {
SELECT toreal(x'7fefffffffffffff');
} {1.7976931348623157e+308}
do_execsql_test func4-6.3.11 {
SELECT toreal(x'8000000000000001');
} {-5e-324}
do_execsql_test func4-6.3.12 {
SELECT toreal(x'800fffffffffffff');
} {-2.225073858507201e-308}
do_execsql_test func4-6.3.13 {
SELECT toreal(x'0000000000000001');
} {5e-324}
do_execsql_test func4-6.3.14 {
SELECT toreal(x'000fffffffffffff');
} {2.225073858507201e-308}
do_execsql_test func4-6.3.15 {
SELECT toreal(x'fff0000000000000');
} {-Inf}
do_execsql_test func4-6.3.16 {
SELECT toreal(x'7ff0000000000000');
} {Inf}
do_execsql_test func4-6.3.17 {
SELECT toreal(x'fff8000000000000');
} {{}}
do_execsql_test func4-6.3.18 {
SELECT toreal(x'fff0000000000001');
} {{}}
do_execsql_test func4-6.3.19 {
SELECT toreal(x'fff7ffffffffffff');
} {{}}
do_execsql_test func4-6.3.20 {
SELECT toreal(x'7ff0000000000001');
} {{}}
do_execsql_test func4-6.3.21 {
SELECT toreal(x'7ff7ffffffffffff');
} {{}}
do_execsql_test func4-6.3.22 {
SELECT toreal(x'fff8000000000001');
} {{}}
do_execsql_test func4-6.3.23 {
SELECT toreal(x'ffffffffffffffff');
} {{}}
do_execsql_test func4-6.3.24 {
SELECT toreal(x'7ff8000000000000');
} {{}}
do_execsql_test func4-6.3.25 {
SELECT toreal(x'7fffffffffffffff');
} {{}}
}
set tcl_precision $saved_tcl_precision
unset saved_tcl_precision
finish_test
+43 -2
View File
@@ -11,6 +11,11 @@
# This file implements regression tests for SQLite library. The
# focus of this file is testing the built-in INSTR() functions.
#
# EVIDENCE-OF: R-27549-59611 The instr(X,Y) function finds the first
# occurrence of string Y within string X and returns the number of prior
# characters plus 1, or 0 if Y is nowhere found within X.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -199,12 +204,48 @@ do_test instr-1.54 {
do_test instr-1.55 {
db eval {SELECT instr(x'78c3a4e282ac79','y');}
} {4}
do_test instr-1.56 {
# EVIDENCE-OF: R-46421-32541 Or, if X and Y are both BLOBs, then
# instr(X,Y) returns one more than the number bytes prior to the first
# occurrence of Y, or 0 if Y does not occur anywhere within X.
#
do_test instr-1.56.1 {
db eval {SELECT instr(x'78c3a4e282ac79',x'79');}
} {7}
do_test instr-1.57 {
do_test instr-1.56.2 {
db eval {SELECT instr(x'78c3a4e282ac79',x'7a');}
} {0}
do_test instr-1.56.3 {
db eval {SELECT instr(x'78c3a4e282ac79',x'78');}
} {1}
do_test instr-1.56.3 {
db eval {SELECT instr(x'78c3a4e282ac79',x'a4');}
} {3}
# EVIDENCE-OF: R-17329-35644 If both arguments X and Y to instr(X,Y) are
# non-NULL and are not BLOBs then both are interpreted as strings.
#
do_test instr-1.57.1 {
db eval {SELECT instr('xä€y',x'79');}
} {4}
do_test instr-1.57.2 {
db eval {SELECT instr('xä€y',x'a4');}
} {0}
do_test instr-1.57.3 {
db eval {SELECT instr(x'78c3a4e282ac79','y');}
} {4}
# EVIDENCE-OF: R-14708-27487 If either X or Y are NULL in instr(X,Y)
# then the result is NULL.
#
do_execsql_test instr-1.60 {
SELECT coalesce(instr(NULL,'abc'), 999);
} {999}
do_execsql_test instr-1.61 {
SELECT coalesce(instr('abc',NULL), 999);
} {999}
do_execsql_test instr-1.62 {
SELECT coalesce(instr(NULL,NULL), 999);
} {999}
finish_test
+11
View File
@@ -289,6 +289,17 @@ test_suite "queryplanner" -prefix "" -description {
where.test
}
test_suite "vfslog" -prefix "" -description {
"Vfslog" quick test suite. Like "veryquick" except does not omits
a few tests that do not work with a version 1 VFS. And the quota* tests,
which do not work with a VFS that uses the pVfs argument passed to
sqlite3_vfs methods.
} -files [
test_set $allquicktests -exclude *malloc* *ioerr* *fault* oserror.test \
pager1.test syscall.test sysfault.test tkt3457.test quota* superlock* \
wal* mmap*
]
lappend ::testsuitelist xxx
#-------------------------------------------------------------------------
# Define the coverage related test suites:
+3 -3
View File
@@ -574,7 +574,7 @@ ifcapable {foreignkey} {
execsql {
pragma index_list(t3);
}
} {/0 sqlite_autoindex_t3_1 1 \d+/}
} {0 sqlite_autoindex_t3_1 1}
}
ifcapable {!foreignkey} {
execsql {CREATE TABLE t3(a,b UNIQUE)}
@@ -647,7 +647,7 @@ do_test pragma-7.1.1 {
execsql {
pragma index_list(t3);
}
} {/0 t3i1 0 \d+ 1 sqlite_autoindex_t3_1 1 \d+/}
} {0 t3i1 0 1 sqlite_autoindex_t3_1 1}
do_test pragma-7.1.2 {
execsql {
pragma index_list(t3_bogus);
@@ -1661,7 +1661,7 @@ do_test 23.3 {
CREATE INDEX i3 ON t1(d,b,c);
}
db2 eval {PRAGMA index_list(t1)}
} {/0 i3 0 \d+ 1 i2 0 \d+ 2 i1 0 \d+/}
} {0 i3 0 1 i2 0 2 i1 0}
do_test 23.4 {
db eval {
ALTER TABLE t1 ADD COLUMN e;
+10
View File
@@ -119,6 +119,11 @@ ifcapable attach {
# Default setting of PRAGMA cache_spill is always ON
#
# EVIDENCE-OF: R-51036-62828 PRAGMA cache_spill; PRAGMA
# cache_spill=boolean;
#
# EVIDENCE-OF: R-23955-02765 Cache_spill is enabled by default
#
db close
delete_file test.db test.db-journal
delete_file test2.db test2.db-journal
@@ -155,6 +160,11 @@ do_execsql_test pragma2-4.3 {
PRAGMA cache_spill=ON;
} {}
sqlite3_release_memory
#
# EVIDENCE-OF: R-07634-40532 The cache_spill pragma enables or disables
# the ability of the pager to spill dirty cache pages to the database
# file in the middle of a transaction.
#
do_test pragma2-4.4 {
db eval {
BEGIN;
+1 -1
View File
@@ -542,7 +542,7 @@ do_test select1-6.9.7 {
set x [execsql2 {
SELECT * FROM test1 a, (select 5, 6) LIMIT 1
}]
regsub -all {subquery_[0-9a-fA-F]+_} $x {subquery} x
regsub -all {sq_[0-9a-fA-F_]+} $x {subquery} x
set x
} {a.f1 11 a.f2 22 sqlite_subquery.5 5 sqlite_subquery.6 6}
do_test select1-6.9.8 {
+3
View File
@@ -23,6 +23,9 @@ do_test shared7-1.1 {
sqlite3_enable_shared_cache
} {1}
# EVIDENCE-OF: R-05098-06501 In shared cache mode, attempting to attach
# the same database file more than once results in an error.
#
do_test shared7-1.2 {
db close
sqlite3 db test.db
+1 -1
View File
@@ -3458,7 +3458,7 @@ void print_stack_union(
break;
}
hash++;
if( hash>=arraysize ) hash = 0;
if( hash>=(unsigned)arraysize ) hash = 0;
}
if( types[hash]==0 ){
sp->dtnum = hash + 1;
+4
View File
@@ -172,6 +172,10 @@ set pragma_def {
FLAG: NeedSchema
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: stats
FLAG: NeedSchema
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
NAME: index_info
FLAG: NeedSchema
IF: !defined(SQLITE_OMIT_SCHEMA_PRAGMAS)
+2
View File
@@ -120,6 +120,7 @@ foreach hdr {
set available_hdr($hdr) 1
}
set available_hdr(sqliteInt.h) 0
set available_hdr(sqlite3.h) 0
# 78 stars used for comment formatting.
set s78 \
@@ -227,6 +228,7 @@ proc copy_file {filename} {
# inlining opportunities.
#
foreach file {
sqlite3.h
sqliteInt.h
global.c
+11 -1
View File
@@ -279,8 +279,18 @@ if {[string equal -nocase $packageFlavor WinRT]} then {
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 \"WinRT\", \"WinRT81\", or \"WP80\""
fail "unsupported package flavor, must be one of: WinRT WinRT81 WP80 Win32"
}
if {$argc >= 4} then {
+92
View File
@@ -0,0 +1,92 @@
/*
** 2013-10-01
**
** 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.
**
******************************************************************************
**
** Compute hash signatures for every page of a database file. This utility
** program is useful for analyzing the output logs generated by the
** ext/misc/vfslog.c extension.
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <stdlib.h>
/*
** Compute signature for a block of content.
**
** For blocks of 16 or fewer bytes, the signature is just a hex dump of
** the entire block.
**
** For blocks of more than 16 bytes, the signature is a hex dump of the
** first 8 bytes followed by a 64-bit has of the entire block.
*/
static void vlogSignature(unsigned char *p, int n, char *zCksum){
unsigned int s0 = 0, s1 = 0;
unsigned int *pI;
int i;
if( n<=16 ){
for(i=0; i<n; i++) sprintf(zCksum+i*2, "%02x", p[i]);
}else{
pI = (unsigned int*)p;
for(i=0; i<n-7; i+=8){
s0 += pI[0] + s1;
s1 += pI[1] + s0;
pI += 2;
}
for(i=0; i<8; i++) sprintf(zCksum+i*2, "%02x", p[i]);
sprintf(zCksum+i*2, "-%08x%08x", s0, s1);
}
}
/*
** Open a file. Find its page size. Read each page, and compute and
** display the page signature.
*/
static void computeSigs(const char *zFilename){
FILE *in = fopen(zFilename, "rb");
unsigned pgsz;
size_t got;
unsigned n;
unsigned char aBuf[50];
unsigned char aPage[65536];
if( in==0 ){
fprintf(stderr, "cannot open \"%s\"\n", zFilename);
return;
}
got = fread(aBuf, 1, sizeof(aBuf), in);
if( got!=sizeof(aBuf) ){
goto endComputeSigs;
}
pgsz = aBuf[16]*256 + aBuf[17];
if( pgsz==1 ) pgsz = 65536;
if( (pgsz & (pgsz-1))!=0 ){
fprintf(stderr, "invalid page size: %02x%02x\n", aBuf[16], aBuf[17]);
goto endComputeSigs;
}
rewind(in);
for(n=1; (got=fread(aPage, 1, pgsz, in))==pgsz; n++){
vlogSignature(aPage, pgsz, aBuf);
printf("%4d: %s\n", n, aBuf);
}
endComputeSigs:
fclose(in);
}
/*
** Find page signatures for all named files.
*/
int main(int argc, char **argv){
int i;
for(i=1; i<argc; i++) computeSigs(argv[i]);
return 0;
}
+2 -2
View File
@@ -9,9 +9,9 @@ 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 \
sqlite3.c
echo '********** No optimizations. ENABLE_STAT3. THREADSAFE=0 *******'
echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
-ansi -DSQLITE_ENABLE_STAT3 -DSQLITE_THREADSAFE=0 \
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
sqlite3.c
echo '********** Optimized -O3. Includes FTS4 and RTREE ************'
gcc -O3 -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \