Compare commits

..

31 Commits

Author SHA1 Message Date
dan c1e914cd85 Changes to make the multi-threaded sorter sort stably.
FossilOrigin-Name: 83a105c864247a02b723c84069055765bf373703
2014-03-29 19:48:15 +00:00
dan 853c4a7621 Fix a broken assert() in vdbesort.c.
FossilOrigin-Name: 18d1b402f2dbe78f1a1113bb356b710e348365ef
2014-03-29 10:01:58 +00:00
dan e7c84cc7e3 Fix a problem in vdbesort.c causing spurious SQLITE_NOMEM errors when using memsys3 or memsys5.
FossilOrigin-Name: a683c05f6250389e84b980b16559e162ba1a27c2
2014-03-29 09:34:45 +00:00
dan ff9fce4d60 Add the optimization to avoid some unnecessary calls to sqlite3VdbeRecordUnpack() added to the trunk by [707ea170b3].
FossilOrigin-Name: fc4d04e6b039ea5aeb47739e38c5926e63a4b01b
2014-03-29 06:27:35 +00:00
dan 2f17001521 Merge latest changes from orderby-planning branch.
FossilOrigin-Name: 4c7fb5423430f3b936befaa7c309f8e1968ee7d8
2014-03-28 19:18:16 +00:00
drh 7c8e9c78c8 Merge the latest changes from trunk.
FossilOrigin-Name: 3047a25f1c41e83f0b4772f7c36fbfec0f12dc7e
2014-03-28 18:35:39 +00:00
dan 6971952c65 Instead of allocating a single large buffer at the beginning of each sort operation, start with a small buffer and extend it using realloc() as required.
FossilOrigin-Name: 81987c8ceb64f051528a6ca42673821d9ab7c0ff
2014-03-27 19:25:02 +00:00
dan face087212 Use xFetch() to access temporary files in vdbesort.c. Use a single large allocation instead of many small allocations when accumulating records in vdbesort.c. This is an interim commit - it allocates a buffer the size of the page-cache every time data is sorted.
FossilOrigin-Name: f4ac1bf28c4ba395ccab8f1c9df72614a61095a7
2014-03-27 17:23:41 +00:00
drh bfa463696b Merge the latest trunk changes and the fix for the crash on a corrupt
database.

FossilOrigin-Name: 0b35346c32dba14963c85ec178f2b46aa2bbf6dc
2014-03-27 00:09:00 +00:00
drh 664eb14d8e Merge from trunk the fix for the crash on a corrupt database.
FossilOrigin-Name: 8cb2b02baa7ef9aa96319e977f0315328f944237
2014-03-26 19:45:01 +00:00
drh e6c7b09df6 Merge enhancements and fixes from trunk.
FossilOrigin-Name: e005f2d6dd9faf38cc8fdb9428b5aa6192a6adae
2014-03-25 18:29:12 +00:00
dan ab1dcc1a4b Fix a problem in the code added by [707ea170b3] causing vdbesort.c to sort unstably.
FossilOrigin-Name: d3e640afe611b6ae0b7f2cff5b00900d7e4d5ee3
2014-03-25 17:07:48 +00:00
dan 78d5843245 Remove the sequence values from sorter records used by ORDER BY as well.
FossilOrigin-Name: c3ae3697832a00d4d5758988a8766bdbb691e6b8
2014-03-25 15:04:07 +00:00
drh 3c863634ef Enable four sorting threads by default in the command-line shell.
FossilOrigin-Name: 1cab83577c814feb35b4fb91af0d52a9751d99bc
2014-03-25 14:12:16 +00:00
drh 5c2b314222 Merge all fixes and enhancements from trunk.
FossilOrigin-Name: b415dfb6cb0df0c69992ca2bb700c15664f158e6
2014-03-25 13:17:41 +00:00
dan dd23c6bfb4 Omit the sequence value from sorter records used by GROUP BY queries that cannot use an index.
FossilOrigin-Name: 3f90abddc31ac20739778c235a834c33f7057997
2014-03-24 20:19:07 +00:00
drh fd0a2f9756 Avoid unnecessary moving of content between registers during an ORDER BY.
FossilOrigin-Name: 4f472accf072d9cb64f209923924b26f21b13d27
2014-03-24 18:08:15 +00:00
dan 3f802ebce2 Remove an unnecessary temporary register allocation.
FossilOrigin-Name: 5d506743f541b022cde04a9606baa4680cdfd70b
2014-03-24 09:34:58 +00:00
drh 83553eefaf Remove a pointless OP_Once operation in ORDER BY clauses with LIMIT.
FossilOrigin-Name: e6c59d23316c83b318b1a94d9b28a5d321737fa5
2014-03-24 02:20:53 +00:00
drh 70f624c3a9 Further enhancements to geneverated VDBE code for ORDER BY.
FossilOrigin-Name: e7188fad87ec82d36a39b80ccaf8006bf45a9bcd
2014-03-24 01:43:50 +00:00
drh d345a66428 merge fixes from trunk
FossilOrigin-Name: faf7f9caf526ab33a6fdb9c89b45a0483510db21
2014-03-23 18:47:00 +00:00
drh f45f2326a2 Use only a single OP_MakeRecord instead of two when constructing entries
to go onto a sorter.

FossilOrigin-Name: d696cdedacd39075aa7fc407ab7c7e50f01d9f39
2014-03-23 17:45:03 +00:00
dan f87684189d Add an experimental multi-threaded capability to vdbesorter.c.
FossilOrigin-Name: ff0b5c851ba7d04d1836d7c6a3222713e7d8d357
2014-03-17 15:43:05 +00:00
dan c625ba7f4f Merge latest trunk changes into this branch.
FossilOrigin-Name: d17231b63d48c1f9c4dee109c90cec112e2f0fd4
2014-03-13 15:41:09 +00:00
drh 6ddecb753a Cherry-pick [555fc07]:
Changes to the thread routines to disable them when threading is turned
off using sqlite3_config().  Also merge all recent trunk changes.

FossilOrigin-Name: c92b0fe1371e7c20a5fbdf5fa96e30da14c40880
2012-08-21 17:36:44 +00:00
drh daa3ce4b08 Update the spellfix virtual table so that all OOM errors are reported out
to the application.

FossilOrigin-Name: c2cf498513c2633bd2b08372772eaa0f3b3ab25f
2012-08-21 13:08:15 +00:00
drh e22724ee54 Update the threads branch to include all the latest trunk changes.
FossilOrigin-Name: f4125771e21f1ca29d5442b5441dacfc06b8032b
2012-08-16 11:24:22 +00:00
mistachkin a806475f86 Add an assert() to help verify the return code from the Win32 thread wait function.
FossilOrigin-Name: ed3dc7a89f3416622fcd741ae5fba437929d06d6
2012-07-23 06:47:30 +00:00
mistachkin 572df3b1e4 Enhance implementation of the Win32 thread wait function.
FossilOrigin-Name: 049b04117353c3e163ffc87916cbe121403a2821
2012-07-23 02:00:38 +00:00
mistachkin da0e47109e Add Win32 support to the internal threads interface. Also, add several asserts and fix a few typos.
FossilOrigin-Name: 793195d37109c75eba84f7190c8fe0b8722f76f7
2012-07-21 22:49:08 +00:00
drh f51446a38c Add an internal interface that allows the code to take advantage of multiple
cores by pushing subcomputations off into separate threads.  The interface
is not currently used.

FossilOrigin-Name: 0e4d977a4a07d6de50acbf022c7dd947998b8d96
2012-07-21 19:40:42 +00:00
117 changed files with 3165 additions and 6383 deletions
+5 -5
View File
@@ -177,7 +177,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo tokenize.lo trigger.lo \
table.lo threads.lo tokenize.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
@@ -239,10 +239,8 @@ SRC = \
$(TOP)/src/os.c \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
@@ -263,6 +261,7 @@ SRC = \
$(TOP)/src/sqliteInt.h \
$(TOP)/src/sqliteLimit.h \
$(TOP)/src/table.c \
$(TOP)/src/threads.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/trigger.c \
@@ -459,8 +458,6 @@ HDR = \
opcodes.h \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
@@ -736,6 +733,9 @@ status.lo: $(TOP)/src/status.c $(HDR)
table.lo: $(TOP)/src/table.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/table.c
threads.lo: $(TOP)/src/threads.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/threads.c
tokenize.lo: $(TOP)/src/tokenize.c keywordhash.h $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/tokenize.c
+34 -106
View File
@@ -1,9 +1,6 @@
#
# nmake Makefile for SQLite
#
###############################################################################
############################## START OF OPTIONS ###############################
###############################################################################
# The toplevel directory of the source tree. This is the directory
# that contains this "Makefile.msc".
@@ -16,13 +13,6 @@ TOP = .
USE_AMALGAMATION = 1
!ENDIF
# Set this non-0 to use the library paths and other options necessary for
# Windows Phone 8.1.
#
!IFNDEF USE_WP81_OPTS
USE_WP81_OPTS = 0
!ENDIF
# Set this non-0 to split the SQLite amalgamation file into chunks to
# be used for debugging with Visual Studio.
#
@@ -126,25 +116,6 @@ DEBUG = 0
OPTIMIZATIONS = 2
!ENDIF
# These are the "standard" SQLite compilation options used when compiling for
# the Windows platform.
#
!IFNDEF OPT_FEATURE_FLAGS
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
!ENDIF
###############################################################################
############################### END OF OPTIONS ################################
###############################################################################
# This assumes that MSVC is always installed in 32-bit Program Files directory
# and sets the variable for use in locating other 32-bit installs accordingly.
#
PROGRAMFILES_X86 = $(VCINSTALLDIR)\..\..
PROGRAMFILES_X86 = $(PROGRAMFILES_X86:\\=\)
# Check for the predefined command macro CC. This should point to the compiler
# binary for the target platform. If it is not defined, simply define it to
# the legacy default value 'cl.exe'.
@@ -169,15 +140,6 @@ LD = link.exe
RC = rc.exe
!ENDIF
# Check for the MSVC runtime library path macro. Othertise, this value will
# default to the 'lib' directory underneath the MSVC installation directory.
#
!IFNDEF CRTLIBPATH
CRTLIBPATH = $(VCINSTALLDIR)\lib
!ENDIF
CRTLIBPATH = $(CRTLIBPATH:\\=\)
# Check for the command macro NCC. This should point to the compiler binary
# for the platform the compilation process is taking place on. If it is not
# defined, simply define it to have the same value as the CC macro. When
@@ -206,8 +168,8 @@ NCC = $(NCC:\\=\)
NCC = $(CC)
!ENDIF
# Check for the MSVC native runtime library path macro. Othertise,
# this value will default to the 'lib' directory underneath the MSVC
# Check for the MSVC runtime library path macro. Othertise, this
# value will default to the 'lib' directory underneath the MSVC
# installation directory.
#
!IFNDEF NCRTLIBPATH
@@ -344,6 +306,7 @@ TCC = $(TCC) -DSQLITE_ENABLE_IOTRACE
RCC = $(RCC) -DSQLITE_ENABLE_IOTRACE
!ENDIF
#
# Prevent warnings about "insecure" MSVC runtime library functions
# being used.
#
@@ -351,24 +314,28 @@ TCC = $(TCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
BCC = $(BCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
RCC = $(RCC) -D_CRT_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS
#
# Prevent warnings about "deprecated" POSIX functions being used.
#
TCC = $(TCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
BCC = $(BCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
RCC = $(RCC) -D_CRT_NONSTDC_NO_DEPRECATE -D_CRT_NONSTDC_NO_WARNINGS
#
# Use the SQLite debugging heap subsystem?
#
!IF $(MEMDEBUG)!=0
TCC = $(TCC) -DSQLITE_MEMDEBUG=1
RCC = $(RCC) -DSQLITE_MEMDEBUG=1
#
# Use native Win32 heap subsystem instead of malloc/free?
#
!ELSEIF $(WIN32HEAP)!=0
TCC = $(TCC) -DSQLITE_WIN32_MALLOC=1
RCC = $(RCC) -DSQLITE_WIN32_MALLOC=1
#
# Validate the heap on every call into the native Win32 heap subsystem?
#
!IF $(DEBUG)>2
@@ -463,25 +430,25 @@ RCC = $(RCC) -DSQLITE_TEMP_STORE=1
# The same set of OMIT and ENABLE flags should be passed to the
# LEMON parser generator and the mkkeywordhash tool as well.
# These are the required SQLite compilation options used when compiling for
# the Windows platform.
#
REQ_FEATURE_FLAGS = $(REQ_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
# BEGIN standard options
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
# END standard options
# Add the required and optional SQLite compilation options into the command
# lines used to invoke the MSVC code and resource compilers.
#
TCC = $(TCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS)
RCC = $(RCC) $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS)
# BEGIN required Windows option
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_MAX_TRIGGER_DEPTH=100
# END required Windows option
# Add in any optional parameters specified on the commane line, e.g.
# nmake /f Makefile.msc all "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1"
#
TCC = $(TCC) $(OPT_FEATURE_FLAGS)
RCC = $(RCC) $(OPT_FEATURE_FLAGS)
# Add in any optional parameters specified on the make commane line
# ie. make "OPTS=-DSQLITE_ENABLE_FOO=1 -DSQLITE_OMIT_FOO=1".
TCC = $(TCC) $(OPTS)
RCC = $(RCC) $(OPTS)
# If compiling for debugging, add some defines.
#
!IF $(DEBUG)>0
TCC = $(TCC) -D_DEBUG
BCC = $(BCC) -D_DEBUG
@@ -490,7 +457,6 @@ RCC = $(RCC) -D_DEBUG
# If optimizations are enabled or disabled (either implicitly or
# explicitly), add the necessary flags.
#
!IF $(DEBUG)>0 || $(OPTIMIZATIONS)==0
TCC = $(TCC) -Od
BCC = $(BCC) -Od
@@ -506,14 +472,12 @@ BCC = $(BCC) -O1
!ENDIF
# If symbols are enabled (or compiling for debugging), enable PDBs.
#
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
TCC = $(TCC) -Zi
BCC = $(BCC) -Zi
!ENDIF
# If ICU support is enabled, add the compiler options for it.
#
!IF $(USE_ICU)!=0
TCC = $(TCC) -DSQLITE_ENABLE_ICU=1
RCC = $(RCC) -DSQLITE_ENABLE_ICU=1
@@ -525,7 +489,6 @@ RCC = $(RCC) -I$(ICUINCDIR)
# Command line prefixes for compiling code, compiling resources,
# linking, etc.
#
LTCOMPILE = $(TCC) -Fo$@
LTRCOMPILE = $(RCC) -r
LTLIB = lib.exe
@@ -547,71 +510,36 @@ LTLIBOPTS = /MACHINE:$(PLATFORM)
!IF $(FOR_WINRT)!=0
LTLINKOPTS = $(LTLINKOPTS) /APPCONTAINER
!IF "$(VISUALSTUDIOVERSION)"=="12.0"
!IFNDEF STORELIBPATH
!IF "$(PLATFORM)"=="x86"
STORELIBPATH = $(CRTLIBPATH)\store
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store"
!ELSEIF "$(PLATFORM)"=="x64"
STORELIBPATH = $(CRTLIBPATH)\store\amd64
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store\amd64"
!ELSEIF "$(PLATFORM)"=="ARM"
STORELIBPATH = $(CRTLIBPATH)\store\arm
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store\arm"
!ELSE
STORELIBPATH = $(CRTLIBPATH)\store
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(VCINSTALLDIR)\lib\store"
!ENDIF
!ENDIF
STORELIBPATH = $(STORELIBPATH:\\=\)
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(STORELIBPATH)"
!ENDIF
!ENDIF
# When compiling for Windows Phone 8.1, an extra library path is
# required.
#
!IF $(USE_WP81_OPTS)!=0
!IFNDEF WP81LIBPATH
!IF "$(PLATFORM)"=="x86"
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
!ELSEIF "$(PLATFORM)"=="ARM"
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\ARM
!ELSE
WP81LIBPATH = $(PROGRAMFILES_X86)\Windows Phone Kits\8.1\lib\x86
!ENDIF
!ENDIF
!ENDIF
# When compiling for Windows Phone 8.1, some extra linker options
# are also required.
#
!IF $(USE_WP81_OPTS)!=0
!IFDEF WP81LIBPATH
LTLINKOPTS = $(LTLINKOPTS) "/LIBPATH:$(WP81LIBPATH)"
!ENDIF
LTLINKOPTS = $(LTLINKOPTS) /DYNAMICBASE
LTLINKOPTS = $(LTLINKOPTS) WindowsPhoneCore.lib RuntimeObject.lib PhoneAppModelHost.lib
LTLINKOPTS = $(LTLINKOPTS) /NODEFAULTLIB:kernel32.lib /NODEFAULTLIB:ole32.lib
!ENDIF
# If either debugging or symbols are enabled, enable PDBs.
#
!IF $(DEBUG)>0 || $(SYMBOLS)!=0
LDFLAGS = /DEBUG
!ENDIF
# Start with the Tcl related linker options.
#
!IF $(NO_TCL)==0
LTLIBPATHS = /LIBPATH:$(TCLLIBDIR)
LTLIBS = $(LIBTCL)
!ENDIF
# If ICU support is enabled, add the linker options for it.
#
!IF $(USE_ICU)!=0
LTLIBPATHS = $(LTLIBPATHS) /LIBPATH:$(ICULIBDIR)
LTLIBS = $(LTLIBS) $(LIBICU)
!ENDIF
# nawk compatible awk.
#
!IFNDEF NAWK
NAWK = gawk.exe
!ENDIF
@@ -636,7 +564,7 @@ LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo select.lo status.lo \
table.lo tokenize.lo trigger.lo \
table.lo threads.o tokenize.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
vdbetrace.lo wal.lo walker.lo where.lo utf.lo vtab.lo
@@ -709,10 +637,8 @@ SRC = \
$(TOP)\src\os.c \
$(TOP)\src\os.h \
$(TOP)\src\os_common.h \
$(TOP)\src\os_setup.h \
$(TOP)\src\os_unix.c \
$(TOP)\src\os_win.c \
$(TOP)\src\os_win.h \
$(TOP)\src\pager.c \
$(TOP)\src\pager.h \
$(TOP)\src\parse.y \
@@ -733,6 +659,7 @@ SRC = \
$(TOP)\src\sqliteInt.h \
$(TOP)\src\sqliteLimit.h \
$(TOP)\src\table.c \
$(TOP)\src\threads.c \
$(TOP)\src\tclsqlite.c \
$(TOP)\src\tokenize.c \
$(TOP)\src\trigger.c \
@@ -932,8 +859,6 @@ HDR = \
opcodes.h \
$(TOP)\src\os.h \
$(TOP)\src\os_common.h \
$(TOP)\src\os_setup.h \
$(TOP)\src\os_win.h \
$(TOP)\src\pager.h \
$(TOP)\src\pcache.h \
parse.h \
@@ -1030,7 +955,7 @@ lempar.c: $(TOP)\src\lempar.c
copy $(TOP)\src\lempar.c .
lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
$(BCC) -Daccess=_access -Fe$@ $(TOP)\tool\lemon.c /link $(NLTLIBPATHS)
# Rules to build individual *.lo files from generated *.c files. This
# applies to:
@@ -1215,6 +1140,9 @@ status.lo: $(TOP)\src\status.c $(HDR)
table.lo: $(TOP)\src\table.c $(HDR)
$(LTCOMPILE) -c $(TOP)\src\table.c
threads.lo: $(TOP)\src\threads.c $(HDR)
$(LTCOMPILE) -c $(TOP)\src\threads.c
tokenize.lo: $(TOP)\src\tokenize.c keywordhash.h $(HDR)
$(LTCOMPILE) -c $(TOP)\src\tokenize.c
@@ -1290,7 +1218,7 @@ parse.h: parse.c
parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\addopcodes.awk
del /Q parse.y parse.h parse.h.temp
copy $(TOP)\src\parse.y .
.\lemon.exe $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
.\lemon.exe $(OPT_FEATURE_FLAGS) $(OPTS) parse.y
move parse.h parse.h.temp
$(NAWK) -f $(TOP)\addopcodes.awk parse.h.temp > parse.h
@@ -1298,7 +1226,7 @@ sqlite3.h: $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > sqlite3.h
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
$(BCC) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLINKOPTS) $(NLTLIBPATHS)
$(BCC) -Fe$@ $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)\tool\mkkeywordhash.c /link $(NLTLIBPATHS)
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
.\mkkeywordhash.exe > keywordhash.h
@@ -1446,8 +1374,8 @@ clean:
del /Q *.lo *.ilk *.lib *.obj *.pdb sqlite3.exe libsqlite3.lib
del /Q *.cod *.da *.bb *.bbg gmon.out
del /Q sqlite3.h opcodes.c opcodes.h
del /Q lemon.* lempar.c parse.*
del /Q mkkeywordhash.* keywordhash.h
del /Q lemon.exe lempar.c parse.*
del /Q mkkeywordhash.exe keywordhash.h
del /Q notasharedlib.*
-rmdir /Q/S .deps
-rmdir /Q/S .libs
-4
View File
@@ -262,10 +262,8 @@ SRC = \
$(TOP)/src/os.c \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
@@ -418,8 +416,6 @@ HDR = \
opcodes.h \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
+4 -9
View File
@@ -1333,7 +1333,7 @@ static int fts3InitVtab(
p->bHasStat = isFts4;
p->bFts4 = isFts4;
p->bDescIdx = bDescIdx;
p->nAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->bAutoincrmerge = 0xff; /* 0xff means setting unknown */
p->zContentTbl = zContent;
p->zLanguageid = zLanguageid;
zContent = 0;
@@ -1376,9 +1376,7 @@ static int fts3InitVtab(
int n = (int)strlen(p->azColumn[iCol]);
for(i=0; i<nNotindexed; i++){
char *zNot = azNotindexed[i];
if( zNot && n==(int)strlen(zNot)
&& 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n)
){
if( zNot && 0==sqlite3_strnicmp(p->azColumn[iCol], zNot, n) ){
p->abNotindexed[iCol] = 1;
sqlite3_free(zNot);
azNotindexed[i] = 0;
@@ -3304,10 +3302,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
Fts3Table *p = (Fts3Table*)pVtab;
int rc = sqlite3Fts3PendingTermsFlush(p);
if( rc==SQLITE_OK
&& p->nLeafAdd>(nMinMerge/16)
&& p->nAutoincrmerge && p->nAutoincrmerge!=0xff
){
if( rc==SQLITE_OK && p->bAutoincrmerge==1 && p->nLeafAdd>(nMinMerge/16) ){
int mxLevel = 0; /* Maximum relative level value in db */
int A; /* Incr-merge parameter A */
@@ -3315,7 +3310,7 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
assert( rc==SQLITE_OK || mxLevel==0 );
A = p->nLeafAdd * mxLevel;
A += (A/2);
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, p->nAutoincrmerge);
if( A>(int)nMinMerge ) rc = sqlite3Fts3Incrmerge(p, A, 8);
}
sqlite3Fts3SegmentsClose(p);
return rc;
+2 -2
View File
@@ -210,13 +210,13 @@ struct Fts3Table {
sqlite3_tokenizer *pTokenizer; /* tokenizer for inserts and queries */
char *zContentTbl; /* content=xxx option, or NULL */
char *zLanguageid; /* languageid=xxx option, or NULL */
int nAutoincrmerge; /* Value configured by 'automerge' */
u8 bAutoincrmerge; /* True if automerge=1 */
u32 nLeafAdd; /* Number of leaf blocks added this trans */
/* Precompiled statements used by the implementation. Each of these
** statements is run and reset within a single virtual table API call.
*/
sqlite3_stmt *aStmt[40];
sqlite3_stmt *aStmt[37];
char *zReadExprlist;
char *zWriteExprlist;
+102 -105
View File
@@ -185,23 +185,40 @@ static int getNextToken(
int rc;
sqlite3_tokenizer_cursor *pCursor;
Fts3Expr *pRet = 0;
int i = 0;
int nConsumed = 0;
/* Set variable i to the maximum number of bytes of input to tokenize. */
for(i=0; i<n; i++){
if( sqlite3_fts3_enable_parentheses && (z[i]=='(' || z[i]==')') ) break;
if( z[i]=='*' || z[i]=='"' ) break;
}
*pnConsumed = i;
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, i, &pCursor);
rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor);
if( rc==SQLITE_OK ){
const char *zToken;
int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0;
int nByte; /* total space to allocate */
rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition);
if( rc==SQLITE_OK ){
if( (rc==SQLITE_OK || rc==SQLITE_DONE) && sqlite3_fts3_enable_parentheses ){
int i;
if( rc==SQLITE_DONE ) iStart = n;
for(i=0; i<iStart; i++){
if( z[i]=='(' ){
pParse->nNest++;
rc = fts3ExprParse(pParse, &z[i+1], n-i-1, &pRet, &nConsumed);
if( rc==SQLITE_OK && !pRet ){
rc = SQLITE_DONE;
}
nConsumed = (int)(i + 1 + nConsumed);
break;
}
if( z[i]==')' ){
rc = SQLITE_DONE;
pParse->nNest--;
nConsumed = i+1;
break;
}
}
}
if( nConsumed==0 && rc==SQLITE_OK ){
nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken;
pRet = (Fts3Expr *)fts3MallocZero(nByte);
if( !pRet ){
@@ -235,14 +252,13 @@ static int getNextToken(
}
}
*pnConsumed = iEnd;
}else if( i && rc==SQLITE_DONE ){
rc = SQLITE_OK;
nConsumed = iEnd;
}
pModule->xClose(pCursor);
}
*pnConsumed = nConsumed;
*ppExpr = pRet;
return rc;
}
@@ -492,21 +508,6 @@ static int getNextNode(
return getNextString(pParse, &zInput[1], ii-1, ppExpr);
}
if( sqlite3_fts3_enable_parentheses ){
if( *zInput=='(' ){
int nConsumed = 0;
pParse->nNest++;
rc = fts3ExprParse(pParse, zInput+1, nInput-1, ppExpr, &nConsumed);
if( rc==SQLITE_OK && !*ppExpr ){ rc = SQLITE_DONE; }
*pnConsumed = (int)(zInput - z) + 1 + nConsumed;
return rc;
}else if( *zInput==')' ){
pParse->nNest--;
*pnConsumed = (int)((zInput - z) + 1);
*ppExpr = 0;
return SQLITE_DONE;
}
}
/* If control flows to this point, this must be a regular token, or
** the end of the input. Read a regular token using the sqlite3_tokenizer
@@ -625,100 +626,96 @@ static int fts3ExprParse(
while( rc==SQLITE_OK ){
Fts3Expr *p = 0;
int nByte = 0;
rc = getNextNode(pParse, zIn, nIn, &p, &nByte);
assert( nByte>0 || (rc!=SQLITE_OK && p==0) );
if( rc==SQLITE_OK ){
if( p ){
int isPhrase;
int isPhrase;
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
if( !pNot ){
if( !sqlite3_fts3_enable_parentheses
&& p->eType==FTSQUERY_PHRASE && pParse->isNot
){
/* Create an implicit NOT operator. */
Fts3Expr *pNot = fts3MallocZero(sizeof(Fts3Expr));
if( !pNot ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pNot->eType = FTSQUERY_NOT;
pNot->pRight = p;
p->pParent = pNot;
if( pNotBranch ){
pNot->pLeft = pNotBranch;
pNotBranch->pParent = pNot;
}
pNotBranch = pNot;
p = pPrev;
}else{
int eType = p->eType;
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
/* The isRequirePhrase variable is set to true if a phrase or
** an expression contained in parenthesis is required. If a
** binary operator (AND, OR, NOT or NEAR) is encounted when
** isRequirePhrase is set, this is a syntax error.
*/
if( !isPhrase && isRequirePhrase ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
pAnd = fts3MallocZero(sizeof(Fts3Expr));
if( !pAnd ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pNot->eType = FTSQUERY_NOT;
pNot->pRight = p;
p->pParent = pNot;
if( pNotBranch ){
pNot->pLeft = pNotBranch;
pNotBranch->pParent = pNot;
}
pNotBranch = pNot;
p = pPrev;
}else{
int eType = p->eType;
isPhrase = (eType==FTSQUERY_PHRASE || p->pLeft);
pAnd->eType = FTSQUERY_AND;
insertBinaryOperator(&pRet, pPrev, pAnd);
pPrev = pAnd;
}
/* The isRequirePhrase variable is set to true if a phrase or
** an expression contained in parenthesis is required. If a
** binary operator (AND, OR, NOT or NEAR) is encounted when
** isRequirePhrase is set, this is a syntax error.
*/
if( !isPhrase && isRequirePhrase ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
if( isPhrase && !isRequirePhrase ){
/* Insert an implicit AND operator. */
Fts3Expr *pAnd;
assert( pRet && pPrev );
pAnd = fts3MallocZero(sizeof(Fts3Expr));
if( !pAnd ){
sqlite3Fts3ExprFree(p);
rc = SQLITE_NOMEM;
goto exprparse_out;
}
pAnd->eType = FTSQUERY_AND;
insertBinaryOperator(&pRet, pPrev, pAnd);
pPrev = pAnd;
}
/* This test catches attempts to make either operand of a NEAR
** operator something other than a phrase. For example, either of
** the following:
**
** (bracketed expression) NEAR phrase
** phrase NEAR (bracketed expression)
**
** Return an error in either case.
*/
if( pPrev && (
/* This test catches attempts to make either operand of a NEAR
** operator something other than a phrase. For example, either of
** the following:
**
** (bracketed expression) NEAR phrase
** phrase NEAR (bracketed expression)
**
** Return an error in either case.
*/
if( pPrev && (
(eType==FTSQUERY_NEAR && !isPhrase && pPrev->eType!=FTSQUERY_PHRASE)
|| (eType!=FTSQUERY_PHRASE && isPhrase && pPrev->eType==FTSQUERY_NEAR)
)){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
if( isPhrase ){
if( pRet ){
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
pPrev->pRight = p;
p->pParent = pPrev;
}else{
pRet = p;
}
}else{
insertBinaryOperator(&pRet, pPrev, p);
}
isRequirePhrase = !isPhrase;
)){
sqlite3Fts3ExprFree(p);
rc = SQLITE_ERROR;
goto exprparse_out;
}
pPrev = p;
if( isPhrase ){
if( pRet ){
assert( pPrev && pPrev->pLeft && pPrev->pRight==0 );
pPrev->pRight = p;
p->pParent = pPrev;
}else{
pRet = p;
}
}else{
insertBinaryOperator(&pRet, pPrev, p);
}
isRequirePhrase = !isPhrase;
}
assert( nByte>0 );
}
assert( rc!=SQLITE_OK || (nByte>0 && nByte<=nIn) );
nIn -= nByte;
zIn += nByte;
pPrev = p;
}
if( rc==SQLITE_DONE && pRet && isRequirePhrase ){
+35 -270
View File
@@ -193,7 +193,6 @@ struct SegmentWriter {
int nSize; /* Size of allocation at aData */
int nData; /* Bytes of data in aData */
char *aData; /* Pointer to block from malloc() */
i64 nLeafData; /* Number of bytes of leaf data written */
};
/*
@@ -269,10 +268,6 @@ struct SegmentNode {
#define SQL_SELECT_INDEXES 35
#define SQL_SELECT_MXLEVEL 36
#define SQL_SELECT_LEVEL_RANGE2 37
#define SQL_UPDATE_LEVEL_IDX 38
#define SQL_UPDATE_LEVEL 39
/*
** This function is used to obtain an SQLite prepared statement handle
** for the statement identified by the second argument. If successful,
@@ -374,18 +369,7 @@ static int fts3SqlStmt(
/* SQL_SELECT_MXLEVEL
** Return the largest relative level in the FTS index or indexes. */
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'",
/* Return segments in order from oldest to newest.*/
/* 37 */ "SELECT level, idx, end_block "
"FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ? "
"ORDER BY level DESC, idx ASC",
/* Update statements used while promoting segments */
/* 38 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=-1,idx=? "
"WHERE level=? AND idx=?",
/* 39 */ "UPDATE OR FAIL %Q.'%q_segdir' SET level=? WHERE level=-1"
/* 36 */ "SELECT max( level %% 1024 ) FROM %Q.'%q_segdir'"
};
int rc = SQLITE_OK;
sqlite3_stmt *pStmt;
@@ -1926,7 +1910,6 @@ static int fts3WriteSegdir(
sqlite3_int64 iStartBlock, /* Value for "start_block" field */
sqlite3_int64 iLeafEndBlock, /* Value for "leaves_end_block" field */
sqlite3_int64 iEndBlock, /* Value for "end_block" field */
sqlite3_int64 nLeafData, /* Bytes of leaf data in segment */
char *zRoot, /* Blob value for "root" field */
int nRoot /* Number of bytes in buffer zRoot */
){
@@ -1937,13 +1920,7 @@ static int fts3WriteSegdir(
sqlite3_bind_int(pStmt, 2, iIdx);
sqlite3_bind_int64(pStmt, 3, iStartBlock);
sqlite3_bind_int64(pStmt, 4, iLeafEndBlock);
if( nLeafData==0 ){
sqlite3_bind_int64(pStmt, 5, iEndBlock);
}else{
char *zEnd = sqlite3_mprintf("%lld %lld", iEndBlock, nLeafData);
if( !zEnd ) return SQLITE_NOMEM;
sqlite3_bind_text(pStmt, 5, zEnd, -1, sqlite3_free);
}
sqlite3_bind_int64(pStmt, 5, iEndBlock);
sqlite3_bind_blob(pStmt, 6, zRoot, nRoot, SQLITE_STATIC);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
@@ -2269,9 +2246,6 @@ static int fts3SegWriterAdd(
nDoclist; /* Doclist data */
}
/* Increase the total number of bytes written to account for the new entry. */
pWriter->nLeafData += nReq;
/* If the buffer currently allocated is too small for this entry, realloc
** the buffer to make it large enough.
*/
@@ -2343,13 +2317,13 @@ static int fts3SegWriterFlush(
pWriter->iFirst, pWriter->iFree, &iLast, &zRoot, &nRoot);
}
if( rc==SQLITE_OK ){
rc = fts3WriteSegdir(p, iLevel, iIdx,
pWriter->iFirst, iLastLeaf, iLast, pWriter->nLeafData, zRoot, nRoot);
rc = fts3WriteSegdir(
p, iLevel, iIdx, pWriter->iFirst, iLastLeaf, iLast, zRoot, nRoot);
}
}else{
/* The entire tree fits on the root node. Write it to the segdir table. */
rc = fts3WriteSegdir(p, iLevel, iIdx,
0, 0, 0, pWriter->nLeafData, pWriter->aData, pWriter->nData);
rc = fts3WriteSegdir(
p, iLevel, iIdx, 0, 0, 0, pWriter->aData, pWriter->nData);
}
p->nLeafAdd++;
return rc;
@@ -2433,37 +2407,6 @@ static int fts3SegmentMaxLevel(
return sqlite3_reset(pStmt);
}
/*
** iAbsLevel is an absolute level that may be assumed to exist within
** the database. This function checks if it is the largest level number
** within its index. Assuming no error occurs, *pbMax is set to 1 if
** iAbsLevel is indeed the largest level, or 0 otherwise, and SQLITE_OK
** is returned. If an error occurs, an error code is returned and the
** final value of *pbMax is undefined.
*/
static int fts3SegmentIsMaxLevel(Fts3Table *p, i64 iAbsLevel, int *pbMax){
/* Set pStmt to the compiled version of:
**
** SELECT max(level) FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?
**
** (1024 is actually the value of macro FTS3_SEGDIR_PREFIXLEVEL_STR).
*/
sqlite3_stmt *pStmt;
int rc = fts3SqlStmt(p, SQL_SELECT_SEGDIR_MAX_LEVEL, &pStmt, 0);
if( rc!=SQLITE_OK ) return rc;
sqlite3_bind_int64(pStmt, 1, iAbsLevel+1);
sqlite3_bind_int64(pStmt, 2,
((iAbsLevel/FTS3_SEGDIR_MAXLEVEL)+1) * FTS3_SEGDIR_MAXLEVEL
);
*pbMax = 0;
if( SQLITE_ROW==sqlite3_step(pStmt) ){
*pbMax = sqlite3_column_type(pStmt, 0)==SQLITE_NULL;
}
return sqlite3_reset(pStmt);
}
/*
** Delete all entries in the %_segments table associated with the segment
** opened with seg-reader pSeg. This function does not affect the contents
@@ -2999,140 +2942,6 @@ void sqlite3Fts3SegReaderFinish(
}
}
/*
** Decode the "end_block" field, selected by column iCol of the SELECT
** statement passed as the first argument.
**
** The "end_block" field may contain either an integer, or a text field
** containing the text representation of two non-negative integers separated
** by one or more space (0x20) characters. In the first case, set *piEndBlock
** to the integer value and *pnByte to zero before returning. In the second,
** set *piEndBlock to the first value and *pnByte to the second.
*/
static void fts3ReadEndBlockField(
sqlite3_stmt *pStmt,
int iCol,
i64 *piEndBlock,
i64 *pnByte
){
const unsigned char *zText = sqlite3_column_text(pStmt, iCol);
if( zText ){
int i;
int iMul = 1;
i64 iVal = 0;
for(i=0; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
*piEndBlock = iVal;
while( zText[i]==' ' ) i++;
iVal = 0;
if( zText[i]=='-' ){
i++;
iMul = -1;
}
for(/* no-op */; zText[i]>='0' && zText[i]<='9'; i++){
iVal = iVal*10 + (zText[i] - '0');
}
*pnByte = (iVal * (i64)iMul);
}
}
/*
** A segment of size nByte bytes has just been written to absolute level
** iAbsLevel. Promote any segments that should be promoted as a result.
*/
static int fts3PromoteSegments(
Fts3Table *p, /* FTS table handle */
sqlite3_int64 iAbsLevel, /* Absolute level just updated */
sqlite3_int64 nByte /* Size of new segment at iAbsLevel */
){
int rc = SQLITE_OK;
sqlite3_stmt *pRange;
rc = fts3SqlStmt(p, SQL_SELECT_LEVEL_RANGE2, &pRange, 0);
if( rc==SQLITE_OK ){
int bOk = 0;
i64 iLast = (iAbsLevel/FTS3_SEGDIR_MAXLEVEL + 1) * FTS3_SEGDIR_MAXLEVEL - 1;
i64 nLimit = (nByte*3)/2;
/* Loop through all entries in the %_segdir table corresponding to
** segments in this index on levels greater than iAbsLevel. If there is
** at least one such segment, and it is possible to determine that all
** such segments are smaller than nLimit bytes in size, they will be
** promoted to level iAbsLevel. */
sqlite3_bind_int64(pRange, 1, iAbsLevel+1);
sqlite3_bind_int64(pRange, 2, iLast);
while( SQLITE_ROW==sqlite3_step(pRange) ){
i64 nSize = 0, dummy;
fts3ReadEndBlockField(pRange, 2, &dummy, &nSize);
if( nSize<=0 || nSize>nLimit ){
/* If nSize==0, then the %_segdir.end_block field does not not
** contain a size value. This happens if it was written by an
** old version of FTS. In this case it is not possible to determine
** the size of the segment, and so segment promotion does not
** take place. */
bOk = 0;
break;
}
bOk = 1;
}
rc = sqlite3_reset(pRange);
if( bOk ){
int iIdx = 0;
sqlite3_stmt *pUpdate1;
sqlite3_stmt *pUpdate2;
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL_IDX, &pUpdate1, 0);
}
if( rc==SQLITE_OK ){
rc = fts3SqlStmt(p, SQL_UPDATE_LEVEL, &pUpdate2, 0);
}
if( rc==SQLITE_OK ){
/* Loop through all %_segdir entries for segments in this index with
** levels equal to or greater than iAbsLevel. As each entry is visited,
** updated it to set (level = -1) and (idx = N), where N is 0 for the
** oldest segment in the range, 1 for the next oldest, and so on.
**
** In other words, move all segments being promoted to level -1,
** setting the "idx" fields as appropriate to keep them in the same
** order. The contents of level -1 (which is never used, except
** transiently here), will be moved back to level iAbsLevel below. */
sqlite3_bind_int64(pRange, 1, iAbsLevel);
while( SQLITE_ROW==sqlite3_step(pRange) ){
sqlite3_bind_int(pUpdate1, 1, iIdx++);
sqlite3_bind_int(pUpdate1, 2, sqlite3_column_int(pRange, 0));
sqlite3_bind_int(pUpdate1, 3, sqlite3_column_int(pRange, 1));
sqlite3_step(pUpdate1);
rc = sqlite3_reset(pUpdate1);
if( rc!=SQLITE_OK ){
sqlite3_reset(pRange);
break;
}
}
}
if( rc==SQLITE_OK ){
rc = sqlite3_reset(pRange);
}
/* Move level -1 to level iAbsLevel */
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pUpdate2, 1, iAbsLevel);
sqlite3_step(pUpdate2);
rc = sqlite3_reset(pUpdate2);
}
}
}
return rc;
}
/*
** Merge all level iLevel segments in the database into a single
** iLevel+1 segment. Or, if iLevel<0, merge all segments into a
@@ -3157,7 +2966,6 @@ static int fts3SegmentMerge(
Fts3SegFilter filter; /* Segment term filter condition */
Fts3MultiSegReader csr; /* Cursor to iterate through level(s) */
int bIgnoreEmpty = 0; /* True to ignore empty segments */
i64 iMaxLevel = 0; /* Max level number for this index/langid */
assert( iLevel==FTS3_SEGCURSOR_ALL
|| iLevel==FTS3_SEGCURSOR_PENDING
@@ -3169,11 +2977,6 @@ static int fts3SegmentMerge(
rc = sqlite3Fts3SegReaderCursor(p, iLangid, iIndex, iLevel, 0, 0, 1, 0, &csr);
if( rc!=SQLITE_OK || csr.nSegment==0 ) goto finished;
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iMaxLevel);
if( rc!=SQLITE_OK ) goto finished;
}
if( iLevel==FTS3_SEGCURSOR_ALL ){
/* This call is to merge all segments in the database to a single
** segment. The level of the new segment is equal to the numerically
@@ -3183,21 +2986,21 @@ static int fts3SegmentMerge(
rc = SQLITE_DONE;
goto finished;
}
iNewLevel = iMaxLevel;
rc = fts3SegmentMaxLevel(p, iLangid, iIndex, &iNewLevel);
bIgnoreEmpty = 1;
}else if( iLevel==FTS3_SEGCURSOR_PENDING ){
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, 0);
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, 0, &iIdx);
}else{
/* This call is to merge all segments at level iLevel. find the next
** available segment index at level iLevel+1. The call to
** fts3AllocateSegdirIdx() will merge the segments at level iLevel+1 to
** a single iLevel+2 segment if necessary. */
assert( FTS3_SEGCURSOR_PENDING==-1 );
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
rc = fts3AllocateSegdirIdx(p, iLangid, iIndex, iLevel+1, &iIdx);
bIgnoreEmpty = (iLevel!=FTS3_SEGCURSOR_PENDING) && (iNewLevel>iMaxLevel);
iNewLevel = getAbsoluteLevel(p, iLangid, iIndex, iLevel+1);
}
if( rc!=SQLITE_OK ) goto finished;
assert( csr.nSegment>0 );
assert( iNewLevel>=getAbsoluteLevel(p, iLangid, iIndex, 0) );
assert( iNewLevel<getAbsoluteLevel(p, iLangid, iIndex,FTS3_SEGDIR_MAXLEVEL) );
@@ -3214,7 +3017,7 @@ static int fts3SegmentMerge(
csr.zTerm, csr.nTerm, csr.aDoclist, csr.nDoclist);
}
if( rc!=SQLITE_OK ) goto finished;
assert( pWriter || bIgnoreEmpty );
assert( pWriter );
if( iLevel!=FTS3_SEGCURSOR_PENDING ){
rc = fts3DeleteSegdir(
@@ -3222,14 +3025,7 @@ static int fts3SegmentMerge(
);
if( rc!=SQLITE_OK ) goto finished;
}
if( pWriter ){
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
if( rc==SQLITE_OK ){
if( iLevel==FTS3_SEGCURSOR_PENDING || iNewLevel<iMaxLevel ){
rc = fts3PromoteSegments(p, iNewLevel, pWriter->nLeafData);
}
}
}
rc = fts3SegWriterFlush(p, pWriter, iNewLevel, iIdx);
finished:
fts3SegWriterFree(pWriter);
@@ -3239,7 +3035,7 @@ static int fts3SegmentMerge(
/*
** Flush the contents of pendingTerms to level 0 segments.
** Flush the contents of pendingTerms to level 0 segments.
*/
int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
int rc = SQLITE_OK;
@@ -3255,19 +3051,14 @@ int sqlite3Fts3PendingTermsFlush(Fts3Table *p){
** estimate the number of leaf blocks of content to be written
*/
if( rc==SQLITE_OK && p->bHasStat
&& p->nAutoincrmerge==0xff && p->nLeafAdd>0
&& p->bAutoincrmerge==0xff && p->nLeafAdd>0
){
sqlite3_stmt *pStmt = 0;
rc = fts3SqlStmt(p, SQL_SELECT_STAT, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
rc = sqlite3_step(pStmt);
if( rc==SQLITE_ROW ){
p->nAutoincrmerge = sqlite3_column_int(pStmt, 0);
if( p->nAutoincrmerge==1 ) p->nAutoincrmerge = 8;
}else if( rc==SQLITE_DONE ){
p->nAutoincrmerge = 0;
}
p->bAutoincrmerge = (rc==SQLITE_ROW && sqlite3_column_int(pStmt, 0));
rc = sqlite3_reset(pStmt);
}
}
@@ -3635,8 +3426,6 @@ struct IncrmergeWriter {
int iIdx; /* Index of *output* segment in iAbsLevel+1 */
sqlite3_int64 iStart; /* Block number of first allocated block */
sqlite3_int64 iEnd; /* Block number of last allocated block */
sqlite3_int64 nLeafData; /* Bytes of leaf page data so far */
u8 bNoLeafData; /* If true, store 0 for segment size */
NodeWriter aNodeWriter[FTS_MAX_APPENDABLE_HEIGHT];
};
@@ -3975,8 +3764,8 @@ static int fts3IncrmergeAppend(
nSpace += sqlite3Fts3VarintLen(nDoclist) + nDoclist;
}
pWriter->nLeafData += nSpace;
blobGrowBuffer(&pLeaf->block, pLeaf->block.n + nSpace, &rc);
if( rc==SQLITE_OK ){
if( pLeaf->block.n==0 ){
pLeaf->block.n = 1;
@@ -4075,7 +3864,6 @@ static void fts3IncrmergeRelease(
pWriter->iStart, /* start_block */
pWriter->aNodeWriter[0].iBlock, /* leaves_end_block */
pWriter->iEnd, /* end_block */
(pWriter->bNoLeafData==0 ? pWriter->nLeafData : 0), /* end_block */
pRoot->block.a, pRoot->block.n /* root */
);
}
@@ -4177,11 +3965,7 @@ static int fts3IncrmergeLoad(
if( sqlite3_step(pSelect)==SQLITE_ROW ){
iStart = sqlite3_column_int64(pSelect, 1);
iLeafEnd = sqlite3_column_int64(pSelect, 2);
fts3ReadEndBlockField(pSelect, 3, &iEnd, &pWriter->nLeafData);
if( pWriter->nLeafData<0 ){
pWriter->nLeafData = pWriter->nLeafData * -1;
}
pWriter->bNoLeafData = (pWriter->nLeafData==0);
iEnd = sqlite3_column_int64(pSelect, 3);
nRoot = sqlite3_column_bytes(pSelect, 4);
aRoot = sqlite3_column_blob(pSelect, 4);
}else{
@@ -4782,11 +4566,11 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
/*
** Attempt an incremental merge that writes nMerge leaf blocks.
**
** Incremental merges happen nMin segments at a time. The segments
** to be merged are the nMin oldest segments (the ones with the smallest
** values for the _segdir.idx field) in the highest level that contains
** at least nMin segments. Multiple merges might occur in an attempt to
** write the quota of nMerge leaf blocks.
** Incremental merges happen nMin segments at a time. The two
** segments to be merged are the nMin oldest segments (the ones with
** the smallest indexes) in the highest level that contains at least
** nMin segments. Multiple merges might occur in an attempt to write the
** quota of nMerge leaf blocks.
*/
int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
int rc; /* Return code */
@@ -4811,7 +4595,6 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
const i64 nMod = FTS3_SEGDIR_MAXLEVEL * p->nIndex;
sqlite3_stmt *pFindLevel = 0; /* SQL used to determine iAbsLevel */
int bUseHint = 0; /* True if attempting to append */
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
/* Search the %_segdir table for the absolute level with the smallest
** relative level number that contains at least nMin segments, if any.
@@ -4865,19 +4648,6 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
** to start work on some other level. */
memset(pWriter, 0, nAlloc);
pFilter->flags = FTS3_SEGMENT_REQUIRE_POS;
if( rc==SQLITE_OK ){
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
assert( bUseHint==1 || bUseHint==0 );
if( iIdx==0 || (bUseHint && iIdx==1) ){
int bIgnore = 0;
rc = fts3SegmentIsMaxLevel(p, iAbsLevel+1, &bIgnore);
if( bIgnore ){
pFilter->flags |= FTS3_SEGMENT_IGNORE_EMPTY;
}
}
}
if( rc==SQLITE_OK ){
rc = fts3IncrmergeCsr(p, iAbsLevel, nSeg, pCsr);
}
@@ -4885,12 +4655,16 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
&& SQLITE_OK==(rc = sqlite3Fts3SegReaderStart(p, pCsr, pFilter))
&& SQLITE_ROW==(rc = sqlite3Fts3SegReaderStep(p, pCsr))
){
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
}else{
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
int iIdx = 0; /* Largest idx in level (iAbsLevel+1) */
rc = fts3IncrmergeOutputIdx(p, iAbsLevel, &iIdx);
if( rc==SQLITE_OK ){
if( bUseHint && iIdx>0 ){
const char *zKey = pCsr->zTerm;
int nKey = pCsr->nTerm;
rc = fts3IncrmergeLoad(p, iAbsLevel, iIdx-1, zKey, nKey, pWriter);
}else{
rc = fts3IncrmergeWriter(p, iAbsLevel, iIdx, pCsr, pWriter);
}
}
if( rc==SQLITE_OK && pWriter->nLeafEst ){
@@ -4912,13 +4686,7 @@ int sqlite3Fts3Incrmerge(Fts3Table *p, int nMerge, int nMin){
}
}
if( nSeg!=0 ){
pWriter->nLeafData = pWriter->nLeafData * -1;
}
fts3IncrmergeRelease(p, pWriter, &rc);
if( nSeg==0 && pWriter->bNoLeafData==0 ){
fts3PromoteSegments(p, iAbsLevel+1, pWriter->nLeafData);
}
}
sqlite3Fts3SegReaderFinish(pCsr);
@@ -5005,10 +4773,7 @@ static int fts3DoAutoincrmerge(
){
int rc = SQLITE_OK;
sqlite3_stmt *pStmt = 0;
p->nAutoincrmerge = fts3Getint(&zParam);
if( p->nAutoincrmerge==1 || p->nAutoincrmerge>FTS3_MERGE_COUNT ){
p->nAutoincrmerge = 8;
}
p->bAutoincrmerge = fts3Getint(&zParam)!=0;
if( !p->bHasStat ){
assert( p->bFts4==0 );
sqlite3Fts3CreateStatTable(&rc, p);
@@ -5017,7 +4782,7 @@ static int fts3DoAutoincrmerge(
rc = fts3SqlStmt(p, SQL_REPLACE_STAT, &pStmt, 0);
if( rc ) return rc;
sqlite3_bind_int(pStmt, 1, FTS_STAT_AUTOINCRMERGE);
sqlite3_bind_int(pStmt, 2, p->nAutoincrmerge);
sqlite3_bind_int(pStmt, 2, p->bAutoincrmerge);
sqlite3_step(pStmt);
rc = sqlite3_reset(pStmt);
return rc;
+726 -754
View File
File diff suppressed because it is too large Load Diff
+8 -11
View File
@@ -120,13 +120,12 @@ proc execsql_intout {sql} {
# Test that it is possible to open an existing database that contains
# r-tree tables.
#
do_execsql_test rtree-1.4.1a {
CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2);
INSERT INTO t1 VALUES(1, 5.0, 10.0);
SELECT substr(hex(data),1,40) FROM t1_node;
} {00000001000000000000000140A0000041200000}
do_execsql_test rtree-1.4.1b {
INSERT INTO t1 VALUES(2, 15.0, 20.0);
do_test rtree-1.4.1 {
execsql {
CREATE VIRTUAL TABLE t1 USING rtree(ii, x1, x2);
INSERT INTO t1 VALUES(1, 5.0, 10.0);
INSERT INTO t1 VALUES(2, 15.0, 20.0);
}
} {}
do_test rtree-1.4.2 {
db close
@@ -436,18 +435,16 @@ do_test rtree-11.2 {
# Test on-conflict clause handling.
#
db_delete_and_reopen
do_execsql_test 12.0.1 {
do_execsql_test 12.0 {
CREATE VIRTUAL TABLE t1 USING rtree_i32(idx, x1, x2, y1, y2);
INSERT INTO t1 VALUES(1, 1, 2, 3, 4);
SELECT substr(hex(data),1,56) FROM t1_node;
} {00000001000000000000000100000001000000020000000300000004}
do_execsql_test 12.0.2 {
INSERT INTO t1 VALUES(2, 2, 3, 4, 5);
INSERT INTO t1 VALUES(3, 3, 4, 5, 6);
CREATE TABLE source(idx, x1, x2, y1, y2);
INSERT INTO source VALUES(5, 8, 8, 8, 8);
INSERT INTO source VALUES(2, 7, 7, 7, 7);
}
db_save_and_close
foreach {tn sql_template testdata} {
+9 -9
View File
@@ -57,31 +57,31 @@ do_test rtree6-1.1 {
do_test rtree6-1.2 {
rtree_strategy {SELECT * FROM t1 WHERE x1>10}
} {E0}
} {Ea}
do_test rtree6-1.3 {
rtree_strategy {SELECT * FROM t1 WHERE x1<10}
} {C0}
} {Ca}
do_test rtree6-1.4 {
rtree_strategy {SELECT * FROM t1,t2 WHERE k=ii AND x1<10}
} {C0}
} {Ca}
do_test rtree6-1.5 {
rtree_strategy {SELECT * FROM t1,t2 WHERE k=+ii AND x1<10}
} {C0}
} {Ca}
do_eqp_test rtree6.2.1 {
SELECT * FROM t1,t2 WHERE k=+ii AND x1<10
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca}
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
do_eqp_test rtree6.2.2 {
SELECT * FROM t1,t2 WHERE k=ii AND x1<10
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:Ca}
0 1 1 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
@@ -95,7 +95,7 @@ do_eqp_test rtree6.2.3 {
do_eqp_test rtree6.2.4 {
SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10
} {
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:C0E1}
0 0 0 {SCAN TABLE t1 VIRTUAL TABLE INDEX 2:CaEb}
0 1 1 {SEARCH TABLE t2 USING AUTOMATIC COVERING INDEX (v=?)}
}
@@ -126,7 +126,7 @@ do_test rtree6.3.2 {
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
}
} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa}
do_test rtree6.3.3 {
rtree_strategy {
SELECT * FROM t3 WHERE
@@ -137,7 +137,7 @@ do_test rtree6.3.3 {
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND
x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5 AND x1>0.5
}
} {E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0E0}
} {EaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEaEa}
do_execsql_test rtree6-3.4 {
SELECT * FROM t3 WHERE x1>0.5 AND x1>0.8 AND x1>1.1
+1 -1
View File
@@ -41,7 +41,7 @@ ifcapable rtree_int_only {
INSERT INTO t1 VALUES(9223372036854775807, 150, 150, 400, 400);
SELECT rtreenode(2, data) FROM t1_node;
}
} {{{1073741824 0 0 100 100} {2147483646 0 0 200 200} {4294967296 0 0 300 300} {8589934592 20 20 150 150} {9223372036854775807 150 150 400 400}}}
} {{{1073741824 0.000000 0.000000 100.000000 100.000000} {2147483646 0.000000 0.000000 200.000000 200.000000} {4294967296 0.000000 0.000000 300.000000 300.000000} {8589934592 20.000000 20.000000 150.000000 150.000000} {9223372036854775807 150.000000 150.000000 400.000000 400.000000}}}
}
finish_test
+7 -6
View File
@@ -29,7 +29,7 @@ do_eqp_test 1.1 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 1 {SCAN TABLE t}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
}
do_eqp_test 1.2 {
@@ -37,7 +37,7 @@ do_eqp_test 1.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
}
do_eqp_test 1.3 {
@@ -45,7 +45,7 @@ do_eqp_test 1.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
}
do_eqp_test 1.5 {
@@ -82,7 +82,7 @@ do_eqp_test 2.1 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 1 {SCAN TABLE t}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
0 1 0 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
}
do_eqp_test 2.2 {
@@ -90,7 +90,7 @@ do_eqp_test 2.2 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND t.x<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
}
do_eqp_test 2.3 {
@@ -98,7 +98,7 @@ do_eqp_test 2.3 {
WHERE t.x>=min_x AND t.x<=max_x AND t.y>=min_y AND ?<=max_y
} {
0 0 0 {SCAN TABLE t}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:D3B2D1B0}
0 1 1 {SCAN TABLE r_tree VIRTUAL TABLE INDEX 2:DdBcDbBa}
}
do_eqp_test 2.5 {
@@ -271,3 +271,4 @@ ifcapable rtree {
finish_test
-129
View File
@@ -1,129 +0,0 @@
# 2010 August 28
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# This file contains tests for the r-tree module. Specifically, it tests
# that new-style custom r-tree queries (geometry callbacks) work.
#
if {![info exists testdir]} {
set testdir [file join [file dirname [info script]] .. .. test]
}
source $testdir/tester.tcl
ifcapable !rtree { finish_test ; return }
ifcapable rtree_int_only { finish_test; return }
#-------------------------------------------------------------------------
# Test the example 2d "circle" geometry callback.
#
register_circle_geom db
do_execsql_test rtreeE-1.1 {
PRAGMA page_size=512;
CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1);
/* A tight pattern of small boxes near 0,0 */
WITH RECURSIVE
x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
INSERT INTO rt1 SELECT x+5*y, x, x+2, y, y+2 FROM x, y;
/* A looser pattern of small boxes near 100, 0 */
WITH RECURSIVE
x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
INSERT INTO rt1 SELECT 100+x+5*y, x*3+100, x*3+102, y*3, y*3+2 FROM x, y;
/* A looser pattern of larger boxes near 0, 200 */
WITH RECURSIVE
x(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM x WHERE x<4),
y(y) AS (VALUES(0) UNION ALL SELECT y+1 FROM y WHERE y<4)
INSERT INTO rt1 SELECT 200+x+5*y, x*7, x*7+15, y*7+200, y*7+215 FROM x, y;
} {}
# Queries against each of the three clusters */
do_execsql_test rtreeE-1.1 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 0.0, 50.0, 3) ORDER BY id;
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24}
do_execsql_test rtreeE-1.2 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(100.0, 0.0, 50.0, 3) ORDER BY id;
} {100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124}
do_execsql_test rtreeE-1.3 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0.0, 200.0, 50.0, 3) ORDER BY id;
} {200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224}
# The Qcircle geometry function gives a lower score to larger leaf-nodes.
# This causes the 200s to sort before the 100s and the 0s to sort before
# last.
#
do_execsql_test rtreeE-1.4 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,3) AND id%100==0
} {200 100 0}
# Exclude odd rowids on a depth-first search
do_execsql_test rtreeE-1.5 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,4) ORDER BY +id
} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
# Exclude odd rowids on a breadth-first search.
do_execsql_test rtreeE-1.6 {
SELECT id FROM rt1 WHERE id MATCH Qcircle(0,0,1000,5) ORDER BY +id
} {0 2 4 6 8 10 12 14 16 18 20 22 24 100 102 104 106 108 110 112 114 116 118 120 122 124 200 202 204 206 208 210 212 214 216 218 220 222 224}
# Construct a large 2-D RTree with thousands of random entries.
#
do_test rtreeE-2.1 {
db eval {
CREATE TABLE t2(id,x0,x1,y0,y1);
CREATE VIRTUAL TABLE rt2 USING rtree(id,x0,x1,y0,y1);
BEGIN;
}
expr srand(0)
for {set i 1} {$i<=10000} {incr i} {
set dx [expr {int(rand()*40)+1}]
set dy [expr {int(rand()*40)+1}]
set x0 [expr {int(rand()*(10000 - $dx))}]
set x1 [expr {$x0+$dx}]
set y0 [expr {int(rand()*(10000 - $dy))}]
set y1 [expr {$y0+$dy}]
set id [expr {$i+10000}]
db eval {INSERT INTO t2 VALUES($id,$x0,$x1,$y0,$y1)}
}
db eval {
INSERT INTO rt2 SELECT * FROM t2;
COMMIT;
}
} {}
for {set i 1} {$i<=200} {incr i} {
set dx [expr {int(rand()*100)}]
set dy [expr {int(rand()*100)}]
set x0 [expr {int(rand()*(10000 - $dx))}]
set x1 [expr {$x0+$dx}]
set y0 [expr {int(rand()*(10000 - $dy))}]
set y1 [expr {$y0+$dy}]
set ans [db eval {SELECT id FROM t2 WHERE x1>=$x0 AND x0<=$x1 AND y1>=$y0 AND y0<=$y1 ORDER BY id}]
do_execsql_test rtreeE-2.2.$i {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ORDER BY id
} $ans
}
# Run query that have very deep priority queues
#
set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=5000 AND y1>=0 AND y0<=5000 ORDER BY id}]
do_execsql_test rtreeE-2.3 {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,5000,0,5000) ORDER BY id
} $ans
set ans [db eval {SELECT id FROM t2 WHERE x1>=0 AND x0<=10000 AND y1>=0 AND y0<=10000 ORDER BY id}]
do_execsql_test rtreeE-2.4 {
SELECT id FROM rt2 WHERE id MATCH breadthfirstsearch(0,10000,0,10000) ORDER BY id
} $ans
finish_test
+6 -61
View File
@@ -21,16 +21,6 @@ extern "C" {
#endif
typedef struct sqlite3_rtree_geometry sqlite3_rtree_geometry;
typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
/* The double-precision datatype used by RTree depends on the
** SQLITE_RTREE_INT_ONLY compile-time option.
*/
#ifdef SQLITE_RTREE_INT_ONLY
typedef sqlite3_int64 sqlite3_rtree_dbl;
#else
typedef double sqlite3_rtree_dbl;
#endif
/*
** Register a geometry callback named zGeom that can be used as part of an
@@ -41,7 +31,11 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
int sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
#ifdef SQLITE_RTREE_INT_ONLY
int (*xGeom)(sqlite3_rtree_geometry*, int n, sqlite3_int64 *a, int *pRes),
#else
int (*xGeom)(sqlite3_rtree_geometry*, int n, double *a, int *pRes),
#endif
void *pContext
);
@@ -53,60 +47,11 @@ int sqlite3_rtree_geometry_callback(
struct sqlite3_rtree_geometry {
void *pContext; /* Copy of pContext passed to s_r_g_c() */
int nParam; /* Size of array aParam[] */
sqlite3_rtree_dbl *aParam; /* Parameters passed to SQL geom function */
double *aParam; /* Parameters passed to SQL geom function */
void *pUser; /* Callback implementation user data */
void (*xDelUser)(void *); /* Called by SQLite to clean up pUser */
};
/*
** Register a 2nd-generation geometry callback named zScore that can be
** used as part of an R-Tree geometry query as follows:
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
int sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
void *pContext,
void (*xDestructor)(void*)
);
/*
** A pointer to a structure of the following type is passed as the
** argument to scored geometry callback registered using
** sqlite3_rtree_query_callback().
**
** Note that the first 5 fields of this structure are identical to
** sqlite3_rtree_geometry. This structure is a subclass of
** sqlite3_rtree_geometry.
*/
struct sqlite3_rtree_query_info {
void *pContext; /* pContext from when function registered */
int nParam; /* Number of function parameters */
sqlite3_rtree_dbl *aParam; /* value of function parameters */
void *pUser; /* callback can use this, if desired */
void (*xDelUser)(void*); /* function to free pUser */
sqlite3_rtree_dbl *aCoord; /* Coordinates of node or entry to check */
unsigned int *anQueue; /* Number of pending entries in the queue */
int nCoord; /* Number of coordinates */
int iLevel; /* Level of current node or entry */
int mxLevel; /* The largest iLevel value in the tree */
sqlite3_int64 iRowid; /* Rowid for current entry */
sqlite3_rtree_dbl rParentScore; /* Score of parent node */
int eParentWithin; /* Visibility of parent node */
int eWithin; /* OUT: Visiblity */
sqlite3_rtree_dbl rScore; /* OUT: Write the score here */
};
/*
** Allowed values for sqlite3_rtree_query.eWithin and .eParentWithin.
*/
#define NOT_WITHIN 0 /* Object completely outside of query region */
#define PARTLY_WITHIN 1 /* Object partially overlaps query region */
#define FULLY_WITHIN 2 /* Object fully contained within query region */
#ifdef __cplusplus
} /* end of the 'extern "C"' block */
+3 -7
View File
@@ -66,7 +66,7 @@ LIBOBJ+= vdbe.o parse.o \
notify.o opcodes.o os.o os_unix.o os_win.o \
pager.o pcache.o pcache1.o pragma.o prepare.o printf.o \
random.o resolve.o rowset.o rtree.o select.o status.o \
table.o tokenize.o trigger.o \
table.o threads.o tokenize.o trigger.o \
update.o util.o vacuum.o \
vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o vdbesort.o \
vdbetrace.o wal.o walker.o where.o utf.o vtab.o
@@ -121,10 +121,8 @@ SRC = \
$(TOP)/src/os.c \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_unix.c \
$(TOP)/src/os_win.c \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.c \
$(TOP)/src/pager.h \
$(TOP)/src/parse.y \
@@ -146,6 +144,7 @@ SRC = \
$(TOP)/src/sqliteLimit.h \
$(TOP)/src/table.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/src/threads.c \
$(TOP)/src/tokenize.c \
$(TOP)/src/trigger.c \
$(TOP)/src/utf.c \
@@ -210,7 +209,6 @@ SRC += \
$(TOP)/ext/icu/sqliteicu.h \
$(TOP)/ext/icu/icu.c
SRC += \
$(TOP)/ext/rtree/sqlite3rtree.h \
$(TOP)/ext/rtree/rtree.h \
$(TOP)/ext/rtree/rtree.c
@@ -342,8 +340,6 @@ HDR = \
opcodes.h \
$(TOP)/src/os.h \
$(TOP)/src/os_common.h \
$(TOP)/src/os_setup.h \
$(TOP)/src/os_win.h \
$(TOP)/src/pager.h \
$(TOP)/src/pcache.h \
parse.h \
@@ -481,7 +477,7 @@ parse.c: $(TOP)/src/parse.y lemon $(TOP)/addopcodes.awk
mv parse.h parse.h.temp
$(NAWK) -f $(TOP)/addopcodes.awk parse.h.temp >parse.h
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION $(TOP)/ext/rtree/sqlite3rtree.h
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
tclsh $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
+107 -120
View File
@@ -1,10 +1,10 @@
C Add\sextra\schecking\sof\sthe\sdatabase\sextended\serror\scode.
D 2014-05-30T16:54:09.869
C Changes\sto\smake\sthe\smulti-threaded\ssorter\ssort\sstably.
D 2014-03-29T19:48:15.410
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in dd2b1aba364ff9b05de41086f74407f285c57670
F Makefile.in ad0921c4b2780d01868cf69b419a4f102308d125
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F Makefile.msc 52911c6bfeaf9b40f47ef4615ab66d98ab0f2b3d
F Makefile.vxworks 034289efa9d591b04b1a73598623119c306cbba0
F Makefile.msc 153eb9b9725bc7b8e4dbe963219298e0c4a644b0
F Makefile.vxworks db21ed42a01d5740e656b16f92cb5d8d5e5dd315
F README.md 64f270c43c38c46de749e419c22f0ae2f4499fe8
F VERSION 9f823c026c6a32fc5f84d212a8aae0a221dba45c
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
@@ -78,11 +78,11 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
F ext/fts3/fts3.c 20bc65862cfcea0a39bb64a819f8fe92a8e144c1
F ext/fts3/fts3.c 41b1920b9a8657963f09cb93b208c2671c5568db
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 16cddf2d7b0e5f3681615ae1d8ca0e45fca44918
F ext/fts3/fts3Int.h bdeb9015405e8facffb8fc7e09174521a2a780f4
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F ext/fts3/fts3_expr.c 351395fad6fcb16ecfc61db0861008a70101330c
F ext/fts3/fts3_expr.c 5165c365cb5a035f5be8bb296f7aa3211d43e4ac
F ext/fts3/fts3_hash.c 29b986e43f4e9dd40110eafa377dc0d63c422c60
F ext/fts3/fts3_hash.h 39cf6874dc239d6b4e30479b1975fe5b22a3caaf
F ext/fts3/fts3_icu.c e319e108661147bcca8dd511cd562f33a1ba81b5
@@ -96,7 +96,7 @@ F ext/fts3/fts3_tokenizer.h 64c6ef6c5272c51ebe60fc607a896e84288fcbc3
F ext/fts3/fts3_tokenizer1.c 5c98225a53705e5ee34824087478cf477bdb7004
F ext/fts3/fts3_unicode.c 92391b4b4fb043564c6539ea9b8661e3bcba47b9
F ext/fts3/fts3_unicode2.c 0113d3acf13429e6dc38e0647d1bc71211c31a4d
F ext/fts3/fts3_write.c 5ee9d894da74a5d15a3c317414fb8c84f1694fa4
F ext/fts3/fts3_write.c 74c00329006c3ed6325ba4e5ab7c9b5fc99c8934
F ext/fts3/fts3speed.tcl b54caf6a18d38174f1a6e84219950d85e98bb1e9
F ext/fts3/mkfts3amal.tcl 252ecb7fe6467854f2aa237bf2c390b74e71f100
F ext/fts3/tool/fts3view.c 6cfc5b67a5f0e09c0d698f9fd012c784bfaa9197
@@ -120,31 +120,30 @@ F ext/misc/vfslog.c fe40fab5c077a40477f7e5eba994309ecac6cc95
F ext/misc/vtshim.c babb0dc2bf116029e3e7c9a618b8a1377045303e
F ext/misc/wholenumber.c 784b12543d60702ebdd47da936e278aa03076212
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
F ext/rtree/rtree.c 6f70db93e0e42c369325c5cddcf2024c5a87ca43
F ext/rtree/rtree.c 2d9f95da404d850474e628c720c5ce15d29b47de
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
F ext/rtree/rtree1.test e2da4aaa426918d27122d1a1066c6ecf8409a514
F ext/rtree/rtree1.test cf679265ecafff494a768ac9c2f43a70915a6290
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
F ext/rtree/rtree3.test a494da55c30ee0bc9b01a91c80c81b387b22d2dc
F ext/rtree/rtree4.test c8fe384f60ebd49540a5fecc990041bf452eb6e0
F ext/rtree/rtree5.test 6a510494f12454bf57ef28f45bc7764ea279431e
F ext/rtree/rtree6.test 756585abc51727fec97c77852476445c10c0ee95
F ext/rtree/rtree6.test fe0bd377a21c68ce2826129d14354c884cb1f354
F ext/rtree/rtree7.test 1fa710b9e6bf997a0c1a537b81be7bb6fded1971
F ext/rtree/rtree8.test db79c812f9e4a11f9b1f3f9934007884610a713a
F ext/rtree/rtree9.test d86ebf08ff6328895613ed577dd8a2a37c472c34
F ext/rtree/rtreeA.test ace05e729a36e342d40cf94e9efc7b4723d9dcdf
F ext/rtree/rtreeB.test c85f9ce78766c4e68b8b89fbf2979ee9cfa82b4e
F ext/rtree/rtreeC.test df158dcc81f1a43ce7eef361af03c48ec91f1e06
F ext/rtree/rtreeB.test 983e567b49b5dca165940f66b87e161aa30e82b2
F ext/rtree/rtreeC.test 16d7aa86ecb6a876d2a38cf590a1471a41b3a46d
F ext/rtree/rtreeD.test 636630357638f5983701550b37f0f5867130d2ca
F ext/rtree/rtreeE.test 388c1c8602c3ce55c15f03b509e9cf545fb7c41f
F ext/rtree/rtree_perf.tcl 6c18c1f23cd48e0f948930c98dfdd37dfccb5195
F ext/rtree/rtree_util.tcl 06aab2ed5b826545bf215fff90ecb9255a8647ea
F ext/rtree/sqlite3rtree.h 83349d519fe5f518b3ea025d18dd1fe51b1684bd
F ext/rtree/sqlite3rtree.h c34c1e41d1ab80bb8ad09aae402c9c956871a765
F ext/rtree/tkt3363.test 142ab96eded44a3615ec79fba98c7bde7d0f96de
F ext/rtree/viewrtree.tcl eea6224b3553599ae665b239bd827e182b466024
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
F magic.txt f439556c5ce01ced70987e5ee86549a45165d9ff
F main.mk cfa185eed4e0f7e9d28a2e3167cecaa9d6cb39f3
F main.mk 4b30dd2a6cb441db688972496b45a6c3abef8b20
F mkopcodec.awk c2ff431854d702cdd2d779c9c0d1f58fa16fa4ea
F mkopcodeh.awk c6b3fa301db6ef7ac916b14c60868aeaec1337b5
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
@@ -158,80 +157,78 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 3d8b83c91651f53472ca17599dae3457b8b89494
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c b00900877f766f116f9e16116f1ccacdc21d82f1
F src/analyze.c e8c8a9d20beb2ad156321330e8f4fea002d8deee
F src/alter.c 5d99edbac5bc416032772b723ee30182ee6e5de0
F src/analyze.c 663e0b291d27eb03c9fd6b421e2d61ba348a2389
F src/attach.c 3801129015ef59d76bf23c95ef9b0069d18a0c52
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c a729e63cf5cd1829507cb7b8e89f99b95141bb53
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 70c60a3807b2072982f184d9614e020d2953f89c
F src/btree.h 4245a349bfe09611d7ff887dbc3a80cee8b7955a
F src/btreeInt.h cf180d86b2e9e418f638d65baa425c4c69c0e0e3
F src/build.c 927e39b6aaf872c7b28f154f6acfeb9a05a72442
F src/btree.c a59a199f21338ae1847d69f5db87c3e8ef1b1578
F src/btree.h 232836cb51753f2e96aa8ce0f052c6df850f76ba
F src/btreeInt.h 0be66063468a520e4d66b80c7a1dc26d04ee6ea4
F src/build.c 0d50ef95aad63f4c4fc47f3fa2670d4557c45db0
F src/callback.c 174e3c8656bc29f91d710ab61550d16eea34be98
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c 0231df905e2c4abba4483ee18ffc05adc321df2a
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c bcf8f72126cea80fc3d5bc5494cf19b3f8935aaf
F src/expr.c 4f9e497c66e2f25a4d139357a778c84d5713207c
F src/delete.c cdd57149543bb28304d8f717c243f2a86b1fc280
F src/expr.c da2b3cb41081af6b56e95e7c9e95949564ce2e21
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c a549cff9fe8b736cdae21650ea0af6de29b77619
F src/func.c 2e16316ec3a6365a0dc3e553c586f91b20f7f6c8
F src/global.c 1e4bd956dc2f608f87d2a929abc4a20db65f30e4
F src/fkey.c 5269ef07b100763134f71b889327c333bd0989cf
F src/func.c 2945bb2c4cdc0ac43733046285a4434310be1811
F src/global.c 1d7bb7ea8254ae6a68ed9bfaf65fcb3d1690b486
F src/hash.c d139319967164f139c8d1bb8a11b14db9c4ba3cd
F src/hash.h 8890a25af81fb85a9ad7790d32eedab4b994da22
F src/hwtime.h d32741c8f4df852c7d959236615444e2b1063b08
F src/insert.c a038daeadfb818aaadafa854f40f5623b6929d84
F src/insert.c d8bb30535c8c0785876025a4a07f9074640a15d1
F src/journal.c b4124532212b6952f42eb2c12fa3c25701d8ba8d
F src/legacy.c 0df0b1550b9cc1f58229644735e317ac89131f12
F src/lempar.c cdf0a000315332fc9b50b62f3b5e22e080a0952b
F src/loadext.c 867c7b330b740c6c917af9956b13b81d0a048303
F src/main.c 40d0837e5d0597eadc47c3acc2fc95bdbd9250b8
F src/main.c 691b25754bef596108fe60ff1bcbe8445369c9db
F src/malloc.c 0203ebce9152c6a0e5de520140b8ba65187350be
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c c0c990fcaddff810ea277b4fb5d9138603dd5d4b
F src/mem2.c dce31758da87ec2cfa52ba4c5df1aed6e07d8e8f
F src/mem3.c 61c9d47b792908c532ca3a62b999cf21795c6534
F src/mem5.c 74670012946c4adc8a6ad84d03acc80959c3e529
F src/mem5.c aeb019f271ea53de83d651ec526877e6ba863450
F src/memjournal.c 0683aac6cab6ec2b5374c0db37c0deb2436a3785
F src/mutex.c d3b66a569368015e0fcb1ac15f81c119f504d3bc
F src/mutex.h 5bc526e19dccc412b7ff04642f6fdad3fdfdabea
F src/mutex_noop.c 7682796b7d8d39bf1c138248858efcd10c9e1553
F src/mutex_unix.c c3a4e00f96ba068a8dbef34084465979aaf369cc
F src/mutex_w32.c 9bcab6e699fdb20eae784237c36b299830fb3316
F src/mutex_w32.c 6108c88e1cb38d8fbb3534b170793815cbedbf97
F src/notify.c 976dd0f6171d4588e89e874fcc765e92914b6d30
F src/os.c 1b147e4cf7cc39e618115c14a086aed44bc91ace
F src/os.h 60d419395e32a8029fa380a80a3da2e9030f635e
F src/os.h 4a46270a64e9193af4a0aaa3bc2c66dc07c29b3f
F src/os_common.h 92815ed65f805560b66166e3583470ff94478f04
F src/os_setup.h c9d4553b5aaa6f73391448b265b89bed0b890faa
F src/os_unix.c ae4b5240af4619d711301d7992396e182585269f
F src/os_win.c 8dbf6c11780fe2eb96c1f289e664d0c7b2911d37
F src/os_win.h 057344a6720b4c8405d9bd98f58cb37a6ee46c25
F src/pager.c f6bb1fa6cdf2062f2d8aec3e64db302bca519ab8
F src/os_win.c 8245fe9184300e641d02e29a8ca95cefe0cb0fd0
F src/pager.c 97a8908bf4e6e7c3adea09d3597cfa48ae33ab4e
F src/pager.h ffd5607f7b3e4590b415b007a4382f693334d428
F src/parse.y 22d6a074e5f5a7258947a1dc55a9bf946b765dd0
F src/pcache.c d8eafac28290d4bb80332005435db44991d07fc2
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c 102e6f5a2fbc646154463eb856d1fd716867b64c
F src/pragma.c 810ef31ccfaa233201dcf100637a9777cc24e897
F src/pragma.c 10f169b9650f0930a7a6df67e1387a4c2c449f38
F src/prepare.c 677521ab7132615a8a26107a1d1c3132f44ae337
F src/printf.c e5a0005f8b3de21f85da6a709d2fbee76775bf4b
F src/random.c d10c1f85b6709ca97278428fd5db5bbb9c74eece
F src/resolve.c 273d5f47c4e2c05b2d3d2bffeda939551ab59e66
F src/rowset.c a9c9aae3234b44a6d7c6f5a3cadf90dce1e627be
F src/select.c 7df17ec5506c2427576d412bee0e6ea740e12563
F src/shell.c bfac06fb15f3cd0d447e2e72ab3a283fac301813
F src/sqlite.h.in a98eb3e8c86c934ea6f5bcfc6b69653dde2f4ed4
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 20055cf917222e660c4222fea306bd13a0623caa
F src/shell.c f48b63f8e582e7998ecefd051d697f91fb1453df
F src/sqlite.h.in a2ef671f92747a5a1c8a47bad5c585a8dd9eca80
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h fccdc735c27b3dc12322fec7cdad8bc76be8d00b
F src/sqliteInt.h 3f5190a4e07ca227035334da8d66ebe227071528
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/tclsqlite.c e87c99e28a145943666b51b212dacae35fcea0bd
F src/test1.c 4edf8810c86d77ae7ac6d56d563965a9beeea2ce
F src/test2.c 98049e51a17dc62606a99a9eb95ee477f9996712
F src/test1.c 2401eee14a4309a7cfe2aeb2f30ad517a1d9c299
F src/test2.c 7355101c085304b90024f2261e056cdff13c6c35
F src/test3.c 1c0e5d6f080b8e33c1ce8b3078e7013fdbcd560c
F src/test4.c 9b32d22f5f150abe23c1830e2057c4037c45b3df
F src/test5.c 5a34feec76d9b3a86aab30fd4f6cc9c48cbab4c1
@@ -242,8 +239,8 @@ F src/test9.c bea1e8cf52aa93695487badedd6e1886c321ea60
F src/test_async.c 21e11293a2f72080eda70e1124e9102044531cd8
F src/test_autoext.c dea8a01a7153b9adc97bd26161e4226329546e12
F src/test_backup.c 3875e899222b651e18b662f86e0e50daa946344e
F src/test_btree.c 2e9978eca99a9a4bfa8cae949efb00886860a64f
F src/test_config.c dabaa32868974e1ae39770cc17d7e066a9c38e6d
F src/test_btree.c 5b89601dcb42a33ba8b820a6b763cc9cb48bac16
F src/test_config.c 0336e0bdbe541b4af89d7e3dd0656e8e6b51e585
F src/test_demovfs.c 69b2085076654ebc18014cbc6386f04409c959a9
F src/test_devsym.c e7498904e72ba7491d142d5c83b476c4e76993bc
F src/test_fs.c ced436e3d4b8e4681328409b8081051ce614e28f
@@ -259,11 +256,11 @@ F src/test_multiplex.c 9f304bf04170c91c0318238d512df2da039eb1c8
F src/test_multiplex.h 110a8c4d356e0aa464ca8730375608a9a0b61ae1
F src/test_mutex.c 293042d623ebba969160f471a82aa1551626454f
F src/test_onefile.c 0396f220561f3b4eedc450cef26d40c593c69a25
F src/test_osinst.c 3d0340bc31a9f3d8a3547e0272373e80f78dde25
F src/test_osinst.c 90a845c8183013d80eccb1f29e8805608516edba
F src/test_pcache.c a5cd24730cb43c5b18629043314548c9169abb00
F src/test_quota.c 65f6348fec0f2b3020c907247fb47556b214abb9
F src/test_quota.h 2a8ad1952d1d2ca9af0ce0465e56e6c023b5e15d
F src/test_rtree.c fdd8d29ca5165c7857987a2ba263fac5c69e231f
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 a2615049954cbb9cfb4a62e18e2f0616e4dc38fe
F src/test_sqllog.c c1c1bbedbcaf82b93d83e4f9dd990e62476a680e
@@ -272,49 +269,50 @@ F src/test_superlock.c 2b97936ca127d13962c3605dbc9a4ef269c424cd
F src/test_syscall.c 2e21ca7f7dc54a028f1967b63f1e76155c356f9b
F src/test_tclvar.c f4dc67d5f780707210d6bb0eb6016a431c04c7fa
F src/test_thread.c 1e133a40b50e9c035b00174035b846e7eef481cb
F src/test_vfs.c f84075a388527892ff184988f43b69ce69b8083c
F src/test_vfstrace.c bab9594adc976cbe696ff3970728830b4c5ed698
F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 3a0ab304682fecbceb689e7d9b904211fde11d78
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/threads.c b96d62f88c06d4fa980a4a92685d1b130c4c84d3
F src/tokenize.c 6da2de6e12218ccb0aea5184b56727d011f4bee7
F src/trigger.c 66f3470b03b52b395e839155786966e3e037fddb
F src/update.c 01564b3c430f6c7b0a35afaf7aba7987206fa3a5
F src/update.c 5b3e74a03b3811e586b4f2b4cbd7c49f01c93115
F src/utf.c 6dc9ec9f1b3db43ae8ba0365377f11df1ee4c01c
F src/util.c 049fe1d3c0e2209c1bee107aec2fcff6285f909f
F src/util.c c46c90459ef9bdc0c6c73803cf4c55425b4771cf
F src/vacuum.c 3728d74919d4fb1356f9e9a13e27773db60b7179
F src/vdbe.c 9bfe6becfc094382ae213656fbe511055ad83a54
F src/vdbe.c 02f2de0b2f3b198438e3e64a2ceba9407bb8348b
F src/vdbe.h 394464909ed682334aa3d5831aae0c2fe2abef94
F src/vdbeInt.h e6d83e5bfd62fc6685ba1ed6153f7099f82de9f7
F src/vdbeapi.c 0ed6053f947edd0b30f64ce5aeb811872a3450a4
F src/vdbeaux.c e493f38758c4b8f4ca2007cf6a700bd405d192f3
F src/vdbeblob.c 9205ce9d3b064d9600f8418a897fc88b5687d9ac
F src/vdbeaux.c 1153175fb57a8454e1c8cf79b59b7bf92b26779d
F src/vdbeblob.c 15377abfb59251bccedd5a9c7d014a895f0c04aa
F src/vdbemem.c 6fc77594c60f6155404f3f8d71bf36d1fdeb4447
F src/vdbesort.c 44441d73b08b3a638dcdb725afffb87c6574ad27
F src/vdbesort.c d42a32a4fff1a1bac6033abc4252f93e6ef3282b
F src/vdbetrace.c 6f52bc0c51e144b7efdcfb2a8f771167a8816767
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 76e7fc6de229bea8b30bb2539110f03a494dc3a8
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c 11edb74d587bc87b33ca96a5173e3ec1b8389e45
F src/where.c b3be5eb4193b6327c4a02fe91411df503fe770e8
F src/whereInt.h 6804c2e5010378568c2bb1350477537755296a46
F src/where.c 7d539cedb1c6a6d6b5d2075b8fea3a48db4838eb
F src/whereInt.h 2564055b440e44ebec8b47f237bbccae6719b7af
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test 45c0201e28045ad38a530b5a144b73cd4aa2cfd6
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
F test/all.test 6ff7b43c2b4b905c74dc4a813d201d0fa64c5783
F test/alter.test 547dc2d292644301ac9a7dda22b319b74f9c08d2
F test/alter.test e88dfa77e020c2b48e52a8020c70171ab828e079
F test/alter2.test 7ea05c7d92ac99349a802ef7ada17294dd647060
F test/alter3.test 49c9d9fba2b8fcdce2dedeca97bbf1f369cc548d
F test/alter4.test d6c011fa0d6227abba762498cafbb607c9609e93
F test/altermalloc.test e81ac9657ed25c6c5bb09bebfa5a047cd8e4acfc
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
F test/analyze.test 1772936d66471c65221e437b6d1999c3a03166c4
F test/analyze3.test bf41f0f680dd1e0d44eed5e769531e93a5320275
F test/analyze3.test 412f690dfe95b337475e3e78a84a85d25f6f125d
F test/analyze4.test eff2df19b8dd84529966420f29ea52edc6b56213
F test/analyze5.test 765c4e284aa69ca172772aa940946f55629bc8c4
F test/analyze6.test d31defa011a561b938b4608d3538c1b4e0b5e92c
F test/analyze7.test bb1409afc9e8629e414387ef048b8e0e3e0bdc4f
F test/analyze8.test 093d15c1c888eed5034304a98c992f7360130b88
F test/analyze9.test 623e02a99a78fa12fe5def2fd559032d5d887e0f
F test/analyze9.test e072a5172d55afcba98d6ca6a219ce8878c2f5c9
F test/analyzeA.test 1a5c40079894847976d983ca39c707aaa44b6944
F test/analyzeB.test 8bf35ee0a548aea831bf56762cb8e7fdb1db083d
F test/async.test 1d0e056ba1bb9729283a0f22718d3a25e82c277b
@@ -332,11 +330,11 @@ F test/auth.test 5bdf154eb28c0e4bbc0473f335858c0d96171768
F test/auth2.test c3b415b76c033bedb81292118fb7c01f5f10cbcd
F test/auth3.test a4755e6a2a2fea547ffe63c874eb569e60a28eb5
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
F test/autoindex1.test 762ff3f8e25d852aae55c6462ca166a80c0cde61
F test/autoindex1.test d4dfe14001dfcb74cfbd7107f45a79fc1ab6183e
F test/autovacuum.test 941892505d2c0f410a0cb5970dfa1c7c4e5f6e74
F test/autovacuum_ioerr2.test 8a367b224183ad801e0e24dcb7d1501f45f244b4
F test/avtrans.test 0252654f4295ddda3b2cce0e894812259e655a85
F test/backcompat.test 19a1f337c68419b020a7481dd272a472c4ad8ef4
F test/backcompat.test 5f8ad58b3eaebc78cd2c66c65476a42e6f32b2ad
F test/backup.test c9cdd23a495864b9edf75a9fa66f5cb7e10fcf62
F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
F test/backup4.test 2a2e4a64388090b152de753fd9e123f28f6a3bd4
@@ -409,7 +407,6 @@ F test/corruptF.test be9fde98e4c93648f1ba52b74e5318edc8f59fe4
F test/corruptG.test 1ab3bf97ee7bdba70e0ff3ba2320657df55d1804
F test/corruptH.test 88ed71a086e13591c917aac6de32750e7c7281cb
F test/corruptI.test b3e4203d420490fc3d3062711597bc1dea06a789
F test/cost.test 04842adec34311d70c3f3c5fd698b22be54138fd
F test/count.test 42a251178e32f617eda33f76236a7f79825a50b5
F test/coveridxscan.test cdb47d01acc4a634a34fd25abe85189e0d0f1e62
F test/crash.test fb9dc4a02dcba30d4aa5c2c226f98b220b2b959f
@@ -437,12 +434,12 @@ F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
F test/diskfull.test 106391384780753ea6896b7b4f005d10e9866b6e
F test/distinct.test 086e70c765f172e8974e9f83b9ac5ca03c154e77
F test/distinctagg.test 1a6ef9c87a58669438fc771450d7a72577417376
F test/e_createtable.test ed82efcedc4b3656b27a5fcd12335cdb7e20eeee
F test/e_createtable.test ee95d48664503d40f6cc9ef4a7d03216188e2ada
F test/e_delete.test d5186e2f5478b659f16a2c8b66c09892823e542a
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
F test/e_expr.test 5c71d183fbf519a4769fd2e2124afdc70b5b1f42
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
F test/e_fkey.test 630597377549af579d34faaf64c6959a5a68ef76
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
F test/e_insert.test 1e44f84d2abe44d66e4fbf198be4b20e3cc724a0
F test/e_reindex.test 396b7b4f0a66863b4e95116a67d93b227193e589
@@ -456,7 +453,7 @@ F test/enc.test e54531cd6bf941ee6760be041dff19a104c7acea
F test/enc2.test 83437a79ba1545a55fb549309175c683fb334473
F test/enc3.test 90683ad0e6ea587b9d5542ca93568af9a9858c40
F test/enc4.test c8f1ce3618508fd0909945beb8b8831feef2c020
F test/eqp.test 85873fa5816c48915c82c4e74cb5c35a5b48160f
F test/eqp.test 57c6c604c2807fb5531731c5323133453c24afac
F test/errmsg.test f31592a594b44ee121371d25ddd5d63497bb3401
F test/eval.test bc269c365ba877554948441e91ad5373f9f91be3
F test/exclusive.test c7ebbc756eacf544c108b15eed64d7d4e5f86b75
@@ -539,16 +536,15 @@ F test/fts3conf.test ee8500c86dd58ec075e8831a1e216a79989436de
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
F test/fts3d.test 95c17d1b67b33a5eac0bf5a0d11116a0c0ac7a3a
F test/fts3d.test 597b0b76e41f0d672e2731c4d7b631d628efd13f
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
F test/fts3defer2.test e880e3b65bdf999f4746cdaefa65f14a98b9b724
F test/fts3defer2.test a3b6cbeabaf28c9398652a4d101ea224d9358479
F test/fts3defer3.test dd53fc13223c6d8264a98244e9b19abd35ed71cd
F test/fts3drop.test 1b906e293d6773812587b3dc458cb9e8f3f0c297
F test/fts3e.test 1f6c6ac9cc8b772ca256e6b22aaeed50c9350851
F test/fts3expr.test 3401d47b229c4504424caf362cc4ff704cad4162
F test/fts3expr.test 06f1a96facc8f3e4b1ad5cc001dc5c8e83e68b9f
F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
F test/fts3expr3.test 9e91b8edbcb197bf2e92161aa7696446d96dce5f
F test/fts3expr4.test 0713d94ab951ed88a8c3629a4889a48c55c4067c
F test/fts3fault.test cb72dccb0a3b9f730f16c5240f3fcb9303eb1660
F test/fts3fault2.test 3198eef2804deea7cac8403e771d9cbcb752d887
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
@@ -570,24 +566,22 @@ F test/fts4aa.test 0c3152322c7f0b548cc942ad763eaba0da87ccca
F test/fts4check.test 66fa274cab2b615f2fb338b257713aba8fad88a8
F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
F test/fts4incr.test 361960ed3550e781f3f313e17e2182ef9cefc0e9
F test/fts4langid.test 24a6e41063b416bbdf371ff6b4476fa41c194aa7
F test/fts4merge.test c424309743fdd203f8e56a1f1cd7872cd66cc0ee
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
F test/fts4merge3.test aab02a09f50fe6baaddc2e159c3eabc116d45fc7
F test/fts4merge4.test d895b1057a7798b67e03455d0fa50e9ea836c47b
F test/fts4noti.test 9695c7c6c32480ea9fc20a2b38ed1de0640bcaec
F test/fts4merge4.test c19c85ca1faa7b6d536832b49c12e1867235f584
F test/fts4noti.test aed33ba44808852dcb24bf70fa132e7bf530f057
F test/fts4unicode.test 01ec3fe2a7c3cfff3b4c0581b83caa11b33efa36
F test/full.test 6b3c8fb43c6beab6b95438c1675374b95fab245d
F test/func.test ae97561957aba6ca9e3a7b8a13aac41830d701ef
F test/func.test a21814945d32137412b553d98ad2107f9b2173a9
F test/func2.test 772d66227e4e6684b86053302e2d74a2500e1e0f
F test/func3.test dbccee9133cfef1473c59ec07b5f0262b9d72f9a
F test/func4.test 6beacdfcb0e18c358e6c2dcacf1b65d1fa80955f
F test/func5.test cdd224400bc3e48d891827cc913a57051a426fa4
F test/fuzz-oss1.test 4912e528ec9cf2f42134456933659d371c9e0d74
F test/fuzz.test 96083052bf5765e4518c1ba686ce2bab785670d1
F test/fuzz.test 77fd50afc12847af50fcf1941679d90adebadde6
F test/fuzz2.test 207d0f9d06db3eaf47a6b7bfc835b8e2fc397167
F test/fuzz3.test efd384b896c647b61a2c1848ba70d42aad60a7b3
F test/fuzz_common.tcl a87dfbb88c2a6b08a38e9a070dabd129e617b45b
@@ -617,12 +611,12 @@ F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test 55a90cff99834305e8141df7afaef39674b57062
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
F test/index5.test fc07c14193c0430814e7a08b5da46888ee795c33
F test/index6.test fb370966ac3cd0989053dd5385757b5c3e24ab6a
F test/index6.test 936979c3a1e87b81feaed2d00505665bf142d764
F test/index7.test a3baf9a625bda7fd49471e99aeae04095fbfeecf
F test/indexedby.test b2f22f3e693a53813aa3f50b812eb609ba6df1ec
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
F test/insert.test acf909b067b838eb55338d619e800e148c17f1f5
F test/insert2.test 4f3a04d168c728ed5ec2c88842e772606c7ce435
F test/insert3.test 1b7db95a03ad9c5013fdf7d6722b6cd66ee55e30
F test/insert4.test 4791662c50518bdd37d394cae9a7a8014e845bb3
@@ -700,7 +694,7 @@ F test/minmax.test 42fbad0e81afaa6e0de41c960329f2b2c3526efd
F test/minmax2.test b44bae787fc7b227597b01b0ca5575c7cb54d3bc
F test/minmax3.test cc1e8b010136db0d01a6f2a29ba5a9f321034354
F test/minmax4.test 536a3360470633a177e42fbc19660d146b51daef
F test/misc1.test 1201a037c24f982cc0e956cdaa34fcaf6439c417
F test/misc1.test 441a0fafc7087f841db09fbfca54e7aea9f5a84c
F test/misc2.test 00d7de54eda90e237fc9a38b9e5ccc769ebf6d4d
F test/misc3.test cf3dda47d5dda3e53fc5804a100d3c82be736c9d
F test/misc4.test 9c078510fbfff05a9869a0b6d8b86a623ad2c4f6
@@ -718,7 +712,6 @@ F test/multiplex3.test d228f59eac91839a977eac19f21d053f03e4d101
F test/mutex1.test 78b2b9bb320e51d156c4efdb71b99b051e7a4b41
F test/mutex2.test bfeaeac2e73095b2ac32285d2756e3a65e681660
F test/nan.test e9648b9d007c7045242af35e11a984d4b169443a
F test/nolock.test 0540dd96f39b8876e3ffdd8814fad0ea425efeee
F test/notify1.test 669b2b743618efdc18ca4b02f45423d5d2304abf
F test/notify2.test ce23eb522c9e1fff6443f96376fe67872202061c
F test/notify3.test 10ff25cde502e72a92053a2f215d64bece4ef934
@@ -730,9 +723,8 @@ F test/orderby1.test 9b524aff9147288da43a6d7ddfdcff47fa2303c6
F test/orderby2.test bc11009f7cd99d96b1b11e57b199b00633eb5b04
F test/orderby3.test 8619d06a3debdcd80a27c0fdea5c40b468854b99
F test/orderby4.test 4d39bfbaaa3ae64d026ca2ff166353d2edca4ba4
F test/orderby5.test 8f08a54836d21fb7c70245360751aedd1c2286fb
F test/orderby5.test 2490183fef54417209d1df253633a605d46bd350
F test/orderby6.test 8b38138ab0972588240b3fca0985d2e400432859
F test/orderby7.test 3d1383d52ade5b9eb3a173b3147fdd296f0202da
F test/oserror.test 50417780d0e0d7cd23cf12a8277bb44024765df3
F test/pager1.test 1acbdb14c5952a72dd43129cabdbf69aaa3ed1fa
F test/pager2.test 67b8f40ae98112bcdba1f2b2d03ea83266418c71
@@ -746,7 +738,7 @@ F test/pagesize.test 1dd51367e752e742f58e861e65ed7390603827a0
F test/pcache.test b09104b03160aca0d968d99e8cd2c5b1921a993d
F test/pcache2.test a83efe2dec0d392f814bfc998def1d1833942025
F test/percentile.test b98fc868d71eb5619d42a1702e9ab91718cbed54
F test/permutations.test d8946218493c77806ec1029df473d8ed4ad9aef6
F test/permutations.test 40add071ba71aefe1c04f5845308cf46f7de8d04
F test/pragma.test adb21a90875bc54a880fa939c4d7c46598905aa0
F test/pragma2.test aea7b3d82c76034a2df2b38a13745172ddc0bc13
F test/printf.test ec9870c4dce8686a37818e0bf1aba6e6a1863552
@@ -761,7 +753,7 @@ F test/quota2.test 7dc12e08b11cbc4c16c9ba2aa2e040ea8d8ab4b8
F test/quote.test 215897dbe8de1a6f701265836d6601cc6ed103e6
F test/randexpr1.tcl 40dec52119ed3a2b8b2a773bce24b63a3a746459
F test/randexpr1.test eda062a97e60f9c38ae8d806b03b0ddf23d796df
F test/rdonly.test dd30a4858d8e0fbad2304c2bd74a33d4df36412a
F test/rdonly.test c267d050a1d9a6a321de502b737daf28821a518d
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
F test/releasetest.mk 2eced2f9ae701fd0a29e714a241760503ccba25a
@@ -795,7 +787,7 @@ F test/select6.test e76bd10a56988f15726c097a5d5a7966fe82d3b2
F test/select7.test 7fd2ef598cfabb6b9ff6ac13973b91d0527df49d
F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
F test/select9.test aebc2bb0c3bc44606125033cbcaac2c8d1f33a95
F test/selectA.test 64b88a80271c1710966e50e633380696b60a12a4
F test/selectA.test 77adaffe9704cb80e301ebaeff4b107b58d435c5
F test/selectB.test 954e4e49cf1f896d61794e440669e03a27ceea25
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
F test/selectD.test b0f02a04ef7737decb24e08be2c39b9664b43394
@@ -817,16 +809,15 @@ F test/shell1.test f2a1d471e5cd2b42f7a65b166dc1ace2b8d11583
F test/shell2.test c57da3a381c099b02c813ba156298d5c2f5c93a3
F test/shell3.test 5e8545ec72c4413a0e8d4c6be56496e3c257ca29
F test/shell4.test aa4eef8118b412d1a01477a53426ece169ea86a9
F test/shell5.test fa5583230c0aea5c9ff33f0ac1e26b1e3f03d153
F test/shell5.test bb755ea9144b8078a752fc56223582627070b5f1
F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
F test/shrink.test 8c70f62b6e8eb4d54533de6d65bd06b1b9a17868
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
F test/skipscan1.test 28c7faa41a0d7265040ecb0a0abd90c0904270b2
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
F test/skipscan1.test bed8cbe9d554c8c27afb6c88500f704c86a9196f
F test/skipscan2.test 5a4db0799c338ddbacb154aaa5589c0254b36a8d
F test/soak.test 0b5b6375c9f4110c828070b826b3b4b0bb65cd5f
F test/softheap1.test 40562fe6cac6d9827b7b42b86d45aedf12c15e24
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
F test/sort.test 79dc647c4e9b123a64e57b7080b7f9a2df43f87a
F test/speed1.test f2974a91d79f58507ada01864c0e323093065452
F test/speed1p.explain d841e650a04728b39e6740296b852dccdca9b2cb
F test/speed1p.test b180e98609c7677382cf618c0ec9b69f789033a8
@@ -835,7 +826,7 @@ F test/speed3.test d32043614c08c53eafdc80f33191d5bd9b920523
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
F test/speedtest1.c d29c8048beb7ea9254191f3fde9414709166a920
F test/speedtest1.c 90446861e566a9965a8d005381a3c964ff333646
F test/spellfix.test 61309f5efbec53603b3f86457d34a504f80abafe
F test/sqllimits1.test b1aae27cc98eceb845e7f7adf918561256e31298
F test/stat.test 76fd746b85459e812a0193410fb599f0531f22de
@@ -855,7 +846,7 @@ F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
F test/temptable.test d2c9b87a54147161bcd1822e30c1d1cd891e5b30
F test/temptrigger.test 8ec228b0db5d7ebc4ee9b458fc28cb9e7873f5e1
F test/tester.tcl f31bea1483ea1d39620f982130026e76f872d744
F test/tester.tcl bc0889a2f86d9c17307992ca1e70391794780265
F test/thread001.test 9f22fd3525a307ff42a326b6bc7b0465be1745a5
F test/thread002.test e630504f8a06c00bf8bbe68528774dd96aeb2e58
F test/thread003.test ee4c9efc3b86a6a2767516a37bd64251272560a7
@@ -906,7 +897,6 @@ F test/tkt-a8a0d2996a.test eb597379dbcefa24765763d7f682c00cb5924fa9
F test/tkt-b1d3a2e531.test 8f7576e41ca179289ee1a8fee28386fd8e4b0550
F test/tkt-b351d95f9.test d14a503c414c5c58fdde3e80f9a3cfef986498c0
F test/tkt-b72787b1.test a95e8cdad0b98af1853ac7f0afd4ab27b77bf5f3
F test/tkt-b75a9ca6b0.test 97cc2d5eeaf82799eb42138c0a1ff64370238ce4
F test/tkt-bd484a090c.test 60460bf946f79a79712b71f202eda501ca99b898
F test/tkt-bdc6bbbb38.test fc38bb09bdd440e3513a1f5f98fc60a075182d7d
F test/tkt-c48d99d690.test ba61977d62ab612fc515b3c488a6fbd6464a2447
@@ -915,7 +905,6 @@ F test/tkt-d11f09d36e.test d999b548fef885d1d1afa49a0e8544ecf436869d
F test/tkt-d635236375.test 9d37e988b47d87505bc9445be0ca447002df5d09
F test/tkt-d82e3f3721.test bcc0dfba658d15bab30fd4a9320c9e35d214ce30
F test/tkt-f3e5abed55.test d5a0126118142d13e27f6ce9f4c47096e9321c00
F test/tkt-f67b41381a.test a23bc124c981662db712167bacd0ed8ad11abac9
F test/tkt-f777251dc7a.test af6531446c64bfd268416f07b4df7be7f9c749d2
F test/tkt-f7b4edec.test d998a08ff2b18b7f62edce8e3044317c45efe6c7
F test/tkt-f973c7ac31.test 28ef85c7f015477916795246d8286aeda39d4ead
@@ -1008,7 +997,7 @@ F test/tkt4018.test 7c2c9ba4df489c676a0a7a0e809a1fb9b2185bd1
F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
F test/tpch01.test 8f4ac52f62f3e9f6bce0889105aecdf0275e331b
F test/trace.test 4b36a41a3e9c7842151af6da5998f5080cdad9e5
F test/trace2.test 93b47ca6996c66b47f57224cfb146f34e07df382
F test/trace2.test e7a988fdd982cdec62f1f1f34b0360e6476d01a0
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
F test/trans3.test 373ac5183cc56be69f48ae44090e7f672939f732
@@ -1033,7 +1022,7 @@ F test/types2.test 3555aacf8ed8dc883356e59efc314707e6247a84
F test/types3.test 99e009491a54f4dc02c06bdbc0c5eea56ae3e25a
F test/unique.test 93f8b2ef5ea51b9495f8d6493429b1fd0f465264
F test/unixexcl.test cd6c765f75e50e8e2c2ba763149e5d340ea19825
F test/unordered.test ca7adce0419e4ca0c50f039885e76ed2c531eda8
F test/unordered.test ef85ac8f2f3c93ed2b9e811b684de73175fc464c
F test/update.test 1b6c488a8f993d090b7ee9ad0e234faa161b3aeb
F test/uri.test 23662b7b61958b0f0e47082de7d06341ccf85d5b
F test/utf16align.test 54cd35a27c005a9b6e7815d887718780b6a462ae
@@ -1062,8 +1051,8 @@ F test/vtabF.test fd5ad376f5a34fe0891df1f3cddb4fe7c3eb077e
F test/vtab_alter.test 9e374885248f69e251bdaacf480b04a197f125e5
F test/vtab_err.test 0d4d8eb4def1d053ac7c5050df3024fd47a3fbd8
F test/vtab_shared.test ea8778d5b0df200adef2ca7c00c3c37d4375f772
F test/wal.test 885f32b2b390b30b4aa3dbb0e568f8f78d40f5cc
F test/wal2.test 1f841d2048080d32f552942e333fd99ce541dada
F test/wal.test 40073e54359d43354925b2b700b7eebd5e207285
F test/wal2.test a8e3963abf6b232cf0b852b09b53665ef34007af
F test/wal3.test b22eb662bcbc148c5f6d956eaf94b047f7afe9c0
F test/wal4.test 4744e155cd6299c6bd99d3eab1c82f77db9cdb3c
F test/wal5.test 8f888b50f66b78821e61ed0e233ded5de378224b
@@ -1090,7 +1079,7 @@ F test/walslow.test e7be6d9888f83aa5d3d3c7c08aa9b5c28b93609a
F test/walthread.test de8dbaf6d9e41481c460ba31ca61e163d7348f8e
F test/where.test 28b64e93428961b07b0d486778d63fd672948f6b
F test/where2.test 455a2eb2666e66c1e84e2cb5815173a85e6237db
F test/where3.test 1ad55ba900bd7747f98b6082e65bd3e442c5004e
F test/where3.test d28c51f257e60be30f74308fa385ceeddfb54a6e
F test/where4.test d8420ceeb8323a41ceff1f1841fc528e824e1ecf
F test/where5.test fdf66f96d29a064b63eb543e28da4dfdccd81ad2
F test/where6.test 5da5a98cec820d488e82708301b96cb8c18a258b
@@ -1101,16 +1090,14 @@ F test/where9.test 4f3eab951353a3ae164befc521c777dfa903e46c
F test/whereA.test 4d253178d135ec46d1671e440cd8f2b916aa6e6b
F test/whereB.test 0def95db3bdec220a731c7e4bec5930327c1d8c5
F test/whereC.test d6f4ecd4fa2d9429681a5b22a25d2bda8e86ab8a
F test/whereD.test fd9120e262f9da3c45940f52aefeef4d15b904e5
F test/whereD.test 6c2feb79ef1f68381b07f39017fe5f9b96da8d62
F test/whereE.test b3a055eef928c992b0a33198a7b8dc10eea5ad2f
F test/whereF.test 5b2ba0dbe8074aa13e416b37c753991f0a2492d7
F test/whereG.test 0ac23e5e8311b69d87245f4a85112de321031658
F test/whereH.test e4b07f7a3c2f5d31195cd33710054c78667573b2
F test/whereI.test 1d89199697919d4930be05a71e7fe620f114e622
F test/whereG.test eb3a46b3eaf38e25e3013433b2db8a25a866c215
F test/wherelimit.test 5e9fd41e79bb2b2d588ed999d641d9c965619b31
F test/wild001.test bca33f499866f04c24510d74baf1e578d4e44b1c
F test/win32heap.test ea19770974795cff26e11575e12d422dbd16893c
F test/win32lock.test 71642fa56e9b06e5cfffe6bad67cb8c1eb2c555a
F test/win32lock.test 7a6bd73a5dcdee39b5bb93e92395e1773a194361
F test/win32longpath.test 169c75a3b2e43481f4a62122510210c67b08f26d
F test/with1.test 268081a6b14817a262ced4d0ee34d4d2a1dd2068
F test/with2.test ee227a663586aa09771cafd4fa269c5217eaf775
@@ -1123,7 +1110,7 @@ F test/without_rowid5.test b4a639a367f04d382d20e8f44fc1be4f2d57d107
F test/wordcount.c 9915e06cb33d8ca8109b8700791afe80d305afda
F test/zeroblob.test caaecfb4f908f7bc086ed238668049f96774d688
F test/zerodamage.test cf6748bad89553cc1632be51a6f54e487e4039ac
F tool/build-all-msvc.bat a0534c971b86fe95f1983f445db5b896d3394818 x
F tool/build-all-msvc.bat e0917e787df675b020d250d60a00de8abaa4e30a x
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
F tool/checkSpacing.c 810e51703529a204fc4e1eb060e9ab663e3c06d2
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
@@ -1135,17 +1122,17 @@ F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
F tool/lemon.c 07aba6270d5a5016ba8107b09e431eea4ecdc123
F tool/lempar.c 01ca97f87610d1dac6d8cd96ab109ab1130e76dc
F tool/logest.c eef612f8adf4d0993dafed0416064cf50d5d33c6
F tool/logest.c 388c318c7ac8b52b7c08ca1e2de0f4ca9a8f7e81
F tool/mkautoconfamal.sh f8d8dbf7d62f409ebed5134998bf5b51d7266383
F tool/mkkeywordhash.c c9e05e4a7bcab8fab9f583d5b321fb72f565ad97
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
F tool/mkpragmatab.tcl 78a77b2c554d534c6f2dc903130186ed15715460
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
F tool/mksqlite3c-noext.tcl 1712d3d71256ca1f297046619c89e77a4d7c8f6d
F tool/mksqlite3c.tcl ba274df71f5e6534b0a913c7c48eabfcbd0934b6
F tool/mksqlite3c-noext.tcl 752f1a9d3287f6c0ef5738b1c4add0b96fbe0854
F tool/mksqlite3c.tcl 8da823522f27608494997e1dba19cd426572ba80
F tool/mksqlite3h.tcl ba24038056f51fde07c0079c41885ab85e2cff12
F tool/mksqlite3internalh.tcl b6514145a7d5321b47e64e19b8116cc44f973eb1
F tool/mkvsix.tcl 52a4c613707ac34ae9c226e5ccc69cb948556105
F tool/mksqlite3internalh.tcl 3dca7bb5374cee003379b8cbac73714f610ef795
F tool/mkvsix.tcl 6477fb9dab838b7eea1eed50658ff1cda04850b5
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
F tool/omittest.tcl 34d7ac01fe4fd18e3637f64abe12c40eca0f6b97
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@@ -1171,9 +1158,9 @@ F tool/tostr.awk e75472c2f98dd76e06b8c9c1367f4ab07e122d06
F tool/vdbe-compress.tcl 0cf56e9263a152b84da86e75a5c0cdcdb7a47891
F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P ed5a9eb4f30a395bc641e79254217c7d7cf0aa5d
R 35776e018c929a9d3407d29571ba8a8f
U mistachkin
Z b80ed398d4e8aaa5357d010e1790f177
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P 18d1b402f2dbe78f1a1113bb356b710e348365ef
R 9fe7387082ff9660756870dd3cb64af4
U dan
Z 65bd6f7e332292b10d887f31007d4273
+1 -1
View File
@@ -1 +1 @@
f2906c44519d76db5bc36013369ae498b80655a8
83a105c864247a02b723c84069055765bf373703
-1
View File
@@ -116,7 +116,6 @@ static void renameParentFunc(
int token; /* Type of token */
UNUSED_PARAMETER(NotUsed);
if( zInput==0 || zOld==0 ) return;
for(z=zInput; *z; z=z+n){
n = sqlite3GetToken(z, &token);
if( token==TK_REFERENCES ){
+8 -19
View File
@@ -1002,7 +1002,7 @@ static void analyzeOneTable(
if( aGotoChng==0 ) continue;
/* Populate the register containing the index name. */
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
zIdxName = pTab->zName;
}else{
zIdxName = pIdx->zName;
@@ -1371,7 +1371,6 @@ static void decodeIntArray(
char *zIntArray, /* String containing int array to decode */
int nOut, /* Number of slots in aOut[] */
tRowcnt *aOut, /* Store integers here */
LogEst *aLog, /* Or, if aOut==0, here */
Index *pIndex /* Handle extra flags for this index, if not NULL */
){
char *z = zIntArray;
@@ -1390,17 +1389,7 @@ static void decodeIntArray(
v = v*10 + c - '0';
z++;
}
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
if( aOut ){
aOut[i] = v;
}else
#else
assert( aOut==0 );
UNUSED_PARAMETER(aOut);
#endif
{
aLog[i] = sqlite3LogEst(v);
}
aOut[i] = v;
if( *z==' ' ) z++;
}
#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
@@ -1456,12 +1445,12 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
z = argv[2];
if( pIndex ){
decodeIntArray((char*)z, pIndex->nKeyCol+1, 0, pIndex->aiRowLogEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowLogEst = pIndex->aiRowLogEst[0];
decodeIntArray((char*)z, pIndex->nKeyCol+1, pIndex->aiRowEst, pIndex);
if( pIndex->pPartIdxWhere==0 ) pTable->nRowEst = pIndex->aiRowEst[0];
}else{
Index fakeIdx;
fakeIdx.szIdxRow = pTable->szTabRow;
decodeIntArray((char*)z, 1, 0, &pTable->nRowLogEst, &fakeIdx);
decodeIntArray((char*)z, 1, &pTable->nRowEst, &fakeIdx);
pTable->szTabRow = fakeIdx.szIdxRow;
}
@@ -1653,9 +1642,9 @@ static int loadStatTbl(
pPrevIdx = pIdx;
}
pSample = &pIdx->aSample[pIdx->nSample];
decodeIntArray((char*)sqlite3_column_text(pStmt,1),nCol,pSample->anEq,0,0);
decodeIntArray((char*)sqlite3_column_text(pStmt,2),nCol,pSample->anLt,0,0);
decodeIntArray((char*)sqlite3_column_text(pStmt,3),nCol,pSample->anDLt,0,0);
decodeIntArray((char*)sqlite3_column_text(pStmt,1), nCol, pSample->anEq, 0);
decodeIntArray((char*)sqlite3_column_text(pStmt,2), nCol, pSample->anLt, 0);
decodeIntArray((char*)sqlite3_column_text(pStmt,3), nCol, pSample->anDLt,0);
/* Take a copy of the sample. Add two 0x00 bytes the end of the buffer.
** This is in case the sample record is corrupted. In that case, the
+96 -109
View File
@@ -446,11 +446,16 @@ static int cursorHoldsMutex(BtCursor *p){
}
#endif
#ifndef SQLITE_OMIT_INCRBLOB
/*
** Invalidate the overflow cache of the cursor passed as the first argument.
** on the shared btree structure pBt.
** Invalidate the overflow page-list cache for cursor pCur, if any.
*/
#define invalidateOverflowCache(pCur) (pCur->curFlags &= ~BTCF_ValidOvfl)
static void invalidateOverflowCache(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
sqlite3_free(pCur->aOverflow);
pCur->aOverflow = 0;
}
/*
** Invalidate the overflow page-list cache for all cursors opened
@@ -464,7 +469,6 @@ static void invalidateAllOverflowCache(BtShared *pBt){
}
}
#ifndef SQLITE_OMIT_INCRBLOB
/*
** This function is called before modifying the contents of a table
** to invalidate any incrblob cursors that are open on the
@@ -487,14 +491,16 @@ static void invalidateIncrblobCursors(
BtShared *pBt = pBtree->pBt;
assert( sqlite3BtreeHoldsMutex(pBtree) );
for(p=pBt->pCursor; p; p=p->pNext){
if( (p->curFlags & BTCF_Incrblob)!=0 && (isClearTable || p->info.nKey==iRow) ){
if( p->isIncrblobHandle && (isClearTable || p->info.nKey==iRow) ){
p->eState = CURSOR_INVALID;
}
}
}
#else
/* Stub function when INCRBLOB is omitted */
/* Stub functions when INCRBLOB is omitted */
#define invalidateOverflowCache(x)
#define invalidateAllOverflowCache(x)
#define invalidateIncrblobCursors(x,y,z)
#endif /* SQLITE_OMIT_INCRBLOB */
@@ -2557,8 +2563,7 @@ static int countValidCursors(BtShared *pBt, int wrOnly){
BtCursor *pCur;
int r = 0;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
if( (wrOnly==0 || (pCur->curFlags & BTCF_WriteFlag)!=0)
&& pCur->eState!=CURSOR_FAULT ) r++;
if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++;
}
return r;
}
@@ -3633,8 +3638,7 @@ static int btreeCursor(
pCur->pKeyInfo = pKeyInfo;
pCur->pBtree = p;
pCur->pBt = pBt;
assert( wrFlag==0 || wrFlag==BTCF_WriteFlag );
pCur->curFlags = wrFlag;
pCur->wrFlag = (u8)wrFlag;
pCur->pNext = pBt->pCursor;
if( pCur->pNext ){
pCur->pNext->pPrev = pCur;
@@ -3704,7 +3708,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
releasePage(pCur->apPage[i]);
}
unlockBtreeIfUnused(pBt);
sqlite3DbFree(pBtree->db, pCur->aOverflow);
invalidateOverflowCache(pCur);
/* sqlite3_free(pCur); */
sqlite3BtreeLeave(pBtree);
}
@@ -3743,7 +3747,7 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
if( pCur->info.nSize==0 ){
int iPage = pCur->iPage;
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info);
pCur->curFlags |= BTCF_ValidNKey;
pCur->validNKey = 1;
}else{
assertCellInfo(pCur);
}
@@ -3753,8 +3757,8 @@ int sqlite3BtreeCloseCursor(BtCursor *pCur){
#define getCellInfo(pCur) \
if( pCur->info.nSize==0 ){ \
int iPage = pCur->iPage; \
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
pCur->curFlags |= BTCF_ValidNKey; \
btreeParseCell(pCur->apPage[iPage],pCur->aiIdx[iPage],&pCur->info); \
pCur->validNKey = 1; \
}else{ \
assertCellInfo(pCur); \
}
@@ -3925,12 +3929,10 @@ static int copyPayload(
/*
** This function is used to read or overwrite payload information
** for the entry that the pCur cursor is pointing to. The eOp
** argument is interpreted as follows:
**
** 0: The operation is a read. Populate the overflow cache.
** 1: The operation is a write. Populate the overflow cache.
** 2: The operation is a read. Do not populate the overflow cache.
** for the entry that the pCur cursor is pointing to. If the eOp
** parameter is 0, this is a read operation (data copied into
** buffer pBuf). If it is non-zero, a write (data copied from
** buffer pBuf).
**
** A total of "amt" bytes are read or written beginning at "offset".
** Data is read to or from the buffer pBuf.
@@ -3938,11 +3940,11 @@ static int copyPayload(
** The content being read or written might appear on the main page
** or be scattered out on multiple overflow pages.
**
** If the current cursor entry uses one or more overflow pages and the
** eOp argument is not 2, this function may allocate space for and lazily
** popluates the overflow page-list cache array (BtCursor.aOverflow).
** Subsequent calls use this cache to make seeking to the supplied offset
** more efficient.
** If the BtCursor.isIncrblobHandle flag is set, and the current
** cursor entry uses one or more overflow pages, this function
** allocates space for and lazily popluates the overflow page-list
** cache array (BtCursor.aOverflow). Subsequent calls use this
** cache to make seeking to the supplied offset more efficient.
**
** Once an overflow page-list cache has been allocated, it may be
** invalidated if some other cursor writes to the same table, or if
@@ -3966,22 +3968,15 @@ static int accessPayload(
int iIdx = 0;
MemPage *pPage = pCur->apPage[pCur->iPage]; /* Btree page of current entry */
BtShared *pBt = pCur->pBt; /* Btree this cursor belongs to */
#ifdef SQLITE_DIRECT_OVERFLOW_READ
int bEnd; /* True if reading to end of data */
#endif
assert( pPage );
assert( pCur->eState==CURSOR_VALID );
assert( pCur->aiIdx[pCur->iPage]<pPage->nCell );
assert( cursorHoldsMutex(pCur) );
assert( eOp!=2 || offset==0 ); /* Always start from beginning for eOp==2 */
getCellInfo(pCur);
aPayload = pCur->info.pCell + pCur->info.nHeader;
nKey = (pPage->intKey ? 0 : (int)pCur->info.nKey);
#ifdef SQLITE_DIRECT_OVERFLOW_READ
bEnd = (offset+amt==nKey+pCur->info.nData);
#endif
if( NEVER(offset+amt > nKey+pCur->info.nData)
|| &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize]
@@ -3996,7 +3991,7 @@ static int accessPayload(
if( a+offset>pCur->info.nLocal ){
a = pCur->info.nLocal - offset;
}
rc = copyPayload(&aPayload[offset], pBuf, a, (eOp & 0x01), pPage->pDbPage);
rc = copyPayload(&aPayload[offset], pBuf, a, eOp, pPage->pDbPage);
offset = 0;
pBuf += a;
amt -= a;
@@ -4010,30 +4005,21 @@ static int accessPayload(
nextPage = get4byte(&aPayload[pCur->info.nLocal]);
/* If the BtCursor.aOverflow[] has not been allocated, allocate it now.
** Except, do not allocate aOverflow[] for eOp==2.
**
** The aOverflow[] array is sized at one entry for each overflow page
** in the overflow chain. The page number of the first overflow page is
** stored in aOverflow[0], etc. A value of 0 in the aOverflow[] array
** means "not yet known" (the cache is lazily populated).
#ifndef SQLITE_OMIT_INCRBLOB
/* If the isIncrblobHandle flag is set and the BtCursor.aOverflow[]
** has not been allocated, allocate it now. The array is sized at
** one entry for each overflow page in the overflow chain. The
** page number of the first overflow page is stored in aOverflow[0],
** etc. A value of 0 in the aOverflow[] array means "not yet known"
** (the cache is lazily populated).
*/
if( eOp!=2 && (pCur->curFlags & BTCF_ValidOvfl)==0 ){
if( pCur->isIncrblobHandle && !pCur->aOverflow ){
int nOvfl = (pCur->info.nPayload-pCur->info.nLocal+ovflSize-1)/ovflSize;
if( nOvfl>pCur->nOvflAlloc ){
Pgno *aNew = (Pgno*)sqlite3DbRealloc(
pCur->pBtree->db, pCur->aOverflow, nOvfl*2*sizeof(Pgno)
);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
pCur->nOvflAlloc = nOvfl*2;
pCur->aOverflow = aNew;
}
}
if( rc==SQLITE_OK ){
memset(pCur->aOverflow, 0, nOvfl*sizeof(Pgno));
pCur->curFlags |= BTCF_ValidOvfl;
pCur->aOverflow = (Pgno *)sqlite3MallocZero(sizeof(Pgno)*nOvfl);
/* nOvfl is always positive. If it were zero, fetchPayload would have
** been used instead of this routine. */
if( ALWAYS(nOvfl) && !pCur->aOverflow ){
rc = SQLITE_NOMEM;
}
}
@@ -4041,19 +4027,22 @@ static int accessPayload(
** entry for the first required overflow page is valid, skip
** directly to it.
*/
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 && pCur->aOverflow[offset/ovflSize] ){
if( pCur->aOverflow && pCur->aOverflow[offset/ovflSize] ){
iIdx = (offset/ovflSize);
nextPage = pCur->aOverflow[iIdx];
offset = (offset%ovflSize);
}
#endif
for( ; rc==SQLITE_OK && amt>0 && nextPage; iIdx++){
#ifndef SQLITE_OMIT_INCRBLOB
/* If required, populate the overflow page-list cache. */
if( (pCur->curFlags & BTCF_ValidOvfl)!=0 ){
if( pCur->aOverflow ){
assert(!pCur->aOverflow[iIdx] || pCur->aOverflow[iIdx]==nextPage);
pCur->aOverflow[iIdx] = nextPage;
}
#endif
if( offset>=ovflSize ){
/* The only reason to read this page is to obtain the page
@@ -4061,17 +4050,13 @@ static int accessPayload(
** data is not required. So first try to lookup the overflow
** page-list cache, if any, then fall back to the getOverflowPage()
** function.
**
** Note that the aOverflow[] array must be allocated because eOp!=2
** here. If eOp==2, then offset==0 and this branch is never taken.
*/
assert( eOp!=2 );
assert( pCur->curFlags & BTCF_ValidOvfl );
if( pCur->aOverflow[iIdx+1] ){
#ifndef SQLITE_OMIT_INCRBLOB
if( pCur->aOverflow && pCur->aOverflow[iIdx+1] ){
nextPage = pCur->aOverflow[iIdx+1];
}else{
} else
#endif
rc = getOverflowPage(pBt, nextPage, 0, &nextPage);
}
offset -= ovflSize;
}else{
/* Need to read this page properly. It contains some of the
@@ -4093,15 +4078,13 @@ static int accessPayload(
** 3) the database is file-backed, and
** 4) there is no open write-transaction, and
** 5) the database is not a WAL database,
** 6) all data from the page is being read.
**
** then data can be read directly from the database file into the
** output buffer, bypassing the page-cache altogether. This speeds
** up loading large records that span many overflow pages.
*/
if( (eOp&0x01)==0 /* (1) */
if( eOp==0 /* (1) */
&& offset==0 /* (2) */
&& (bEnd || a==ovflSize) /* (6) */
&& pBt->inTransaction==TRANS_READ /* (4) */
&& (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
&& pBt->pPage1->aData[19]==0x01 /* (5) */
@@ -4118,12 +4101,12 @@ static int accessPayload(
{
DbPage *pDbPage;
rc = sqlite3PagerAcquire(pBt->pPager, nextPage, &pDbPage,
((eOp&0x01)==0 ? PAGER_GET_READONLY : 0)
(eOp==0 ? PAGER_GET_READONLY : 0)
);
if( rc==SQLITE_OK ){
aPayload = sqlite3PagerGetData(pDbPage);
nextPage = get4byte(aPayload);
rc = copyPayload(&aPayload[offset+4], pBuf, a, (eOp&0x01), pDbPage);
rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
sqlite3PagerUnref(pDbPage);
offset = 0;
}
@@ -4218,6 +4201,12 @@ static const void *fetchPayload(
assert( cursorHoldsMutex(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 );
#if 0
if( pCur->info.nSize==0 ){
btreeParseCell(pCur->apPage[pCur->iPage], pCur->aiIdx[pCur->iPage],
&pCur->info);
}
#endif
*pAmt = pCur->info.nLocal;
return (void*)(pCur->info.pCell + pCur->info.nHeader);
}
@@ -4268,14 +4257,14 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
return SQLITE_CORRUPT_BKPT;
}
rc = getAndInitPage(pBt, newPgno, &pNewPage,
(pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc ) return rc;
pCur->apPage[i+1] = pNewPage;
pCur->aiIdx[i+1] = 0;
pCur->iPage++;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->validNKey = 0;
if( pNewPage->nCell<1 || pNewPage->intKey!=pCur->apPage[i]->intKey ){
return SQLITE_CORRUPT_BKPT;
}
@@ -4333,7 +4322,7 @@ static void moveToParent(BtCursor *pCur){
releasePage(pCur->apPage[pCur->iPage]);
pCur->iPage--;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->validNKey = 0;
}
/*
@@ -4380,7 +4369,7 @@ static int moveToRoot(BtCursor *pCur){
return SQLITE_OK;
}else{
rc = getAndInitPage(pCur->pBtree->pBt, pCur->pgnoRoot, &pCur->apPage[0],
(pCur->curFlags & BTCF_WriteFlag)==0 ? PAGER_GET_READONLY : 0);
pCur->wrFlag==0 ? PAGER_GET_READONLY : 0);
if( rc!=SQLITE_OK ){
pCur->eState = CURSOR_INVALID;
return rc;
@@ -4407,7 +4396,8 @@ static int moveToRoot(BtCursor *pCur){
pCur->aiIdx[0] = 0;
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->atLast = 0;
pCur->validNKey = 0;
if( pRoot->nCell>0 ){
pCur->eState = CURSOR_VALID;
@@ -4470,7 +4460,7 @@ static int moveToRightmost(BtCursor *pCur){
if( rc==SQLITE_OK ){
pCur->aiIdx[pCur->iPage] = pPage->nCell-1;
pCur->info.nSize = 0;
pCur->curFlags &= ~BTCF_ValidNKey;
pCur->validNKey = 0;
}
return rc;
}
@@ -4509,7 +4499,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
/* If the cursor already points to the last entry, this is a no-op. */
if( CURSOR_VALID==pCur->eState && (pCur->curFlags & BTCF_AtLast)!=0 ){
if( CURSOR_VALID==pCur->eState && pCur->atLast ){
#ifdef SQLITE_DEBUG
/* This block serves to assert() that the cursor really does point
** to the last entry in the b-tree. */
@@ -4532,12 +4522,7 @@ int sqlite3BtreeLast(BtCursor *pCur, int *pRes){
assert( pCur->eState==CURSOR_VALID );
*pRes = 0;
rc = moveToRightmost(pCur);
if( rc==SQLITE_OK ){
pCur->curFlags |= BTCF_AtLast;
}else{
pCur->curFlags &= ~BTCF_AtLast;
}
pCur->atLast = rc==SQLITE_OK ?1:0;
}
}
return rc;
@@ -4588,14 +4573,14 @@ int sqlite3BtreeMovetoUnpacked(
/* If the cursor is already positioned at the point we are trying
** to move to, then just return without doing any work */
if( pCur->eState==CURSOR_VALID && (pCur->curFlags & BTCF_ValidNKey)!=0
if( pCur->eState==CURSOR_VALID && pCur->validNKey
&& pCur->apPage[0]->intKey
){
if( pCur->info.nKey==intKey ){
*pRes = 0;
return SQLITE_OK;
}
if( (pCur->curFlags & BTCF_AtLast)!=0 && pCur->info.nKey<intKey ){
if( pCur->atLast && pCur->info.nKey<intKey ){
*pRes = -1;
return SQLITE_OK;
}
@@ -4662,7 +4647,7 @@ int sqlite3BtreeMovetoUnpacked(
if( lwr>upr ){ c = +1; break; }
}else{
assert( nCellKey==intKey );
pCur->curFlags |= BTCF_ValidNKey;
pCur->validNKey = 1;
pCur->info.nKey = nCellKey;
pCur->aiIdx[pCur->iPage] = (u16)idx;
if( !pPage->leaf ){
@@ -4719,7 +4704,7 @@ int sqlite3BtreeMovetoUnpacked(
goto moveto_finish;
}
pCur->aiIdx[pCur->iPage] = (u16)idx;
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 2);
rc = accessPayload(pCur, 0, nCell, (unsigned char*)pCellKey, 0);
if( rc ){
sqlite3_free(pCellKey);
goto moveto_finish;
@@ -4766,7 +4751,7 @@ moveto_next_layer:
}
moveto_finish:
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->validNKey = 0;
return rc;
}
@@ -4811,7 +4796,6 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
if( pCur->eState!=CURSOR_VALID ){
invalidateOverflowCache(pCur);
rc = restoreCursorPosition(pCur);
if( rc!=SQLITE_OK ){
*pRes = 0;
@@ -4845,7 +4829,7 @@ int sqlite3BtreeNext(BtCursor *pCur, int *pRes){
testcase( idx>pPage->nCell );
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->validNKey = 0;
if( idx>=pPage->nCell ){
if( !pPage->leaf ){
rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8]));
@@ -4906,7 +4890,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
assert( pRes!=0 );
assert( *pRes==0 || *pRes==1 );
assert( pCur->skipNext==0 || pCur->eState!=CURSOR_VALID );
pCur->curFlags &= ~(BTCF_AtLast|BTCF_ValidOvfl);
pCur->atLast = 0;
if( pCur->eState!=CURSOR_VALID ){
if( ALWAYS(pCur->eState>=CURSOR_REQUIRESEEK) ){
rc = btreeRestoreCursorPosition(pCur);
@@ -4951,7 +4935,7 @@ int sqlite3BtreePrevious(BtCursor *pCur, int *pRes){
moveToParent(pCur);
}
pCur->info.nSize = 0;
pCur->curFlags &= ~(BTCF_ValidNKey|BTCF_ValidOvfl);
pCur->validNKey = 0;
pCur->aiIdx[pCur->iPage]--;
pPage = pCur->apPage[pCur->iPage];
@@ -6976,7 +6960,7 @@ int sqlite3BtreeInsert(
}
assert( cursorHoldsMutex(pCur) );
assert( (pCur->curFlags & BTCF_WriteFlag)!=0 && pBt->inTransaction==TRANS_WRITE
assert( pCur->wrFlag && pBt->inTransaction==TRANS_WRITE
&& (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
@@ -7009,7 +6993,7 @@ int sqlite3BtreeInsert(
/* If the cursor is currently on the last row and we are appending a
** new row onto the end, set the "loc" to avoid an unnecessary btreeMoveto()
** call */
if( (pCur->curFlags&BTCF_ValidNKey)!=0 && nKey>0 && pCur->info.nKey==nKey-1 ){
if( pCur->validNKey && nKey>0 && pCur->info.nKey==nKey-1 ){
loc = -1;
}
}
@@ -7062,7 +7046,7 @@ int sqlite3BtreeInsert(
/* If no error has occurred and pPage has an overflow cell, call balance()
** to redistribute the cells within the tree. Since balance() may move
** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey
** the cursor, zero the BtCursor.info.nSize and BtCursor.validNKey
** variables.
**
** Previous versions of SQLite called moveToRoot() to move the cursor
@@ -7082,7 +7066,7 @@ int sqlite3BtreeInsert(
*/
pCur->info.nSize = 0;
if( rc==SQLITE_OK && pPage->nOverflow ){
pCur->curFlags &= ~(BTCF_ValidNKey);
pCur->validNKey = 0;
rc = balance(pCur);
/* Must make sure nOverflow is reset to zero even if the balance()
@@ -7114,7 +7098,7 @@ int sqlite3BtreeDelete(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( pBt->inTransaction==TRANS_WRITE );
assert( (pBt->btsFlags & BTS_READ_ONLY)==0 );
assert( pCur->curFlags & BTCF_WriteFlag );
assert( pCur->wrFlag );
assert( hasSharedCacheTableLock(p, pCur->pgnoRoot, pCur->pKeyInfo!=0, 2) );
assert( !hasReadConflicts(p, pCur->pgnoRoot) );
@@ -8427,7 +8411,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
int rc;
assert( cursorHoldsMutex(pCsr) );
assert( sqlite3_mutex_held(pCsr->pBtree->db->mutex) );
assert( pCsr->curFlags & BTCF_Incrblob );
assert( pCsr->isIncrblobHandle );
rc = restoreCursorPosition(pCsr);
if( rc!=SQLITE_OK ){
@@ -8456,7 +8440,7 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
** (d) there are no conflicting read-locks, and
** (e) the cursor points at a valid row of an intKey table.
*/
if( (pCsr->curFlags & BTCF_WriteFlag)==0 ){
if( !pCsr->wrFlag ){
return SQLITE_READONLY;
}
assert( (pCsr->pBt->btsFlags & BTS_READ_ONLY)==0
@@ -8469,10 +8453,20 @@ int sqlite3BtreePutData(BtCursor *pCsr, u32 offset, u32 amt, void *z){
}
/*
** Mark this cursor as an incremental blob cursor.
** Set a flag on this cursor to cache the locations of pages from the
** overflow list for the current row. This is used by cursors opened
** for incremental blob IO only.
**
** This function sets a flag only. The actual page location cache
** (stored in BtCursor.aOverflow[]) is allocated and used by function
** accessPayload() (the worker function for sqlite3BtreeData() and
** sqlite3BtreePutData()).
*/
void sqlite3BtreeIncrblobCursor(BtCursor *pCur){
pCur->curFlags |= BTCF_Incrblob;
void sqlite3BtreeCacheOverflow(BtCursor *pCur){
assert( cursorHoldsMutex(pCur) );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
invalidateOverflowCache(pCur);
pCur->isIncrblobHandle = 1;
}
#endif
@@ -8520,10 +8514,3 @@ void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
assert( mask==BTREE_BULKLOAD || mask==0 );
pCsr->hints = mask;
}
/*
** Return true if the given Btree is read-only.
*/
int sqlite3BtreeIsReadonly(Btree *p){
return (p->pBt->btsFlags & BTS_READ_ONLY)!=0;
}
+1 -2
View File
@@ -190,11 +190,10 @@ char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
struct Pager *sqlite3BtreePager(Btree*);
int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
void sqlite3BtreeIncrblobCursor(BtCursor *);
void sqlite3BtreeCacheOverflow(BtCursor *);
void sqlite3BtreeClearCursor(BtCursor *);
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
int sqlite3BtreeIsReadonly(Btree *pBt);
#ifndef NDEBUG
int sqlite3BtreeCursorIsValid(BtCursor*);
+11 -14
View File
@@ -496,30 +496,27 @@ struct BtCursor {
BtShared *pBt; /* The BtShared this cursor points to */
BtCursor *pNext, *pPrev; /* Forms a linked list of all cursors */
struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
#ifndef SQLITE_OMIT_INCRBLOB
Pgno *aOverflow; /* Cache of overflow page locations */
CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor last known position */
#endif
Pgno pgnoRoot; /* The root page of this tree */
int nOvflAlloc; /* Allocated size of aOverflow[] array */
CellInfo info; /* A parse of the cell we are pointing at */
i64 nKey; /* Size of pKey, or last integer key */
void *pKey; /* Saved key that was cursor's last known position */
int skipNext; /* Prev() is noop if negative. Next() is noop if positive */
u8 curFlags; /* zero or more BTCF_* flags defined below */
u8 wrFlag; /* True if writable */
u8 atLast; /* Cursor pointing to the last entry */
u8 validNKey; /* True if info.nKey is valid */
u8 eState; /* One of the CURSOR_XXX constants (see below) */
#ifndef SQLITE_OMIT_INCRBLOB
u8 isIncrblobHandle; /* True if this cursor is an incr. io handle */
#endif
u8 hints; /* As configured by CursorSetHints() */
i16 iPage; /* Index of current page in apPage */
u16 aiIdx[BTCURSOR_MAX_DEPTH]; /* Current index in apPage[i] */
MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
};
/*
** Legal values for BtCursor.curFlags
*/
#define BTCF_WriteFlag 0x01 /* True if a write cursor */
#define BTCF_ValidNKey 0x02 /* True if info.nKey is valid */
#define BTCF_ValidOvfl 0x04 /* True if aOverflow is valid */
#define BTCF_AtLast 0x08 /* Cursor is pointing ot the last entry */
#define BTCF_Incrblob 0x10 /* True if an incremental I/O handle */
/*
** Potential values for BtCursor.eState.
**
+30 -41
View File
@@ -757,7 +757,7 @@ int sqlite3CheckObjectName(Parse *pParse, const char *zName){
*/
Index *sqlite3PrimaryKeyIndex(Table *pTab){
Index *p;
for(p=pTab->pIndex; p && !IsPrimaryKeyIndex(p); p=p->pNext){}
for(p=pTab->pIndex; p && p->autoIndex!=2; p=p->pNext){}
return p;
}
@@ -905,7 +905,7 @@ void sqlite3StartTable(
pTable->iPKey = -1;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
pTable->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTable->nRowEst = 1048576;
assert( pParse->pNewTable==0 );
pParse->pNewTable = pTable;
@@ -1286,7 +1286,7 @@ void sqlite3AddPrimaryKey(
p = sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0,
0, sortOrder, 0);
if( p ){
p->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
p->autoIndex = 2;
if( v ) sqlite3VdbeJumpHere(v, pParse->addrSkipPK);
}
pList = 0;
@@ -1306,10 +1306,7 @@ void sqlite3AddCheckConstraint(
){
#ifndef SQLITE_OMIT_CHECK
Table *pTab = pParse->pNewTable;
sqlite3 *db = pParse->db;
if( pTab && !IN_DECLARE_VTAB
&& !sqlite3BtreeIsReadonly(db->aDb[db->init.iDb].pBt)
){
if( pTab && !IN_DECLARE_VTAB ){
pTab->pCheck = sqlite3ExprListAppend(pParse, pTab->pCheck, pCheckExpr);
if( pParse->constraintName.n ){
sqlite3ExprListSetName(pParse, pTab->pCheck, &pParse->constraintName, 1);
@@ -1661,7 +1658,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
assert( pParse->pNewTable==pTab );
pPk = sqlite3CreateIndex(pParse, 0, 0, 0, pList, pTab->keyConf, 0, 0, 0, 0);
if( pPk==0 ) return;
pPk->idxType = SQLITE_IDXTYPE_PRIMARYKEY;
pPk->autoIndex = 2;
pTab->iPKey = -1;
}else{
pPk = sqlite3PrimaryKeyIndex(pTab);
@@ -1684,7 +1681,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
*/
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int n;
if( IsPrimaryKeyIndex(pIdx) ) continue;
if( pIdx->autoIndex==2 ) continue;
for(i=n=0; i<nPk; i++){
if( !hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) ) n++;
}
@@ -2683,7 +2680,7 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
sqlite3GenerateIndexKey(pParse,pIndex,iTab,regRecord,0,&iPartIdxLabel,0,0);
sqlite3VdbeAddOp2(v, OP_SorterInsert, iSorter, regRecord);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
sqlite3VdbeAddOp2(v, OP_Next, iTab, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
if( memRootPage<0 ) sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
@@ -2733,15 +2730,15 @@ Index *sqlite3AllocateIndexObject(
nByte = ROUND8(sizeof(Index)) + /* Index structure */
ROUND8(sizeof(char*)*nCol) + /* Index.azColl */
ROUND8(sizeof(LogEst)*(nCol+1) + /* Index.aiRowLogEst */
ROUND8(sizeof(tRowcnt)*(nCol+1) + /* Index.aiRowEst */
sizeof(i16)*nCol + /* Index.aiColumn */
sizeof(u8)*nCol); /* Index.aSortOrder */
p = sqlite3DbMallocZero(db, nByte + nExtra);
if( p ){
char *pExtra = ((char*)p)+ROUND8(sizeof(Index));
p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
p->aiRowLogEst = (LogEst*)pExtra; pExtra += sizeof(LogEst)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->azColl = (char**)pExtra; pExtra += ROUND8(sizeof(char*)*nCol);
p->aiRowEst = (tRowcnt*)pExtra; pExtra += sizeof(tRowcnt)*(nCol+1);
p->aiColumn = (i16*)pExtra; pExtra += sizeof(i16)*nCol;
p->aSortOrder = (u8*)pExtra;
p->nColumn = nCol;
p->nKeyCol = nCol - 1;
@@ -2764,7 +2761,7 @@ Index *sqlite3AllocateIndexObject(
**
** If the index is created successfully, return a pointer to the new Index
** structure. This is used by sqlite3AddPrimaryKey() to mark the index
** as the tables primary key (Index.idxType==SQLITE_IDXTYPE_PRIMARYKEY)
** as the tables primary key (Index.autoIndex==2).
*/
Index *sqlite3CreateIndex(
Parse *pParse, /* All information about this parse */
@@ -2971,7 +2968,7 @@ Index *sqlite3CreateIndex(
if( db->mallocFailed ){
goto exit_create_index;
}
assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowLogEst) );
assert( EIGHT_BYTE_ALIGNMENT(pIndex->aiRowEst) );
assert( EIGHT_BYTE_ALIGNMENT(pIndex->azColl) );
pIndex->zName = zExtra;
zExtra += nName + 1;
@@ -2979,7 +2976,7 @@ Index *sqlite3CreateIndex(
pIndex->pTable = pTab;
pIndex->onError = (u8)onError;
pIndex->uniqNotNull = onError!=OE_None;
pIndex->idxType = pName ? SQLITE_IDXTYPE_APPDEF : SQLITE_IDXTYPE_UNIQUE;
pIndex->autoIndex = (u8)(pName==0);
pIndex->pSchema = db->aDb[iDb].pSchema;
pIndex->nKeyCol = pList->nExpr;
if( pPIWhere ){
@@ -3091,7 +3088,7 @@ Index *sqlite3CreateIndex(
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
int k;
assert( pIdx->onError!=OE_None );
assert( pIdx->idxType!=SQLITE_IDXTYPE_APPDEF );
assert( pIdx->autoIndex );
assert( pIndex->onError!=OE_None );
if( pIdx->nKeyCol!=pIndex->nKeyCol ) continue;
@@ -3252,7 +3249,7 @@ exit_create_index:
** Since we do not know, guess 1 million. aiRowEst[1] is an estimate of the
** number of rows in the table that match any particular value of the
** first column of the index. aiRowEst[2] is an estimate of the number
** of rows that match any particular combination of the first 2 columns
** of rows that match any particular combiniation of the first 2 columns
** of the index. And so forth. It must always be the case that
*
** aiRowEst[N]<=aiRowEst[N-1]
@@ -3263,27 +3260,20 @@ exit_create_index:
** are based on typical values found in actual indices.
*/
void sqlite3DefaultRowEst(Index *pIdx){
/* 10, 9, 8, 7, 6 */
LogEst aVal[] = { 33, 32, 30, 28, 26 };
LogEst *a = pIdx->aiRowLogEst;
int nCopy = MIN(ArraySize(aVal), pIdx->nKeyCol);
tRowcnt *a = pIdx->aiRowEst;
int i;
/* Set the first entry (number of rows in the index) to the estimated
** number of rows in the table. Or 10, if the estimated number of rows
** in the table is less than that. */
a[0] = pIdx->pTable->nRowLogEst;
if( a[0]<33 ) a[0] = 33; assert( 33==sqlite3LogEst(10) );
/* Estimate that a[1] is 10, a[2] is 9, a[3] is 8, a[4] is 7, a[5] is
** 6 and each subsequent value (if any) is 5. */
memcpy(&a[1], aVal, nCopy*sizeof(LogEst));
for(i=nCopy+1; i<=pIdx->nKeyCol; i++){
a[i] = 23; assert( 23==sqlite3LogEst(5) );
tRowcnt n;
assert( a!=0 );
a[0] = pIdx->pTable->nRowEst;
if( a[0]<10 ) a[0] = 10;
n = 10;
for(i=1; i<=pIdx->nKeyCol; i++){
a[i] = n;
if( n>5 ) n--;
}
if( pIdx->onError!=OE_None ){
a[pIdx->nKeyCol] = 1;
}
assert( 0==sqlite3LogEst(1) );
if( pIdx->onError!=OE_None ) a[pIdx->nKeyCol] = 0;
}
/*
@@ -3314,7 +3304,7 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName, int ifExists){
pParse->checkSchema = 1;
goto exit_drop_index;
}
if( pIndex->idxType!=SQLITE_IDXTYPE_APPDEF ){
if( pIndex->autoIndex ){
sqlite3ErrorMsg(pParse, "index associated with UNIQUE "
"or PRIMARY KEY constraint cannot be dropped", 0);
goto exit_drop_index;
@@ -3973,8 +3963,7 @@ void sqlite3UniqueConstraint(
}
zErr = sqlite3StrAccumFinish(&errMsg);
sqlite3HaltConstraint(pParse,
IsPrimaryKeyIndex(pIdx) ? SQLITE_CONSTRAINT_PRIMARYKEY
: SQLITE_CONSTRAINT_UNIQUE,
(pIdx->autoIndex==2)?SQLITE_CONSTRAINT_PRIMARYKEY:SQLITE_CONSTRAINT_UNIQUE,
onError, zErr, P4_DYNAMIC, P5_ConstraintUnique);
}
+2 -16
View File
@@ -739,7 +739,7 @@ void sqlite3GenerateRowIndexDelete(
&iPartIdxLabel, pPrior, r1);
sqlite3VdbeAddOp3(v, OP_IdxDelete, iIdxCur+i, r1,
pIdx->uniqNotNull ? pIdx->nKeyCol : pIdx->nColumn);
sqlite3ResolvePartIdxLabel(pParse, iPartIdxLabel);
sqlite3VdbeResolveLabel(v, iPartIdxLabel);
pPrior = pIdx;
}
}
@@ -758,11 +758,10 @@ void sqlite3GenerateRowIndexDelete(
**
** If *piPartIdxLabel is not NULL, fill it in with a label and jump
** to that label if pIdx is a partial index that should be skipped.
** The label should be resolved using sqlite3ResolvePartIdxLabel().
** A partial index should be skipped if its WHERE clause evaluates
** to false or null. If pIdx is not a partial index, *piPartIdxLabel
** will be set to zero which is an empty label that is ignored by
** sqlite3ResolvePartIdxLabel().
** sqlite3VdbeResolveLabel().
**
** The pPrior and regPrior parameters are used to implement a cache to
** avoid unnecessary register loads. If pPrior is not NULL, then it is
@@ -795,7 +794,6 @@ int sqlite3GenerateIndexKey(
if( pIdx->pPartIdxWhere ){
*piPartIdxLabel = sqlite3VdbeMakeLabel(v);
pParse->iPartIdxTab = iDataCur;
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pIdx->pPartIdxWhere, *piPartIdxLabel,
SQLITE_JUMPIFNULL);
}else{
@@ -823,15 +821,3 @@ int sqlite3GenerateIndexKey(
sqlite3ReleaseTempRange(pParse, regBase, nCol);
return regBase;
}
/*
** If a prior call to sqlite3GenerateIndexKey() generated a jump-over label
** because it was a partial index, then this routine should be called to
** resolve that label.
*/
void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
if( iLabel ){
sqlite3VdbeResolveLabel(pParse->pVdbe, iLabel);
sqlite3ExprCachePop(pParse);
}
}
+16 -15
View File
@@ -1883,7 +1883,7 @@ int sqlite3CodeSubselect(
if( testAddr>=0 ){
sqlite3VdbeJumpHere(v, testAddr);
}
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
return rReg;
}
@@ -2018,7 +2018,7 @@ static void sqlite3ExprCodeIN(
}
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
VdbeComment((v, "end IN expr"));
}
#endif /* SQLITE_OMIT_SUBQUERY */
@@ -2201,14 +2201,15 @@ void sqlite3ExprCachePush(Parse *pParse){
/*
** Remove from the column cache any entries that were added since the
** the previous sqlite3ExprCachePush operation. In other words, restore
** the cache to the state it was in prior the most recent Push.
** the previous N Push operations. In other words, restore the cache
** to the state it was in N Pushes ago.
*/
void sqlite3ExprCachePop(Parse *pParse){
void sqlite3ExprCachePop(Parse *pParse, int N){
int i;
struct yColCache *p;
assert( pParse->iCacheLevel>=1 );
pParse->iCacheLevel--;
assert( N>0 );
assert( pParse->iCacheLevel>=N );
pParse->iCacheLevel -= N;
#ifdef SQLITE_DEBUG
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
printf("POP to %d\n", pParse->iCacheLevel);
@@ -2686,7 +2687,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCacheRemove(pParse, target, 1);
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pFarg->a[i].pExpr, target);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
}
sqlite3VdbeResolveLabel(v, endCoalesce);
break;
@@ -2740,7 +2741,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
sqlite3ExprCachePush(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCodeExprList(pParse, pFarg, r1,
SQLITE_ECEL_DUP|SQLITE_ECEL_FACTOR);
sqlite3ExprCachePop(pParse); /* Ticket 2ea2425d34be */
sqlite3ExprCachePop(pParse, 1); /* Ticket 2ea2425d34be */
}else{
r1 = 0;
}
@@ -2960,13 +2961,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
sqlite3VdbeResolveLabel(v, nextCase);
}
if( (nExpr&1)!=0 ){
sqlite3ExprCachePush(pParse);
sqlite3ExprCode(pParse, pEList->a[nExpr-1].pExpr, target);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
}else{
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
}
@@ -3545,7 +3546,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
break;
}
case TK_OR: {
@@ -3553,7 +3554,7 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfTrue(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
break;
}
case TK_NOT: {
@@ -3699,7 +3700,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull);
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
break;
}
case TK_OR: {
@@ -3709,7 +3710,7 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
sqlite3ExprCachePush(pParse);
sqlite3ExprIfFalse(pParse, pExpr->pRight, dest, jumpIfNull);
sqlite3VdbeResolveLabel(v, d2);
sqlite3ExprCachePop(pParse);
sqlite3ExprCachePop(pParse, 1);
break;
}
case TK_NOT: {
+2 -2
View File
@@ -233,8 +233,8 @@ int sqlite3FkLocateIndex(
if( zKey==0 ){
/* If zKey is NULL, then this foreign key is implicitly mapped to
** the PRIMARY KEY of table pParent. The PRIMARY KEY index may be
** identified by the test. */
if( IsPrimaryKeyIndex(pIdx) ){
** identified by the test (Index.autoIndex==2). */
if( pIdx->autoIndex==2 ){
if( aiCol ){
int i;
for(i=0; i<nCol; i++) aiCol[i] = pFKey->aCol[i].iFrom;
+1 -1
View File
@@ -1541,7 +1541,7 @@ static void groupConcatStep(
}
zVal = (char*)sqlite3_value_text(argv[0]);
nVal = sqlite3_value_bytes(argv[0]);
if( zVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
if( nVal ) sqlite3StrAccumAppend(pAccum, zVal, nVal);
}
}
static void groupConcatFinalize(sqlite3_context *context){
+3 -10
View File
@@ -173,22 +173,15 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
0, /* isMutexInit */
0, /* isMallocInit */
0, /* isPCacheInit */
0, /* nRefInitMutex */
0, /* pInitMutex */
0, /* nRefInitMutex */
0, /* xLog */
0, /* pLogArg */
0, /* bLocaltimeFault */
#ifdef SQLITE_ENABLE_SQLLOG
0, /* xSqllog */
0, /* pSqllogArg */
0 /* pSqllogArg */
#endif
#ifdef SQLITE_VDBE_COVERAGE
0, /* xVdbeBranch */
0, /* pVbeBranchArg */
#endif
#ifndef SQLITE_OMIT_BUILTIN_TEST
0, /* xTestCallback */
#endif
0 /* bLocaltimeFault */
};
/*
+6 -16
View File
@@ -614,7 +614,6 @@ void sqlite3Insert(
if( j>=pTab->nCol ){
if( sqlite3IsRowid(pColumn->a[i].zName) && !withoutRowid ){
ipkColumn = i;
bIdListInOrder = 0;
}else{
sqlite3ErrorMsg(pParse, "table %S has no column named %s",
pTabList, 0, pColumn->a[i].zName);
@@ -1463,7 +1462,7 @@ void sqlite3GenerateConstraintChecks(
** KEY values of this row before the update. */
int addrJump = sqlite3VdbeCurrentAddr(v)+pPk->nKeyCol;
int op = OP_Ne;
int regCmp = (IsPrimaryKeyIndex(pIdx) ? regIdx : regR);
int regCmp = (pIdx->autoIndex==2 ? regIdx : regR);
for(i=0; i<pPk->nKeyCol; i++){
char *p4 = (char*)sqlite3LocateCollSeq(pParse, pPk->azColl[i]);
@@ -1564,7 +1563,7 @@ void sqlite3CompleteInsertion(
sqlite3VdbeAddOp2(v, OP_IdxInsert, iIdxCur+i, aRegIdx[i]);
pik_flags = 0;
if( useSeekResult ) pik_flags = OPFLAG_USESEEKRESULT;
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) ){
if( pIdx->autoIndex==2 && !HasRowid(pTab) ){
assert( pParse->nested==0 );
pik_flags |= OPFLAG_NCHANGE;
}
@@ -1650,7 +1649,7 @@ int sqlite3OpenTableAndIndices(
for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
int iIdxCur = iBase++;
assert( pIdx->pSchema==pTab->pSchema );
if( IsPrimaryKeyIndex(pIdx) && !HasRowid(pTab) && piDataCur ){
if( pIdx->autoIndex==2 && !HasRowid(pTab) && piDataCur ){
*piDataCur = iIdxCur;
}
if( aToOpen==0 || aToOpen[i+1] ){
@@ -1866,24 +1865,15 @@ static int xferOptimization(
return 0; /* Both tables must have the same INTEGER PRIMARY KEY */
}
for(i=0; i<pDest->nCol; i++){
Column *pDestCol = &pDest->aCol[i];
Column *pSrcCol = &pSrc->aCol[i];
if( pDestCol->affinity!=pSrcCol->affinity ){
if( pDest->aCol[i].affinity!=pSrc->aCol[i].affinity ){
return 0; /* Affinity must be the same on all columns */
}
if( !xferCompatibleCollation(pDestCol->zColl, pSrcCol->zColl) ){
if( !xferCompatibleCollation(pDest->aCol[i].zColl, pSrc->aCol[i].zColl) ){
return 0; /* Collating sequence must be the same on all columns */
}
if( pDestCol->notNull && !pSrcCol->notNull ){
if( pDest->aCol[i].notNull && !pSrc->aCol[i].notNull ){
return 0; /* tab2 must be NOT NULL if tab1 is */
}
/* Default values for second and subsequent columns need to match. */
if( i>0
&& ((pDestCol->zDflt==0)!=(pSrcCol->zDflt==0)
|| (pDestCol->zDflt && strcmp(pDestCol->zDflt, pSrcCol->zDflt)!=0))
){
return 0; /* Default values must be the same for all columns */
}
}
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
if( pDestIdx->onError!=OE_None ){
+1 -39
View File
@@ -3114,28 +3114,6 @@ int sqlite3_test_control(int op, ...){
break;
}
/*
** sqlite3_test_control(FAULT_INSTALL, xCallback)
**
** Arrange to invoke xCallback() whenever sqlite3FaultSim() is called,
** if xCallback is not NULL.
**
** As a test of the fault simulator mechanism itself, sqlite3FaultSim(0)
** is called immediately after installing the new callback and the return
** value from sqlite3FaultSim(0) becomes the return from
** sqlite3_test_control().
*/
case SQLITE_TESTCTRL_FAULT_INSTALL: {
/* MSVC is picky about pulling func ptrs from va lists.
** http://support.microsoft.com/kb/47961
** sqlite3Config.xTestCallback = va_arg(ap, int(*)(int));
*/
typedef int(*TESTCALLBACKFUNC_t)(int);
sqlite3Config.xTestCallback = va_arg(ap, TESTCALLBACKFUNC_t);
rc = sqlite3FaultSim(0);
break;
}
/*
** sqlite3_test_control(BENIGN_MALLOC_HOOKS, xBegin, xEnd)
**
@@ -3227,22 +3205,6 @@ int sqlite3_test_control(int op, ...){
break;
}
/*
** sqlite3_test_control(SQLITE_TESTCTRL_BYTEORDER);
**
** The integer returned reveals the byte-order of the computer on which
** SQLite is running:
**
** 1 big-endian, determined at run-time
** 10 little-endian, determined at run-time
** 432101 big-endian, determined at compile-time
** 123410 little-endian, determined at compile-time
*/
case SQLITE_TESTCTRL_BYTEORDER: {
rc = SQLITE_BYTEORDER*100 + SQLITE_LITTLEENDIAN*10 + SQLITE_BIGENDIAN;
break;
}
/* sqlite3_test_control(SQLITE_TESTCTRL_RESERVE, sqlite3 *db, int N)
**
** Set the nReserve size to N for the main database on the database
@@ -3445,5 +3407,5 @@ const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
*/
int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
Btree *pBt = sqlite3DbNameToBtree(db, zDbName);
return pBt ? sqlite3BtreeIsReadonly(pBt) : -1;
return pBt ? sqlite3PagerIsreadonly(sqlite3BtreePager(pBt)) : -1;
}
+1 -1
View File
@@ -248,7 +248,7 @@ static void *memsys5MallocUnsafe(int nByte){
** block. If not, then split a block of the next larger power of
** two in order to create a new free block of size iLogsize.
*/
for(iBin=iLogsize; iBin<=LOGMAX && mem5.aiFreelist[iBin]<0; iBin++){}
for(iBin=iLogsize; mem5.aiFreelist[iBin]<0 && iBin<=LOGMAX; iBin++){}
if( iBin>LOGMAX ){
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(SQLITE_NOMEM, "failed to allocate %u bytes", nByte);
-7
View File
@@ -13,13 +13,6 @@
*/
#include "sqliteInt.h"
#if SQLITE_OS_WIN
/*
** Include the header file for the Windows VFS.
*/
#include "os_win.h"
#endif
/*
** The code in this file is only used if we are compiling multithreaded
** on a win32 system.
+76 -3
View File
@@ -21,10 +21,83 @@
#define _SQLITE_OS_H_
/*
** Attempt to automatically detect the operating system and setup the
** necessary pre-processor macros for it.
** Figure out if we are dealing with Unix, Windows, or some other
** operating system. After the following block of preprocess macros,
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
** will defined to either 1 or 0. One of the four will be 1. The other
** three will be 0.
*/
#include "os_setup.h"
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
# undef SQLITE_OS_UNIX
# define SQLITE_OS_UNIX 0
# undef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# else
# undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
# define SQLITE_OS_UNIX 0
# else
# define SQLITE_OS_WIN 0
# define SQLITE_OS_UNIX 1
# endif
# else
# define SQLITE_OS_UNIX 0
# endif
#else
# ifndef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# endif
#endif
#if SQLITE_OS_WIN
# include <windows.h>
#endif
/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for win98 or winNT
** using the _WIN32_WINNT macro as follows:
**
** #if defined(_WIN32_WINNT)
** # define SQLITE_OS_WINNT 1
** #else
** # define SQLITE_OS_WINNT 0
** #endif
**
** However, vs2005 does not set _WIN32_WINNT by default, as it ought to,
** so the above test does not work. We'll just assume that everything is
** winNT unless the programmer explicitly says otherwise by setting
** SQLITE_OS_WINNT to 0.
*/
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
# define SQLITE_OS_WINNT 1
#endif
/*
** Determine if we are dealing with WindowsCE - which has a much
** reduced API.
*/
#if defined(_WIN32_WCE)
# define SQLITE_OS_WINCE 1
#else
# define SQLITE_OS_WINCE 0
#endif
/*
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif
/* If the SET_FULLSYNC macro is not defined above, then make it
** a no-op
-57
View File
@@ -1,57 +0,0 @@
/*
** 2013 November 25
**
** 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 pre-processor directives related to operating system
** detection and/or setup.
*/
#ifndef _OS_SETUP_H_
#define _OS_SETUP_H_
/*
** Figure out if we are dealing with Unix, Windows, or some other operating
** system.
**
** After the following block of preprocess macros, all of SQLITE_OS_UNIX,
** SQLITE_OS_WIN, and SQLITE_OS_OTHER will defined to either 1 or 0. One of
** the three will be 1. The other two will be 0.
*/
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
# undef SQLITE_OS_UNIX
# define SQLITE_OS_UNIX 0
# undef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# else
# undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) || \
defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
# define SQLITE_OS_UNIX 0
# else
# define SQLITE_OS_WIN 0
# define SQLITE_OS_UNIX 1
# endif
# else
# define SQLITE_OS_UNIX 0
# endif
#else
# ifndef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# endif
#endif
#endif /* _OS_SETUP_H_ */
+27 -70
View File
@@ -15,16 +15,16 @@
#include "sqliteInt.h"
#if SQLITE_OS_WIN /* This file is used for Windows only */
#ifdef __CYGWIN__
# include <sys/cygwin.h>
# include <errno.h> /* amalgamator: keep */
#endif
/*
** Include code that is common to all os_*.c files
*/
#include "os_common.h"
/*
** Include the header file for the Windows VFS.
*/
#include "os_win.h"
/*
** Compiling and using WAL mode requires several APIs that are only
** available in Windows platforms based on the NT kernel.
@@ -1279,6 +1279,13 @@ void sqlite3_win32_sleep(DWORD milliseconds){
#endif
}
DWORD sqlite3Win32Wait(HANDLE hObject){
DWORD rc;
while( (rc = osWaitForSingleObjectEx(hObject, INFINITE,
TRUE))==WAIT_IO_COMPLETION ){}
return rc;
}
/*
** Return true (non-zero) if we are running under WinNT, Win2K, WinXP,
** or WinCE. Return false (zero) for Win95, Win98, or WinME.
@@ -1836,32 +1843,6 @@ static int winLogErrorAtLine(
static int winIoerrRetry = SQLITE_WIN32_IOERR_RETRY;
static int winIoerrRetryDelay = SQLITE_WIN32_IOERR_RETRY_DELAY;
/*
** The "winIoerrCanRetry1" macro is used to determine if a particular I/O
** error code obtained via GetLastError() is eligible to be retried. It
** must accept the error code DWORD as its only argument and should return
** non-zero if the error code is transient in nature and the operation
** responsible for generating the original error might succeed upon being
** retried. The argument to this macro should be a variable.
**
** Additionally, a macro named "winIoerrCanRetry2" may be defined. If it
** is defined, it will be consulted only when the macro "winIoerrCanRetry1"
** returns zero. The "winIoerrCanRetry2" macro is completely optional and
** may be used to include additional error codes in the set that should
** result in the failing I/O operation being retried by the caller. If
** defined, the "winIoerrCanRetry2" macro must exhibit external semantics
** identical to those of the "winIoerrCanRetry1" macro.
*/
#if !defined(winIoerrCanRetry1)
#define winIoerrCanRetry1(a) (((a)==ERROR_ACCESS_DENIED) || \
((a)==ERROR_SHARING_VIOLATION) || \
((a)==ERROR_LOCK_VIOLATION) || \
((a)==ERROR_DEV_NOT_EXIST) || \
((a)==ERROR_NETNAME_DELETED) || \
((a)==ERROR_SEM_TIMEOUT) || \
((a)==ERROR_NETWORK_UNREACHABLE))
#endif
/*
** If a ReadFile() or WriteFile() error occurs, invoke this routine
** to see if it should be retried. Return TRUE to retry. Return FALSE
@@ -1875,18 +1856,13 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
}
return 0;
}
if( winIoerrCanRetry1(e) ){
if( e==ERROR_ACCESS_DENIED ||
e==ERROR_LOCK_VIOLATION ||
e==ERROR_SHARING_VIOLATION ){
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
#if defined(winIoerrCanRetry2)
else if( winIoerrCanRetry2(e) ){
sqlite3_win32_sleep(winIoerrRetryDelay*(1+*pnRetry));
++*pnRetry;
return 1;
}
#endif
if( pError ){
*pError = e;
}
@@ -2825,7 +2801,7 @@ static int winGetReadLock(winFile *pFile){
pFile->lastErrno = osGetLastError();
/* No need to log a failure to lock */
}
OSTRACE(("READ-LOCK file=%p, result=%d\n", pFile->h, res));
OSTRACE(("READ-LOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
return res;
}
@@ -2849,7 +2825,7 @@ static int winUnlockReadLock(winFile *pFile){
winLogError(SQLITE_IOERR_UNLOCK, pFile->lastErrno,
"winUnlockReadLock", pFile->zPath);
}
OSTRACE(("READ-UNLOCK file=%p, result=%d\n", pFile->h, res));
OSTRACE(("READ-UNLOCK file=%p, rc=%s\n", pFile->h, sqlite3ErrName(res)));
return res;
}
@@ -2924,16 +2900,8 @@ static int winLock(sqlite3_file *id, int locktype){
** If you are using this code as a model for alternative VFSes, do not
** copy this retry logic. It is a hack intended for Windows only.
*/
lastErrno = osGetLastError();
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
pFile->h, cnt, res));
if( lastErrno==ERROR_INVALID_HANDLE ){
pFile->lastErrno = lastErrno;
rc = SQLITE_IOERR_LOCK;
OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
pFile->h, cnt, sqlite3ErrName(rc)));
return rc;
}
OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, rc=%s\n",
pFile->h, cnt, sqlite3ErrName(res)));
if( cnt ) sqlite3_win32_sleep(1);
}
gotPendingLock = res;
@@ -3018,7 +2986,7 @@ static int winLock(sqlite3_file *id, int locktype){
** non-zero, otherwise zero.
*/
static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
int res;
int rc;
winFile *pFile = (winFile*)id;
SimulateIOError( return SQLITE_IOERR_CHECKRESERVEDLOCK; );
@@ -3026,17 +2994,17 @@ static int winCheckReservedLock(sqlite3_file *id, int *pResOut){
assert( id!=0 );
if( pFile->locktype>=RESERVED_LOCK ){
res = 1;
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (local)\n", pFile->h, res));
rc = 1;
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (local)\n", pFile->h, rc));
}else{
res = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
if( res ){
rc = winLockFile(&pFile->h, SQLITE_LOCKFILEEX_FLAGS,RESERVED_BYTE, 0, 1, 0);
if( rc ){
winUnlockFile(&pFile->h, RESERVED_BYTE, 0, 1, 0);
}
res = !res;
OSTRACE(("TEST-WR-LOCK file=%p, result=%d (remote)\n", pFile->h, res));
rc = !rc;
OSTRACE(("TEST-WR-LOCK file=%p, rc=%d (remote)\n", pFile->h, rc));
}
*pResOut = res;
*pResOut = rc;
OSTRACE(("TEST-WR-LOCK file=%p, pResOut=%p, *pResOut=%d, rc=SQLITE_OK\n",
pFile->h, pResOut, *pResOut));
return SQLITE_OK;
@@ -3177,17 +3145,6 @@ static int winFileControl(sqlite3_file *id, int op, void *pArg){
OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
return SQLITE_OK;
}
#ifdef SQLITE_TEST
case SQLITE_FCNTL_WIN32_SET_HANDLE: {
LPHANDLE phFile = (LPHANDLE)pArg;
HANDLE hOldFile = pFile->h;
pFile->h = *phFile;
*phFile = hOldFile;
OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
hOldFile, pFile->h));
return SQLITE_OK;
}
#endif
case SQLITE_FCNTL_TEMPFILENAME: {
char *zTFile = 0;
int rc = winGetTempname(pFile->pVfs, &zTFile);
-67
View File
@@ -1,67 +0,0 @@
/*
** 2013 November 25
**
** 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 code that is specific to Windows.
*/
#ifndef _OS_WIN_H_
#define _OS_WIN_H_
/*
** Include the primary Windows SDK header file.
*/
#include "windows.h"
#ifdef __CYGWIN__
# include <sys/cygwin.h>
# include <errno.h> /* amalgamator: dontcache */
#endif
/*
** Determine if we are dealing with Windows NT.
**
** We ought to be able to determine if we are compiling for Windows 9x or
** Windows NT using the _WIN32_WINNT macro as follows:
**
** #if defined(_WIN32_WINNT)
** # define SQLITE_OS_WINNT 1
** #else
** # define SQLITE_OS_WINNT 0
** #endif
**
** However, Visual Studio 2005 does not set _WIN32_WINNT by default, as
** it ought to, so the above test does not work. We'll just assume that
** everything is Windows NT unless the programmer explicitly says otherwise
** by setting SQLITE_OS_WINNT to 0.
*/
#if SQLITE_OS_WIN && !defined(SQLITE_OS_WINNT)
# define SQLITE_OS_WINNT 1
#endif
/*
** Determine if we are dealing with Windows CE - which has a much reduced
** API.
*/
#if defined(_WIN32_WCE)
# define SQLITE_OS_WINCE 1
#else
# define SQLITE_OS_WINCE 0
#endif
/*
** Determine if we are dealing with WinRT, which provides only a subset of
** the full Win32 API.
*/
#if !defined(SQLITE_OS_WINRT)
# define SQLITE_OS_WINRT 0
#endif
#endif /* _OS_WIN_H_ */
+29 -38
View File
@@ -626,8 +626,7 @@ struct Pager {
u8 ckptSyncFlags; /* SYNC_NORMAL or SYNC_FULL for checkpoint */
u8 walSyncFlags; /* SYNC_NORMAL or SYNC_FULL for wal writes */
u8 syncFlags; /* SYNC_NORMAL or SYNC_FULL otherwise */
u8 tempFile; /* zFilename is a temporary or immutable file */
u8 noLock; /* Do not lock (except in WAL mode) */
u8 tempFile; /* zFilename is a temporary file */
u8 readOnly; /* True for a read-only database */
u8 memDb; /* True to inhibit all file I/O */
@@ -1092,7 +1091,7 @@ static int pagerUnlockDb(Pager *pPager, int eLock){
assert( eLock!=NO_LOCK || pagerUseWal(pPager)==0 );
if( isOpen(pPager->fd) ){
assert( pPager->eLock>=eLock );
rc = pPager->noLock ? SQLITE_OK : sqlite3OsUnlock(pPager->fd, eLock);
rc = sqlite3OsUnlock(pPager->fd, eLock);
if( pPager->eLock!=UNKNOWN_LOCK ){
pPager->eLock = (u8)eLock;
}
@@ -1116,7 +1115,7 @@ static int pagerLockDb(Pager *pPager, int eLock){
assert( eLock==SHARED_LOCK || eLock==RESERVED_LOCK || eLock==EXCLUSIVE_LOCK );
if( pPager->eLock<eLock || pPager->eLock==UNKNOWN_LOCK ){
rc = pPager->noLock ? SQLITE_OK : sqlite3OsLock(pPager->fd, eLock);
rc = sqlite3OsLock(pPager->fd, eLock);
if( rc==SQLITE_OK && (pPager->eLock!=UNKNOWN_LOCK||eLock==EXCLUSIVE_LOCK) ){
pPager->eLock = (u8)eLock;
IOTRACE(("LOCK %p %d\n", pPager, eLock))
@@ -1625,11 +1624,12 @@ static int writeMasterJournal(Pager *pPager, const char *zMaster){
if( !zMaster
|| pPager->journalMode==PAGER_JOURNALMODE_MEMORY
|| !isOpen(pPager->jfd)
|| pPager->journalMode==PAGER_JOURNALMODE_OFF
){
return SQLITE_OK;
}
pPager->setMaster = 1;
assert( isOpen(pPager->jfd) );
assert( pPager->journalHdr <= pPager->journalOff );
/* Calculate the length in bytes and the checksum of zMaster */
@@ -4675,38 +4675,30 @@ int sqlite3PagerOpen(
** + The value returned by sqlite3OsSectorSize()
** + The largest page size that can be written atomically.
*/
if( rc==SQLITE_OK ){
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
if( !readOnly ){
setSectorSize(pPager);
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
if( szPageDflt<pPager->sectorSize ){
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
}else{
szPageDflt = (u32)pPager->sectorSize;
}
if( rc==SQLITE_OK && !readOnly ){
setSectorSize(pPager);
assert(SQLITE_DEFAULT_PAGE_SIZE<=SQLITE_MAX_DEFAULT_PAGE_SIZE);
if( szPageDflt<pPager->sectorSize ){
if( pPager->sectorSize>SQLITE_MAX_DEFAULT_PAGE_SIZE ){
szPageDflt = SQLITE_MAX_DEFAULT_PAGE_SIZE;
}else{
szPageDflt = (u32)pPager->sectorSize;
}
}
#ifdef SQLITE_ENABLE_ATOMIC_WRITE
{
int ii;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
szPageDflt = ii;
}
{
int iDc = sqlite3OsDeviceCharacteristics(pPager->fd);
int ii;
assert(SQLITE_IOCAP_ATOMIC512==(512>>8));
assert(SQLITE_IOCAP_ATOMIC64K==(65536>>8));
assert(SQLITE_MAX_DEFAULT_PAGE_SIZE<=65536);
for(ii=szPageDflt; ii<=SQLITE_MAX_DEFAULT_PAGE_SIZE; ii=ii*2){
if( iDc&(SQLITE_IOCAP_ATOMIC|(ii>>8)) ){
szPageDflt = ii;
}
}
}
#endif
}
pPager->noLock = sqlite3_uri_boolean(zFilename, "nolock", 0);
if( (iDc & SQLITE_IOCAP_IMMUTABLE)!=0
|| sqlite3_uri_boolean(zFilename, "immutable", 0) ){
vfsFlags |= SQLITE_OPEN_READONLY;
goto act_like_temp_file;
}
}
}else{
/* If a temporary file is requested, it is not opened immediately.
@@ -4716,14 +4708,10 @@ int sqlite3PagerOpen(
** This branch is also run for an in-memory database. An in-memory
** database is the same as a temp-file that is never written out to
** disk and uses an in-memory rollback journal.
**
** This branch also runs for files marked as immutable.
*/
act_like_temp_file:
tempFile = 1;
pPager->eState = PAGER_READER; /* Pretend we already have a lock */
pPager->eLock = EXCLUSIVE_LOCK; /* Pretend we are in EXCLUSIVE locking mode */
pPager->noLock = 1; /* Do no locking */
pPager->eState = PAGER_READER;
pPager->eLock = EXCLUSIVE_LOCK;
readOnly = (vfsFlags&SQLITE_OPEN_READONLY);
}
@@ -4764,6 +4752,9 @@ act_like_temp_file:
/* pPager->nPage = 0; */
pPager->mxPgno = SQLITE_MAX_PAGE_COUNT;
/* pPager->state = PAGER_UNLOCK; */
#if 0
assert( pPager->state == (tempFile ? PAGER_EXCLUSIVE : PAGER_UNLOCK) );
#endif
/* pPager->errMask = 0; */
pPager->tempFile = (u8)tempFile;
assert( tempFile==PAGER_LOCKINGMODE_NORMAL
+3 -5
View File
@@ -1488,15 +1488,13 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Null, 0, 2);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pTab->szTabRow), 3);
sqlite3VdbeAddOp2(v, OP_Integer,
(int)sqlite3LogEstToInt(pTab->nRowLogEst), 4);
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)sqlite3LogEstToInt(pIdx->aiRowLogEst[0]), 4);
sqlite3VdbeAddOp2(v, OP_Integer, (int)pIdx->aiRowEst[0], 4);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 4);
}
}
@@ -1930,7 +1928,7 @@ void sqlite3Pragma(
sqlite3VdbeAddOp0(v, OP_Halt);
sqlite3VdbeJumpHere(v, jmp4);
sqlite3VdbeJumpHere(v, jmp2);
sqlite3ResolvePartIdxLabel(pParse, jmp3);
sqlite3VdbeResolveLabel(v, jmp3);
}
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
+3 -3
View File
@@ -112,8 +112,8 @@ struct RowSet {
struct RowSetEntry *pFresh; /* Source of new entry objects */
struct RowSetEntry *pForest; /* List of binary trees of entries */
u16 nFresh; /* Number of objects on pFresh */
u16 rsFlags; /* Various flags */
int iBatch; /* Current insert batch */
u8 rsFlags; /* Various flags */
u8 iBatch; /* Current insert batch */
};
/*
@@ -447,7 +447,7 @@ int sqlite3RowSetNext(RowSet *p, i64 *pRowid){
** on pRowSet->pEntry, then sort those entires into the forest at
** pRowSet->pForest so that they can be tested.
*/
int sqlite3RowSetTest(RowSet *pRowSet, int iBatch, sqlite3_int64 iRowid){
int sqlite3RowSetTest(RowSet *pRowSet, u8 iBatch, sqlite3_int64 iRowid){
struct RowSetEntry *p, *pTree;
/* This routine is never called after sqlite3RowSetNext() */
+114 -98
View File
@@ -455,28 +455,42 @@ static KeyInfo *keyInfoFromExprList(
);
/*
** Insert code into "v" that will push the record in register regData
** into the sorter.
** Generate code that will push the record in registers regData
** through regData+nData-1 onto the sorter.
*/
static void pushOntoSorter(
Parse *pParse, /* Parser context */
SortCtx *pSort, /* Information about the ORDER BY clause */
Select *pSelect, /* The whole SELECT statement */
int regData /* Register holding data to be sorted */
int regData, /* First register holding data to be sorted */
int nData, /* Number of elements in the data array */
int nPrefixReg /* No. of reg prior to regData available for use */
){
Vdbe *v = pParse->pVdbe;
int nExpr = pSort->pOrderBy->nExpr;
int regRecord = ++pParse->nMem;
int regBase = pParse->nMem+1;
int nOBSat = pSort->nOBSat;
int op;
Vdbe *v = pParse->pVdbe; /* Stmt under construction */
int bSeq = ((pSort->sortFlags & SORTFLAG_UseSorter)==0);
int nExpr = pSort->pOrderBy->nExpr; /* No. of ORDER BY terms */
int nBase = nExpr + bSeq + nData; /* Fields in sorter record */
int regBase; /* Regs for sorter record */
int regRecord = sqlite3GetTempReg(pParse); /* Assembled sorter record */
int nOBSat = pSort->nOBSat; /* ORDER BY terms to skip */
int op; /* Opcode to add sorter record to sorter */
pParse->nMem += nExpr+2; /* nExpr+2 registers allocated at regBase */
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nExpr+2-nOBSat,regRecord);
assert( bSeq==0 || bSeq==1 );
if( nPrefixReg ){
assert( nPrefixReg==nExpr+bSeq );
regBase = regData - nExpr - bSeq;
}else{
regBase = sqlite3GetTempRange(pParse, nBase);
}
sqlite3ExprCodeExprList(pParse, pSort->pOrderBy, regBase, SQLITE_ECEL_DUP);
if( bSeq ){
sqlite3VdbeAddOp2(v, OP_Sequence, pSort->iECursor, regBase+nExpr);
}
if( nPrefixReg==0 ){
sqlite3VdbeAddOp3(v, OP_Move, regData, regBase+nExpr+bSeq, nData);
}
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase+nOBSat, nBase-nOBSat, regRecord);
if( nOBSat>0 ){
int regPrevKey; /* The first nOBSat columns of the previous row */
int addrFirst; /* Address of the OP_IfNot opcode */
@@ -487,8 +501,13 @@ static void pushOntoSorter(
regPrevKey = pParse->nMem+1;
pParse->nMem += pSort->nOBSat;
nKey = nExpr - pSort->nOBSat + 1;
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr); VdbeCoverage(v);
nKey = nExpr - pSort->nOBSat + bSeq;
if( bSeq ){
addrFirst = sqlite3VdbeAddOp1(v, OP_IfNot, regBase+nExpr);
}else{
addrFirst = sqlite3VdbeAddOp1(v, OP_SequenceTest, pSort->iECursor);
}
VdbeCoverage(v);
sqlite3VdbeAddOp3(v, OP_Compare, regPrevKey, regBase, pSort->nOBSat);
pOp = sqlite3VdbeGetOp(v, pSort->addrSortIndex);
if( pParse->db->mallocFailed ) return;
@@ -513,6 +532,12 @@ static void pushOntoSorter(
op = OP_IdxInsert;
}
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
if( nOBSat==0 ){
sqlite3ReleaseTempReg(pParse, regRecord);
if( nPrefixReg==0 ){
sqlite3ReleaseTempRange(pParse, regBase, nBase);
}
}
if( pSelect->iLimit ){
int addr1, addr2;
int iLimit;
@@ -627,6 +652,7 @@ static void selectInnerLoop(
int eDest = pDest->eDest; /* How to dispose of results */
int iParm = pDest->iSDParm; /* First argument to disposal method */
int nResultCol; /* Number of result columns */
int nPrefixReg = 0; /* Number of extra registers before regResult */
assert( v );
assert( pEList!=0 );
@@ -642,6 +668,11 @@ static void selectInnerLoop(
nResultCol = pEList->nExpr;
if( pDest->iSdst==0 ){
if( pSort ){
nPrefixReg = pSort->pOrderBy->nExpr;
if( !(pSort->sortFlags & SORTFLAG_UseSorter) ) nPrefixReg++;
pParse->nMem += nPrefixReg;
}
pDest->iSdst = pParse->nMem+1;
pParse->nMem += nResultCol;
}else if( pDest->iSdst+nResultCol > pParse->nMem ){
@@ -758,10 +789,10 @@ static void selectInnerLoop(
case SRT_DistFifo:
case SRT_Table:
case SRT_EphemTab: {
int r1 = sqlite3GetTempReg(pParse);
int r1 = sqlite3GetTempRange(pParse, nPrefixReg+1);
testcase( eDest==SRT_Table );
testcase( eDest==SRT_EphemTab );
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg);
#ifndef SQLITE_OMIT_CTE
if( eDest==SRT_DistFifo ){
/* If the destination is DistFifo, then cursor (iParm+1) is open
@@ -776,7 +807,7 @@ static void selectInnerLoop(
}
#endif
if( pSort ){
pushOntoSorter(pParse, pSort, p, r1);
pushOntoSorter(pParse, pSort, p, r1+nPrefixReg, 1, nPrefixReg);
}else{
int r2 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
@@ -784,7 +815,7 @@ static void selectInnerLoop(
sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
sqlite3ReleaseTempReg(pParse, r2);
}
sqlite3ReleaseTempReg(pParse, r1);
sqlite3ReleaseTempRange(pParse, r1, nPrefixReg+1);
break;
}
@@ -802,7 +833,7 @@ static void selectInnerLoop(
** ORDER BY in this case since the order of entries in the set
** does not matter. But there might be a LIMIT clause, in which
** case the order does matter */
pushOntoSorter(pParse, pSort, p, regResult);
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg);
}else{
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult,1,r1, &pDest->affSdst, 1);
@@ -828,7 +859,7 @@ static void selectInnerLoop(
case SRT_Mem: {
assert( nResultCol==1 );
if( pSort ){
pushOntoSorter(pParse, pSort, p, regResult);
pushOntoSorter(pParse, pSort, p, regResult, 1, nPrefixReg);
}else{
sqlite3ExprCodeMove(pParse, regResult, iParm, 1);
/* The LIMIT clause will jump out of the loop for us */
@@ -842,10 +873,7 @@ static void selectInnerLoop(
testcase( eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
if( pSort ){
int r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1);
pushOntoSorter(pParse, pSort, p, r1);
sqlite3ReleaseTempReg(pParse, r1);
pushOntoSorter(pParse, pSort, p, regResult, nResultCol, nPrefixReg);
}else if( eDest==SRT_Coroutine ){
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
}else{
@@ -1125,46 +1153,62 @@ static void generateSortTail(
int addr;
int addrOnce = 0;
int iTab;
int pseudoTab = 0;
ExprList *pOrderBy = pSort->pOrderBy;
int eDest = pDest->eDest;
int iParm = pDest->iSDParm;
int regRow;
int regRowid;
int nKey;
int iSortTab; /* Sorter cursor to read from */
int nSortData; /* Trailing values to read from sorter */
u8 p5; /* p5 parameter for 1st OP_Column */
int i;
int bSeq; /* True if sorter record includes seq. no. */
#ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS
struct ExprList_item *aOutEx = p->pEList->a;
#endif
if( pSort->labelBkOut ){
sqlite3VdbeAddOp2(v, OP_Gosub, pSort->regReturn, pSort->labelBkOut);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addrBreak);
sqlite3VdbeResolveLabel(v, pSort->labelBkOut);
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
iTab = pSort->iECursor;
regRow = sqlite3GetTempReg(pParse);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
pseudoTab = pParse->nTab++;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, pseudoTab, regRow, nColumn);
regRowid = 0;
regRow = pDest->iSdst;
nSortData = nColumn;
}else{
regRowid = sqlite3GetTempReg(pParse);
regRow = sqlite3GetTempReg(pParse);
nSortData = 1;
}
nKey = pOrderBy->nExpr - pSort->nOBSat;
if( pSort->sortFlags & SORTFLAG_UseSorter ){
int regSortOut = ++pParse->nMem;
int ptab2 = pParse->nTab++;
sqlite3VdbeAddOp3(v, OP_OpenPseudo, ptab2, regSortOut, nKey+2);
iSortTab = pParse->nTab++;
if( pSort->labelBkOut ){
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
}
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_SorterSort, iTab, addrBreak);
VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp2(v, OP_SorterData, iTab, regSortOut);
sqlite3VdbeAddOp3(v, OP_Column, ptab2, nKey+1, regRow);
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
p5 = OPFLAG_CLEARCACHE;
bSeq = 0;
}else{
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, addrBreak); VdbeCoverage(v);
codeOffset(v, p->iOffset, addrContinue);
sqlite3VdbeAddOp3(v, OP_Column, iTab, nKey+1, regRow);
iSortTab = iTab;
p5 = 0;
bSeq = 1;
}
for(i=0; i<nSortData; i++){
sqlite3VdbeAddOp3(v, OP_Column, iSortTab, nKey+bSeq+i, regRow+i);
if( i==0 ) sqlite3VdbeChangeP5(v, p5);
VdbeComment((v, "%s", aOutEx[i].zName ? aOutEx[i].zName : aOutEx[i].zSpan));
}
switch( eDest ){
case SRT_Table:
@@ -1193,17 +1237,9 @@ static void generateSortTail(
}
#endif
default: {
int i;
assert( eDest==SRT_Output || eDest==SRT_Coroutine );
testcase( eDest==SRT_Output );
testcase( eDest==SRT_Coroutine );
for(i=0; i<nColumn; i++){
assert( regRow!=pDest->iSdst+i );
sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iSdst+i);
if( i==0 ){
sqlite3VdbeChangeP5(v, OPFLAG_CLEARCACHE);
}
}
if( eDest==SRT_Output ){
sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iSdst, nColumn);
sqlite3ExprCacheAffinityChange(pParse, pDest->iSdst, nColumn);
@@ -1213,9 +1249,10 @@ static void generateSortTail(
break;
}
}
sqlite3ReleaseTempReg(pParse, regRow);
sqlite3ReleaseTempReg(pParse, regRowid);
if( regRowid ){
sqlite3ReleaseTempReg(pParse, regRow);
sqlite3ReleaseTempReg(pParse, regRowid);
}
/* The bottom of the loop
*/
sqlite3VdbeResolveLabel(v, addrContinue);
@@ -1226,9 +1263,6 @@ static void generateSortTail(
}
if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
sqlite3VdbeResolveLabel(v, addrBreak);
if( eDest==SRT_Output || eDest==SRT_Coroutine ){
sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
}
}
/*
@@ -1688,7 +1722,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect){
assert( db->lookaside.bEnabled==0 );
pTab->nRef = 1;
pTab->zName = 0;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->nRowEst = 1048576;
selectColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol);
selectAddColumnTypeAndCollation(pParse, pTab, pSelect);
pTab->iPKey = -1;
@@ -3827,7 +3861,7 @@ static int withExpand(
pTab->nRef = 1;
pTab->zName = sqlite3DbStrDup(db, pCte->zName);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->nRowEst = 1048576;
pTab->tabFlags |= TF_Ephemeral;
pFrom->pSelect = sqlite3SelectDup(db, pCte->pSelect, 0);
if( db->mallocFailed ) return SQLITE_NOMEM;
@@ -4003,7 +4037,7 @@ static int selectExpander(Walker *pWalker, Select *p){
while( pSel->pPrior ){ pSel = pSel->pPrior; }
selectColumnsFromExprList(pParse, pSel->pEList, &pTab->nCol, &pTab->aCol);
pTab->iPKey = -1;
pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) );
pTab->nRowEst = 1048576;
pTab->tabFlags |= TF_Ephemeral;
#endif
}else{
@@ -4498,11 +4532,10 @@ static void explainSimpleCount(
Index *pIdx /* Index used to optimize scan, or NULL */
){
if( pParse->explain==2 ){
int bCover = (pIdx!=0 && (HasRowid(pTab) || !IsPrimaryKeyIndex(pIdx)));
char *zEqp = sqlite3MPrintf(pParse->db, "SCAN TABLE %s%s%s",
pTab->zName,
bCover ? " USING COVERING INDEX " : "",
bCover ? pIdx->zName : ""
pTab->zName,
pIdx ? " USING COVERING INDEX " : "",
pIdx ? pIdx->zName : ""
);
sqlite3VdbeAddOp4(
pParse->pVdbe, OP_Explain, pParse->iSelectId, 0, 0, zEqp, P4_DYNAMIC
@@ -4654,7 +4687,7 @@ int sqlite3Select(
sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
pItem->viaCoroutine = 1;
pItem->regResult = dest.iSdst;
sqlite3VdbeAddOp1(v, OP_EndCoroutine, pItem->regReturn);
@@ -4685,7 +4718,7 @@ int sqlite3Select(
sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId);
sqlite3Select(pParse, pSub, &dest);
pItem->pTab->nRowLogEst = sqlite3LogEst(pSub->nSelectRow);
pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow;
if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr);
retAddr = sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn);
VdbeComment((v, "end %s", pItem->pTab->zName));
@@ -4718,6 +4751,18 @@ int sqlite3Select(
}
#endif
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then disable the ORDER BY clause since the GROUP BY
** will cause elements to come out in the correct order. This is
** an optimization - the correct answer should result regardless.
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER
** to disable this optimization for testing purposes.
*/
if( sqlite3ExprListCompare(p->pGroupBy, sSort.pOrderBy, -1)==0
&& OptimizationEnabled(db, SQLITE_GroupByOrder) ){
sSort.pOrderBy = 0;
}
/* If the query is DISTINCT with an ORDER BY but is not an aggregate, and
** if the select-list is the same as the ORDER BY list, then this query
** can be rewritten as a GROUP BY. In other words, this:
@@ -4759,8 +4804,9 @@ int sqlite3Select(
sSort.iECursor = pParse->nTab++;
sSort.addrSortIndex =
sqlite3VdbeAddOp4(v, OP_OpenEphemeral,
sSort.iECursor, sSort.pOrderBy->nExpr+2, 0,
(char*)pKeyInfo, P4_KEYINFO);
sSort.iECursor, sSort.pOrderBy->nExpr+1+pEList->nExpr, 0,
(char*)pKeyInfo, P4_KEYINFO
);
}else{
sSort.addrSortIndex = -1;
}
@@ -4846,7 +4892,6 @@ int sqlite3Select(
int addrEnd; /* End of processing for this SELECT */
int sortPTab = 0; /* Pseudotable used to decode sorting results */
int sortOut = 0; /* Output register from the sorter */
int orderByGrp = 0; /* True if the GROUP BY and ORDER BY are the same */
/* Remove any and all aliases between the result set and the
** GROUP BY clause.
@@ -4866,18 +4911,6 @@ int sqlite3Select(
p->nSelectRow = 1;
}
/* If there is both a GROUP BY and an ORDER BY clause and they are
** identical, then it may be possible to disable the ORDER BY clause
** on the grounds that the GROUP BY will cause elements to come out
** in the correct order. It also may not - the GROUP BY may use a
** database index that causes rows to be grouped together as required
** but not actually sorted. Either way, record the fact that the
** ORDER BY and GROUP BY clauses are the same by setting the orderByGrp
** variable. */
if( sqlite3ExprListCompare(pGroupBy, sSort.pOrderBy, -1)==0 ){
orderByGrp = 1;
}
/* Create a label to jump to when we want to abort the query */
addrEnd = sqlite3VdbeMakeLabel(v);
@@ -4891,7 +4924,7 @@ int sqlite3Select(
sNC.pSrcList = pTabList;
sNC.pAggInfo = &sAggInfo;
sAggInfo.mnReg = pParse->nMem+1;
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr+1 : 0;
sAggInfo.nSortingColumn = pGroupBy ? pGroupBy->nExpr : 0;
sAggInfo.pGroupBy = pGroupBy;
sqlite3ExprAnalyzeAggList(&sNC, pEList);
sqlite3ExprAnalyzeAggList(&sNC, sSort.pOrderBy);
@@ -4958,8 +4991,7 @@ int sqlite3Select(
*/
sqlite3VdbeAddOp2(v, OP_Gosub, regReset, addrReset);
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0,
WHERE_GROUPBY | (orderByGrp ? WHERE_SORTBYGROUP : 0), 0
);
WHERE_GROUPBY, 0);
if( pWInfo==0 ) goto select_end;
if( sqlite3WhereIsOrdered(pWInfo)==pGroupBy->nExpr ){
/* The optimizer is able to deliver rows in group by order so
@@ -4984,8 +5016,8 @@ int sqlite3Select(
groupBySort = 1;
nGroupBy = pGroupBy->nExpr;
nCol = nGroupBy + 1;
j = nGroupBy+1;
nCol = nGroupBy;
j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){
if( sAggInfo.aCol[i].iSorterColumn>=j ){
nCol++;
@@ -4995,8 +5027,7 @@ int sqlite3Select(
regBase = sqlite3GetTempRange(pParse, nCol);
sqlite3ExprCacheClear(pParse);
sqlite3ExprCodeExprList(pParse, pGroupBy, regBase, 0);
sqlite3VdbeAddOp2(v, OP_Sequence, sAggInfo.sortingIdx,regBase+nGroupBy);
j = nGroupBy+1;
j = nGroupBy;
for(i=0; i<sAggInfo.nColumn; i++){
struct AggInfo_col *pCol = &sAggInfo.aCol[i];
if( pCol->iSorterColumn>=j ){
@@ -5024,21 +5055,6 @@ int sqlite3Select(
VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v);
sAggInfo.useSortingIdx = 1;
sqlite3ExprCacheClear(pParse);
}
/* If the index or temporary table used by the GROUP BY sort
** will naturally deliver rows in the order required by the ORDER BY
** clause, cancel the ephemeral table open coded earlier.
**
** This is an optimization - the correct answer should result regardless.
** Use the SQLITE_GroupByOrder flag with SQLITE_TESTCTRL_OPTIMIZER to
** disable this optimization for testing purposes. */
if( orderByGrp && OptimizationEnabled(db, SQLITE_GroupByOrder)
&& (groupBySort || sqlite3WhereIsSorted(pWInfo))
){
sSort.pOrderBy = 0;
sqlite3VdbeChangeToNoop(v, sSort.addrSortIndex);
}
/* Evaluate the current GROUP BY terms and store in b0, b1, b2...
+3 -10
View File
@@ -697,8 +697,7 @@ static void output_csv(struct callback_data *p, const char *z, int bSep){
*/
static void interrupt_handler(int NotUsed){
UNUSED_PARAMETER(NotUsed);
seenInterrupt++;
if( seenInterrupt>2 ) exit(1);
seenInterrupt = 1;
if( db ) sqlite3_interrupt(db);
}
#endif
@@ -2131,12 +2130,10 @@ static void tryToClone(struct callback_data *p, const char *zNewDb){
fprintf(stderr, "Cannot create output database: %s\n",
sqlite3_errmsg(newDb));
}else{
sqlite3_exec(p->db, "PRAGMA writable_schema=ON;", 0, 0, 0);
sqlite3_exec(newDb, "BEGIN EXCLUSIVE;", 0, 0, 0);
tryToCloneSchema(p, newDb, "type='table'", tryToCloneData);
tryToCloneSchema(p, newDb, "type!='table'", 0);
sqlite3_exec(newDb, "COMMIT;", 0, 0, 0);
sqlite3_exec(p->db, "PRAGMA writable_schema=OFF;", 0, 0, 0);
}
sqlite3_close(newDb);
}
@@ -2431,7 +2428,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){
}
nByte = strlen30(zSql);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
csv_append_char(&sCsv, 0); /* To ensure sCsv.z is allocated */
if( rc && sqlite3_strglob("no such table: *", sqlite3_errmsg(db))==0 ){
char *zCreate = sqlite3_mprintf("CREATE TABLE %s", zTable);
char cSep = '(';
@@ -3029,7 +3025,6 @@ static int do_meta_command(char *zLine, struct callback_data *p){
{ "optimizations", SQLITE_TESTCTRL_OPTIMIZATIONS },
{ "iskeyword", SQLITE_TESTCTRL_ISKEYWORD },
{ "scratchmalloc", SQLITE_TESTCTRL_SCRATCHMALLOC },
{ "byteorder", SQLITE_TESTCTRL_BYTEORDER },
};
int testctrl = -1;
int rc = 0;
@@ -3070,10 +3065,9 @@ static int do_meta_command(char *zLine, struct callback_data *p){
break;
/* sqlite3_test_control(int) */
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
case SQLITE_TESTCTRL_PRNG_SAVE:
case SQLITE_TESTCTRL_PRNG_RESTORE:
case SQLITE_TESTCTRL_PRNG_RESET:
case SQLITE_TESTCTRL_BYTEORDER:
if( nArg==2 ){
rc = sqlite3_test_control(testctrl);
fprintf(p->out, "%d (0x%08x)\n", rc, rc);
@@ -3538,7 +3532,6 @@ static void main_init(struct callback_data *data) {
sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data);
sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> ");
sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> ");
sqlite3_config(SQLITE_CONFIG_SINGLETHREAD);
}
/*
+4 -41
View File
@@ -555,10 +555,7 @@ int sqlite3_exec(
** file that were written at the application level might have changed
** and that adjacent bytes, even bytes within the same sector are
** guaranteed to be unchanged. The SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN
** flag indicate that a file cannot be deleted when open. The
** SQLITE_IOCAP_IMMUTABLE flag indicates that the file is on
** read-only media and cannot be changed even by processes with
** elevated privileges.
** flag indicate that a file cannot be deleted when open.
*/
#define SQLITE_IOCAP_ATOMIC 0x00000001
#define SQLITE_IOCAP_ATOMIC512 0x00000002
@@ -573,7 +570,6 @@ int sqlite3_exec(
#define SQLITE_IOCAP_SEQUENTIAL 0x00000400
#define SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN 0x00000800
#define SQLITE_IOCAP_POWERSAFE_OVERWRITE 0x00001000
#define SQLITE_IOCAP_IMMUTABLE 0x00002000
/*
** CAPI3REF: File Locking Levels
@@ -942,12 +938,6 @@ struct sqlite3_io_methods {
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging. This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
@@ -971,7 +961,6 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_HAS_MOVED 20
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
/*
** CAPI3REF: Mutex Handle
@@ -2785,30 +2774,6 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** ^If sqlite3_open_v2() is used and the "cache" parameter is present in
** a URI filename, its value overrides any behavior requested by setting
** SQLITE_OPEN_PRIVATECACHE or SQLITE_OPEN_SHAREDCACHE flag.
**
** <li> <b>psow</b>: ^The psow parameter may be "true" (or "on" or "yes" or
** "1") or "false" (or "off" or "no" or "0") to indicate that the
** [powersafe overwrite] property does or does not apply to the
** storage media on which the database file resides. ^The psow query
** parameter only works for the built-in unix and Windows VFSes.
**
** <li> <b>nolock</b>: ^The nolock parameter is a boolean query parameter
** which if set disables file locking in rollback journal modes. This
** is useful for accessing a database on a filesystem that does not
** support locking. Caution: Database corruption might result if two
** or more processes write to the same database and any one of those
** processes uses nolock=1.
**
** <li> <b>immutable</b>: ^The immutable parameter is a boolean query
** parameter that indicates that the database file is stored on
** read-only media. ^When immutable is set, SQLite assumes that the
** database file cannot be changed, even by a process with higher
** privilege, and so the database is opened read-only and all locking
** and change detection is disabled. Caution: Setting the immutable
** property on a database file that does in fact change can result
** in incorrect query results and/or [SQLITE_CORRUPT] errors.
** See also: [SQLITE_IOCAP_IMMUTABLE].
**
** </ul>
**
** ^Specifying an unknown parameter in the query component of a URI is not an
@@ -2838,9 +2803,8 @@ void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
** Open file "data.db" in the current directory for read-only access.
** Regardless of whether or not shared-cache mode is enabled by
** default, use a private cache.
** <tr><td> file:/home/fred/data.db?vfs=unix-dotfile <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-dotfile"
** that uses dot-files in place of posix advisory locking.
** <tr><td> file:/home/fred/data.db?vfs=unix-nolock <td>
** Open file "/home/fred/data.db". Use the special VFS "unix-nolock".
** <tr><td> file:data.db?mode=readonly <td>
** An error. "readonly" is not a valid option for the "mode" parameter.
** </table>
@@ -6154,8 +6118,7 @@ int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
#define SQLITE_TESTCTRL_BYTEORDER 22
#define SQLITE_TESTCTRL_LAST 22
#define SQLITE_TESTCTRL_LAST 21
/*
** CAPI3REF: SQLite Runtime Status
+28 -53
View File
@@ -525,10 +525,10 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
** gives a possible range of values of approximately 1.0e986 to 1e-986.
** But the allowed values are "grainy". Not every value is representable.
** For example, quantities 16 and 17 are both represented by a LogEst
** of 40. However, since LogEst quantaties are suppose to be estimates,
** of 40. However, since LogEst quantatites are suppose to be estimates,
** not exact values, this imprecision is not a problem.
**
** "LogEst" is short for "Logarithmic Estimate".
** "LogEst" is short for "Logarithimic Estimate".
**
** Examples:
** 1 -> 0 20 -> 43 10000 -> 132
@@ -546,39 +546,22 @@ typedef INT16_TYPE LogEst;
/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
** For best performance, an attempt is made to guess at the byte-order
** using C-preprocessor macros. If that is unsuccessful, or if
** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined
** at run-time.
** evaluated at runtime.
*/
#ifdef SQLITE_AMALGAMATION
const int sqlite3one = 1;
#else
extern const int sqlite3one;
#endif
#if (defined(i386) || defined(__i386__) || defined(_M_IX86) || \
defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \
defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \
defined(__arm__)) && !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER 1234
#if defined(i386) || defined(__i386__) || defined(_M_IX86)\
|| defined(__x86_64) || defined(__x86_64__)
# define SQLITE_BIGENDIAN 0
# define SQLITE_LITTLEENDIAN 1
# define SQLITE_UTF16NATIVE SQLITE_UTF16LE
#endif
#if (defined(sparc) || defined(__ppc__)) \
&& !defined(SQLITE_RUNTIME_BYTEORDER)
# define SQLITE_BYTEORDER 4321
# define SQLITE_BIGENDIAN 1
# define SQLITE_LITTLEENDIAN 0
# define SQLITE_UTF16NATIVE SQLITE_UTF16BE
#endif
#if !defined(SQLITE_BYTEORDER)
# define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */
#else
# define SQLITE_BIGENDIAN (*(char *)(&sqlite3one)==0)
# define SQLITE_LITTLEENDIAN (*(char *)(&sqlite3one)==1)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
# define SQLITE_UTF16NATIVE (SQLITE_BIGENDIAN?SQLITE_UTF16BE:SQLITE_UTF16LE)
#endif
/*
@@ -805,6 +788,7 @@ typedef struct PrintfArguments PrintfArguments;
typedef struct RowSet RowSet;
typedef struct Savepoint Savepoint;
typedef struct Select Select;
typedef struct SQLiteThread SQLiteThread;
typedef struct SelectDest SelectDest;
typedef struct SrcList SrcList;
typedef struct StrAccum StrAccum;
@@ -1471,7 +1455,7 @@ struct Table {
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
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 */
@@ -1680,7 +1664,7 @@ struct UnpackedRecord {
struct Index {
char *zName; /* Name of this index */
i16 *aiColumn; /* Which columns are used by this index. 1st is 0 */
LogEst *aiRowLogEst; /* 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 */
@@ -1694,7 +1678,7 @@ struct Index {
u16 nKeyCol; /* Number of columns forming the key */
u16 nColumn; /* Number of columns stored in the index */
u8 onError; /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
unsigned idxType:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned autoIndex:2; /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
unsigned bUnordered:1; /* Use this index for == or IN queries only */
unsigned uniqNotNull:1; /* True if UNIQUE and NOT NULL for all columns */
unsigned isResized:1; /* True if resizeIndexObject() has been called */
@@ -1707,16 +1691,6 @@ struct Index {
#endif
};
/*
** Allowed values for Index.idxType
*/
#define SQLITE_IDXTYPE_APPDEF 0 /* Created using CREATE INDEX */
#define SQLITE_IDXTYPE_UNIQUE 1 /* Implements a UNIQUE constraint */
#define SQLITE_IDXTYPE_PRIMARYKEY 2 /* Is the PRIMARY KEY for the table */
/* Return true if index X is a PRIMARY KEY index */
#define IsPrimaryKeyIndex(X) ((X)->idxType==SQLITE_IDXTYPE_PRIMARYKEY)
/*
** Each sample stored in the sqlite_stat3 table is represented in memory
** using a structure of this type. See documentation at the top of the
@@ -2135,7 +2109,6 @@ struct SrcList {
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
#define WHERE_SORTBYGROUP 0x0800 /* Support sqlite3WhereIsSorted() */
/* Allowed return values from sqlite3WhereIsDistinct()
*/
@@ -2719,10 +2692,11 @@ struct Sqlite3Config {
int isMutexInit; /* True after mutexes are initialized */
int isMallocInit; /* True after malloc is initialized */
int isPCacheInit; /* True after malloc is initialized */
int nRefInitMutex; /* Number of users of pInitMutex */
sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */
int nRefInitMutex; /* Number of users of pInitMutex */
void (*xLog)(void*,int,const char*); /* Function for logging */
void *pLogArg; /* First argument to xLog() */
int bLocaltimeFault; /* True to fail localtime() calls */
#ifdef SQLITE_ENABLE_SQLLOG
void(*xSqllog)(void*,sqlite3*,const char*, int);
void *pSqllogArg;
@@ -2734,10 +2708,6 @@ struct Sqlite3Config {
void (*xVdbeBranch)(void*,int iSrcLine,u8 eThis,u8 eMx); /* Callback */
void *pVdbeBranchArg; /* 1st argument */
#endif
#ifndef SQLITE_OMIT_BUILTIN_TEST
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
#endif
int bLocaltimeFault; /* True to fail localtime() calls */
};
/*
@@ -3039,12 +3009,6 @@ int sqlite3ParseUri(const char*,const char*,unsigned int*,
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
int sqlite3CodeOnce(Parse *);
#ifdef SQLITE_OMIT_BUILTIN_TEST
# define sqlite3FaultSim(X) SQLITE_OK
#else
int sqlite3FaultSim(int);
#endif
Bitvec *sqlite3BitvecCreate(u32);
int sqlite3BitvecTest(Bitvec*, u32);
int sqlite3BitvecSet(Bitvec*, u32);
@@ -3056,7 +3020,7 @@ int sqlite3BitvecBuiltinTest(int,int*);
RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
void sqlite3RowSetClear(RowSet*);
void sqlite3RowSetInsert(RowSet*, i64);
int sqlite3RowSetTest(RowSet*, int iBatch, i64);
int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
int sqlite3RowSetNext(RowSet*, i64*);
void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
@@ -3112,7 +3076,6 @@ void sqlite3WhereEnd(WhereInfo*);
u64 sqlite3WhereOutputRowCount(WhereInfo*);
int sqlite3WhereIsDistinct(WhereInfo*);
int sqlite3WhereIsOrdered(WhereInfo*);
int sqlite3WhereIsSorted(WhereInfo*);
int sqlite3WhereContinueLabel(WhereInfo*);
int sqlite3WhereBreakLabel(WhereInfo*);
int sqlite3WhereOkOnePass(WhereInfo*, int*);
@@ -3121,7 +3084,7 @@ void sqlite3ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int);
void sqlite3ExprCodeMove(Parse*, int, int, int);
void sqlite3ExprCacheStore(Parse*, int, int, int);
void sqlite3ExprCachePush(Parse*);
void sqlite3ExprCachePop(Parse*);
void sqlite3ExprCachePop(Parse*, int);
void sqlite3ExprCacheRemove(Parse*, int, int);
void sqlite3ExprCacheClear(Parse*);
void sqlite3ExprCacheAffinityChange(Parse*, int, int);
@@ -3173,7 +3136,6 @@ int sqlite3IsRowid(const char*);
void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);
int sqlite3GenerateIndexKey(Parse*, Index*, int, int, int, int*,Index*,int);
void sqlite3ResolvePartIdxLabel(Parse*,int);
void sqlite3GenerateConstraintChecks(Parse*,Table*,int*,int,int,int,int,
u8,u8,int,int*);
void sqlite3CompleteInsertion(Parse*,Table*,int,int,int,int*,int,int,int);
@@ -3672,4 +3634,17 @@ SQLITE_EXTERN void (*sqlite3IoTrace)(const char*,...);
#define MEMTYPE_PCACHE 0x08 /* Page cache allocations */
#define MEMTYPE_DB 0x10 /* Uses sqlite3DbMalloc, not sqlite_malloc */
/*
** Threading interface
*/
int sqlite3ThreadCreate(SQLiteThread**,void*(*)(void*),void*);
int sqlite3ThreadJoin(SQLiteThread*, void**);
/*
** Win32 interface
*/
#if SQLITE_OS_WIN
DWORD sqlite3Win32Wait(HANDLE hObject);
#endif
#endif /* _SQLITEINT_H_ */
-54
View File
@@ -14,10 +14,6 @@
** testing of the SQLite library.
*/
#include "sqliteInt.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#include "vdbeInt.h"
#include "tcl.h"
#include <stdlib.h>
@@ -117,16 +113,6 @@ int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
return TCL_OK;
}
#if SQLITE_OS_WIN
/*
** Decode a Win32 HANDLE object.
*/
int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
*phFile = (HANDLE)sqlite3TestTextToPtr(zA);
return TCL_OK;
}
#endif
extern const char *sqlite3ErrName(int);
#define t1ErrorName sqlite3ErrName
@@ -5220,7 +5206,6 @@ static int file_control_lockproxy_test(
return TCL_OK;
}
#if SQLITE_OS_WIN
/*
** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
**
@@ -5254,42 +5239,6 @@ static int file_control_win32_av_retry(
return TCL_OK;
}
/*
** tclcmd: file_control_win32_set_handle DB HANDLE
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
*/
static int file_control_win32_set_handle(
ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int objc, /* Number of arguments */
Tcl_Obj *CONST objv[] /* Command arguments */
){
sqlite3 *db;
int rc;
HANDLE hFile = NULL;
char z[100];
if( objc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"",
Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
return TCL_ERROR;
}
if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
return TCL_ERROR;
}
rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
(void*)&hFile);
sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
Tcl_AppendResult(interp, z, (char*)0);
return TCL_OK;
}
#endif
/*
** tclcmd: file_control_persist_wal DB PERSIST-FLAG
**
@@ -6519,10 +6468,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
{ "file_control_chunksize_test", file_control_chunksize_test, 0 },
{ "file_control_sizehint_test", file_control_sizehint_test, 0 },
#if SQLITE_OS_WIN
{ "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
{ "file_control_win32_set_handle", file_control_win32_set_handle, 0 },
#endif
{ "file_control_persist_wal", file_control_persist_wal, 0 },
{ "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
{ "file_control_vfsname", file_control_vfsname, 0 },
+2 -86
View File
@@ -568,90 +568,7 @@ static int testPendingByte(
rc = sqlite3_test_control(SQLITE_TESTCTRL_PENDING_BYTE, pbyte);
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return TCL_OK;
}
/*
** The sqlite3FaultSim() callback:
*/
static Tcl_Interp *faultSimInterp = 0;
static int faultSimScriptSize = 0;
static char *faultSimScript;
static int faultSimCallback(int x){
char zInt[30];
int i;
int isNeg;
int rc;
if( x==0 ){
memcpy(faultSimScript+faultSimScriptSize, "0", 2);
}else{
/* Convert x to text without using any sqlite3 routines */
if( x<0 ){
isNeg = 1;
x = -x;
}else{
isNeg = 0;
}
zInt[sizeof(zInt)-1] = 0;
for(i=sizeof(zInt)-2; i>0 && x>0; i--, x /= 10){
zInt[i] = (x%10) + '0';
}
if( isNeg ) zInt[i--] = '-';
memcpy(faultSimScript+faultSimScriptSize, zInt+i+1, sizeof(zInt)-i);
}
rc = Tcl_Eval(faultSimInterp, faultSimScript);
if( rc ){
fprintf(stderr, "fault simulator script failed: [%s]", faultSimScript);
rc = SQLITE_ERROR;
}else{
rc = atoi(Tcl_GetStringResult(faultSimInterp));
}
Tcl_ResetResult(faultSimInterp);
return rc;
}
/*
** sqlite3_test_control_fault_install SCRIPT
**
** Arrange to invoke SCRIPT with the integer argument to sqlite3FaultSim()
** appended, whenever sqlite3FaultSim() is called. Or, if SCRIPT is the
** empty string, cancel the sqlite3FaultSim() callback.
*/
static int faultInstallCmd(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
const char **argv /* Text of each argument */
){
const char *zScript;
int nScript;
int rc;
if( argc!=1 && argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" SCRIPT\"", (void*)0);
}
zScript = argc==2 ? argv[1] : "";
nScript = (int)strlen(zScript);
if( faultSimScript ){
free(faultSimScript);
faultSimScript = 0;
}
if( nScript==0 ){
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, 0);
}else{
faultSimScript = malloc( nScript+100 );
if( faultSimScript==0 ){
Tcl_AppendResult(interp, "out of memory", (void*)0);
return SQLITE_ERROR;
}
memcpy(faultSimScript, zScript, nScript);
faultSimScript[nScript] = ' ';
faultSimScriptSize = nScript+1;
faultSimInterp = interp;
rc = sqlite3_test_control(SQLITE_TESTCTRL_FAULT_INSTALL, faultSimCallback);
}
Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
return SQLITE_OK;
}
}
/*
** sqlite3BitvecBuiltinTest SIZE PROGRAM
@@ -721,8 +638,7 @@ int Sqlitetest2_Init(Tcl_Interp *interp){
{ "fake_big_file", (Tcl_CmdProc*)fake_big_file },
#endif
{ "sqlite3BitvecBuiltinTest",(Tcl_CmdProc*)testBitvecBuiltinTest },
{ "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
{ "sqlite3_test_control_fault_install", (Tcl_CmdProc*)faultInstallCmd },
{ "sqlite3_test_control_pending_byte", (Tcl_CmdProc*)testPendingByte },
};
int i;
for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
+1 -1
View File
@@ -51,7 +51,7 @@ void sqlite3BtreeCursorList(Btree *p){
BtShared *pBt = p->pBt;
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
MemPage *pPage = pCur->apPage[pCur->iPage];
char *zMode = (pCur->curFlags & BTCF_WriteFlag) ? "rw" : "ro";
char *zMode = pCur->wrFlag ? "rw" : "ro";
sqlite3DebugPrintf("CURSOR %p rooted at %4d(%s) currently at %d.%d%s\n",
pCur, pCur->pgnoRoot, zMode,
pPage ? pPage->pgno : 0, pCur->aiIdx[pCur->iPage],
-4
View File
@@ -20,10 +20,6 @@
#include "sqliteLimit.h"
#include "sqliteInt.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
+1 -6
View File
@@ -70,12 +70,6 @@
*/
#include "sqlite3.h"
#include "os_setup.h"
#if SQLITE_OS_WIN
# include "os_win.h"
#endif
#include <string.h>
#include <assert.h>
@@ -227,6 +221,7 @@ static sqlite3_uint64 vfslog_time(){
return sTime.tv_usec + (sqlite3_uint64)sTime.tv_sec * 1000000;
}
#elif SQLITE_OS_WIN
#include <windows.h>
#include <time.h>
static sqlite3_uint64 vfslog_time(){
FILETIME ft;
+38 -2
View File
@@ -44,13 +44,49 @@
#define sqlite3_mutex_notheld(X) ((void)(X),1)
#endif /* SQLITE_THREADSAFE==0 */
#include "os_setup.h"
/*
** Figure out if we are dealing with Unix, Windows, or some other
** operating system. After the following block of preprocess macros,
** all of SQLITE_OS_UNIX, SQLITE_OS_WIN, and SQLITE_OS_OTHER
** will defined to either 1 or 0. One of the four will be 1. The other
** three will be 0.
*/
#if defined(SQLITE_OS_OTHER)
# if SQLITE_OS_OTHER==1
# undef SQLITE_OS_UNIX
# define SQLITE_OS_UNIX 0
# undef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# else
# undef SQLITE_OS_OTHER
# endif
#endif
#if !defined(SQLITE_OS_UNIX) && !defined(SQLITE_OS_OTHER)
# define SQLITE_OS_OTHER 0
# ifndef SQLITE_OS_WIN
# if defined(_WIN32) || defined(WIN32) || defined(__CYGWIN__) \
|| defined(__MINGW32__) || defined(__BORLANDC__)
# define SQLITE_OS_WIN 1
# define SQLITE_OS_UNIX 0
# else
# define SQLITE_OS_WIN 0
# define SQLITE_OS_UNIX 1
# endif
# else
# define SQLITE_OS_UNIX 0
# endif
#else
# ifndef SQLITE_OS_WIN
# define SQLITE_OS_WIN 0
# endif
#endif
#if SQLITE_OS_UNIX
# include <unistd.h>
#endif
#if SQLITE_OS_WIN
# include "os_win.h"
# include <windows.h>
# include <io.h>
#endif
+6
View File
@@ -31,6 +31,12 @@
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#if SQLITE_OS_UNIX
# include <unistd.h>
#endif
#if SQLITE_OS_WIN
# include <windows.h>
#endif
/* Make this callable from C++ */
#ifdef __cplusplus
+17 -183
View File
@@ -35,8 +35,6 @@ struct Circle {
double centerx;
double centery;
double radius;
double mxArea;
int eScoreType;
};
/*
@@ -52,7 +50,11 @@ static void circle_del(void *p){
static int circle_geom(
sqlite3_rtree_geometry *p,
int nCoord,
sqlite3_rtree_dbl *aCoord,
#ifdef SQLITE_RTREE_INT_ONLY
sqlite3_int64 *aCoord,
#else
double *aCoord,
#endif
int *pRes
){
int i; /* Iterator variable */
@@ -60,12 +62,7 @@ static int circle_geom(
double xmin, xmax; /* X dimensions of box being tested */
double ymin, ymax; /* X dimensions of box being tested */
xmin = aCoord[0];
xmax = aCoord[1];
ymin = aCoord[2];
ymax = aCoord[3];
pCircle = (Circle *)p->pUser;
if( pCircle==0 ){
if( p->pUser==0 ){
/* If pUser is still 0, then the parameter values have not been tested
** for correctness or stored into a Circle structure yet. Do this now. */
@@ -111,9 +108,14 @@ static int circle_geom(
pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
pCircle->aBox[1].ymin = pCircle->centery;
pCircle->aBox[1].ymax = pCircle->centery;
pCircle->mxArea = (xmax - xmin)*(ymax - ymin) + 1.0;
}
pCircle = (Circle *)p->pUser;
xmin = aCoord[0];
xmax = aCoord[1];
ymin = aCoord[2];
ymax = aCoord[3];
/* Check if any of the 4 corners of the bounding-box being tested lie
** inside the circular region. If they do, then the bounding-box does
** intersect the region of interest. Set the output variable to true and
@@ -152,170 +154,6 @@ static int circle_geom(
return SQLITE_OK;
}
/*
** Implementation of "circle" r-tree geometry callback using the
** 2nd-generation interface that allows scoring.
*/
static int circle_query_func(sqlite3_rtree_query_info *p){
int i; /* Iterator variable */
Circle *pCircle; /* Structure defining circular region */
double xmin, xmax; /* X dimensions of box being tested */
double ymin, ymax; /* X dimensions of box being tested */
int nWithin = 0; /* Number of corners inside the circle */
xmin = p->aCoord[0];
xmax = p->aCoord[1];
ymin = p->aCoord[2];
ymax = p->aCoord[3];
pCircle = (Circle *)p->pUser;
if( pCircle==0 ){
/* If pUser is still 0, then the parameter values have not been tested
** for correctness or stored into a Circle structure yet. Do this now. */
/* This geometry callback is for use with a 2-dimensional r-tree table.
** Return an error if the table does not have exactly 2 dimensions. */
if( p->nCoord!=4 ) return SQLITE_ERROR;
/* Test that the correct number of parameters (4) have been supplied,
** and that the parameters are in range (that the radius of the circle
** radius is greater than zero). */
if( p->nParam!=4 || p->aParam[2]<0.0 ) return SQLITE_ERROR;
/* Allocate a structure to cache parameter data in. Return SQLITE_NOMEM
** if the allocation fails. */
pCircle = (Circle *)(p->pUser = sqlite3_malloc(sizeof(Circle)));
if( !pCircle ) return SQLITE_NOMEM;
p->xDelUser = circle_del;
/* Record the center and radius of the circular region. One way that
** tested bounding boxes that intersect the circular region are detected
** is by testing if each corner of the bounding box lies within radius
** units of the center of the circle. */
pCircle->centerx = p->aParam[0];
pCircle->centery = p->aParam[1];
pCircle->radius = p->aParam[2];
pCircle->eScoreType = (int)p->aParam[3];
/* Define two bounding box regions. The first, aBox[0], extends to
** infinity in the X dimension. It covers the same range of the Y dimension
** as the circular region. The second, aBox[1], extends to infinity in
** the Y dimension and is constrained to the range of the circle in the
** X dimension.
**
** Then imagine each box is split in half along its short axis by a line
** that intersects the center of the circular region. A bounding box
** being tested can be said to intersect the circular region if it contains
** points from each half of either of the two infinite bounding boxes.
*/
pCircle->aBox[0].xmin = pCircle->centerx;
pCircle->aBox[0].xmax = pCircle->centerx;
pCircle->aBox[0].ymin = pCircle->centery + pCircle->radius;
pCircle->aBox[0].ymax = pCircle->centery - pCircle->radius;
pCircle->aBox[1].xmin = pCircle->centerx + pCircle->radius;
pCircle->aBox[1].xmax = pCircle->centerx - pCircle->radius;
pCircle->aBox[1].ymin = pCircle->centery;
pCircle->aBox[1].ymax = pCircle->centery;
pCircle->mxArea = 200.0*200.0;
}
/* Check if any of the 4 corners of the bounding-box being tested lie
** inside the circular region. If they do, then the bounding-box does
** intersect the region of interest. Set the output variable to true and
** return SQLITE_OK in this case. */
for(i=0; i<4; i++){
double x = (i&0x01) ? xmax : xmin;
double y = (i&0x02) ? ymax : ymin;
double d2;
d2 = (x-pCircle->centerx)*(x-pCircle->centerx);
d2 += (y-pCircle->centery)*(y-pCircle->centery);
if( d2<(pCircle->radius*pCircle->radius) ) nWithin++;
}
/* Check if the bounding box covers any other part of the circular region.
** See comments above for a description of how this test works. If it does
** cover part of the circular region, set the output variable to true
** and return SQLITE_OK. */
if( nWithin==0 ){
for(i=0; i<2; i++){
if( xmin<=pCircle->aBox[i].xmin
&& xmax>=pCircle->aBox[i].xmax
&& ymin<=pCircle->aBox[i].ymin
&& ymax>=pCircle->aBox[i].ymax
){
nWithin = 1;
break;
}
}
}
if( pCircle->eScoreType==1 ){
/* Depth first search */
p->rScore = p->iLevel;
}else if( pCircle->eScoreType==2 ){
/* Breadth first search */
p->rScore = 100 - p->iLevel;
}else if( pCircle->eScoreType==3 ){
/* Depth-first search, except sort the leaf nodes by area with
** the largest area first */
if( p->iLevel==1 ){
p->rScore = 1.0 - (xmax-xmin)*(ymax-ymin)/pCircle->mxArea;
if( p->rScore<0.01 ) p->rScore = 0.01;
}else{
p->rScore = 0.0;
}
}else if( pCircle->eScoreType==4 ){
/* Depth-first search, except exclude odd rowids */
p->rScore = p->iLevel;
if( p->iRowid&1 ) nWithin = 0;
}else{
/* Breadth-first search, except exclude odd rowids */
p->rScore = 100 - p->iLevel;
if( p->iRowid&1 ) nWithin = 0;
}
if( nWithin==0 ){
p->eWithin = NOT_WITHIN;
}else if( nWithin>=4 ){
p->eWithin = FULLY_WITHIN;
}else{
p->eWithin = PARTLY_WITHIN;
}
return SQLITE_OK;
}
/*
** Implementation of "breadthfirstsearch" r-tree geometry callback using the
** 2nd-generation interface that allows scoring.
**
** ... WHERE id MATCH breadthfirstsearch($x0,$x1,$y0,$y1) ...
**
** It returns all entries whose bounding boxes overlap with $x0,$x1,$y0,$y1.
*/
static int bfs_query_func(sqlite3_rtree_query_info *p){
double x0,x1,y0,y1; /* Dimensions of box being tested */
double bx0,bx1,by0,by1; /* Boundary of the query function */
if( p->nParam!=4 ) return SQLITE_ERROR;
x0 = p->aCoord[0];
x1 = p->aCoord[1];
y0 = p->aCoord[2];
y1 = p->aCoord[3];
bx0 = p->aParam[0];
bx1 = p->aParam[1];
by0 = p->aParam[2];
by1 = p->aParam[3];
p->rScore = 100 - p->iLevel;
if( p->eParentWithin==FULLY_WITHIN ){
p->eWithin = FULLY_WITHIN;
}else if( x0>=bx0 && x1<=bx1 && y0>=by0 && y1<=by1 ){
p->eWithin = FULLY_WITHIN;
}else if( x1>=bx0 && x0<=bx1 && y1>=by0 && y0<=by1 ){
p->eWithin = PARTLY_WITHIN;
}else{
p->eWithin = NOT_WITHIN;
}
return SQLITE_OK;
}
/* END of implementation of "circle" geometry callback.
**************************************************************************
*************************************************************************/
@@ -356,7 +194,11 @@ static int gHere = 42;
static int cube_geom(
sqlite3_rtree_geometry *p,
int nCoord,
sqlite3_rtree_dbl *aCoord,
#ifdef SQLITE_RTREE_INT_ONLY
sqlite3_int64 *aCoord,
#else
double *aCoord,
#endif
int *piRes
){
Cube *pCube = (Cube *)p->pUser;
@@ -451,14 +293,6 @@ static int register_circle_geom(
}
if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
rc = sqlite3_rtree_geometry_callback(db, "circle", circle_geom, 0);
if( rc==SQLITE_OK ){
rc = sqlite3_rtree_query_callback(db, "Qcircle",
circle_query_func, 0, 0);
}
if( rc==SQLITE_OK ){
rc = sqlite3_rtree_query_callback(db, "breadthfirstsearch",
bfs_query_func, 0, 0);
}
Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_STATIC);
#endif
return TCL_OK;
+20 -53
View File
@@ -127,10 +127,8 @@ struct Testvfs {
#define TESTVFS_FULLPATHNAME_MASK 0x00008000
#define TESTVFS_READ_MASK 0x00010000
#define TESTVFS_UNLOCK_MASK 0x00020000
#define TESTVFS_LOCK_MASK 0x00040000
#define TESTVFS_CKLOCK_MASK 0x00080000
#define TESTVFS_ALL_MASK 0x000FFFFF
#define TESTVFS_ALL_MASK 0x0003FFFF
#define TESTVFS_MAX_PAGES 1024
@@ -468,15 +466,8 @@ static int tvfsFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
** Lock an tvfs-file.
*/
static int tvfsLock(sqlite3_file *pFile, int eLock){
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_LOCK_MASK ){
char zLock[30];
sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
tvfsExecTcl(p, "xLock", Tcl_NewStringObj(pFd->zFilename, -1),
Tcl_NewStringObj(zLock, -1), 0, 0);
}
return sqlite3OsLock(pFd->pReal, eLock);
TestvfsFd *p = tvfsGetFd(pFile);
return sqlite3OsLock(p->pReal, eLock);
}
/*
@@ -485,12 +476,6 @@ static int tvfsLock(sqlite3_file *pFile, int eLock){
static int tvfsUnlock(sqlite3_file *pFile, int eLock){
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_UNLOCK_MASK ){
char zLock[30];
sqlite3_snprintf(sizeof(zLock),zLock,"%d",eLock);
tvfsExecTcl(p, "xUnlock", Tcl_NewStringObj(pFd->zFilename, -1),
Tcl_NewStringObj(zLock, -1), 0, 0);
}
if( p->mask&TESTVFS_WRITE_MASK && tvfsInjectIoerr(p) ){
return SQLITE_IOERR_UNLOCK;
}
@@ -501,13 +486,8 @@ static int tvfsUnlock(sqlite3_file *pFile, int eLock){
** Check if another file-handle holds a RESERVED lock on an tvfs-file.
*/
static int tvfsCheckReservedLock(sqlite3_file *pFile, int *pResOut){
TestvfsFd *pFd = tvfsGetFd(pFile);
Testvfs *p = (Testvfs *)pFd->pVfs->pAppData;
if( p->pScript && p->mask&TESTVFS_CKLOCK_MASK ){
tvfsExecTcl(p, "xCheckReservedLock", Tcl_NewStringObj(pFd->zFilename, -1),
0, 0, 0);
}
return sqlite3OsCheckReservedLock(pFd->pReal, pResOut);
TestvfsFd *p = tvfsGetFd(pFile);
return sqlite3OsCheckReservedLock(p->pReal, pResOut);
}
/*
@@ -1131,32 +1111,26 @@ static int testvfs_obj_cmd(
break;
}
/* TESTVFS filter METHOD-LIST
**
** Activate special processing for those methods contained in the list
*/
case CMD_FILTER: {
static struct VfsMethod {
char *zName;
int mask;
} vfsmethod [] = {
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
{ "xShmMap", TESTVFS_SHMMAP_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
{ "xRead", TESTVFS_READ_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
{ "xAccess", TESTVFS_ACCESS_MASK },
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
{ "xUnlock", TESTVFS_UNLOCK_MASK },
{ "xLock", TESTVFS_LOCK_MASK },
{ "xCheckReservedLock", TESTVFS_CKLOCK_MASK },
{ "xShmOpen", TESTVFS_SHMOPEN_MASK },
{ "xShmLock", TESTVFS_SHMLOCK_MASK },
{ "xShmBarrier", TESTVFS_SHMBARRIER_MASK },
{ "xShmUnmap", TESTVFS_SHMCLOSE_MASK },
{ "xShmMap", TESTVFS_SHMMAP_MASK },
{ "xSync", TESTVFS_SYNC_MASK },
{ "xDelete", TESTVFS_DELETE_MASK },
{ "xWrite", TESTVFS_WRITE_MASK },
{ "xRead", TESTVFS_READ_MASK },
{ "xTruncate", TESTVFS_TRUNCATE_MASK },
{ "xOpen", TESTVFS_OPEN_MASK },
{ "xClose", TESTVFS_CLOSE_MASK },
{ "xAccess", TESTVFS_ACCESS_MASK },
{ "xFullPathname", TESTVFS_FULLPATHNAME_MASK },
{ "xUnlock", TESTVFS_UNLOCK_MASK },
};
Tcl_Obj **apElem = 0;
int nElem = 0;
@@ -1188,12 +1162,6 @@ static int testvfs_obj_cmd(
break;
}
/*
** TESTVFS script ?SCRIPT?
**
** Query or set the script to be run when filtered VFS events
** occur.
*/
case CMD_SCRIPT: {
if( objc==3 ){
int nByte;
@@ -1280,7 +1248,6 @@ static int testvfs_obj_cmd(
{ "safe_append", SQLITE_IOCAP_SAFE_APPEND },
{ "undeletable_when_open", SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN },
{ "powersafe_overwrite", SQLITE_IOCAP_POWERSAFE_OVERWRITE },
{ "immutable", SQLITE_IOCAP_IMMUTABLE },
{ 0, 0 }
};
Tcl_Obj *pRet;
+1 -1
View File
@@ -678,7 +678,7 @@ static int vfstraceAccess(
vfstrace_info *pInfo = (vfstrace_info*)pVfs->pAppData;
sqlite3_vfs *pRoot = pInfo->pRootVfs;
int rc;
vfstrace_printf(pInfo, "%s.xAccess(\"%s\",%d)",
vfstrace_printf(pInfo, "%s.xDelete(\"%s\",%d)",
pInfo->zVfsName, zPath, flags);
rc = pRoot->xAccess(pRoot, zPath, flags, pResOut);
vfstrace_print_errcode(pInfo, " -> %s", rc);
+217
View File
@@ -0,0 +1,217 @@
/*
** 2012 July 21
**
** 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 presents a simple cross-platform threading interface for
** use internally by SQLite.
**
** A "thread" can be created using sqlite3ThreadCreate(). This thread
** runs independently of its creator until it is joined using
** sqlite3ThreadJoin(), at which point it terminates.
**
** Threads do not have to be real. It could be that the work of the
** "thread" is done by the main thread at either the sqlite3ThreadCreate()
** or sqlite3ThreadJoin() call. This is, in fact, what happens in
** single threaded systems. Nothing in SQLite requires multiple threads.
** This interface exists so that applications that want to take advantage
** of multiple cores can do so, while also allowing applications to stay
** single-threaded if desired.
*/
#include "sqliteInt.h"
/********************************* Unix Pthreads ****************************/
#if SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) && SQLITE_THREADSAFE>0
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
#include <pthread.h>
/* A running thread */
struct SQLiteThread {
pthread_t tid;
int done;
void *pOut;
};
/* Create a new thread */
int sqlite3ThreadCreate(
SQLiteThread **ppThread, /* OUT: Write the thread object here */
void *(*xTask)(void*), /* Routine to run in a separate thread */
void *pIn /* Argument passed into xTask() */
){
SQLiteThread *p;
assert( ppThread!=0 );
assert( xTask!=0 );
*ppThread = 0;
p = sqlite3Malloc(sizeof(*p));
if( p==0 ) return SQLITE_NOMEM;
memset(p, 0, sizeof(*p));
if( sqlite3GlobalConfig.bCoreMutex==0
|| pthread_create(&p->tid, 0, xTask, pIn)!=0
){
p->done = 1;
p->pOut = xTask(pIn);
}
*ppThread = p;
return SQLITE_OK;
}
/* Get the results of the thread */
int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
int rc;
assert( ppOut!=0 );
if( p==0 ) return SQLITE_NOMEM;
if( p->done ){
*ppOut = p->pOut;
rc = SQLITE_OK;
}else{
rc = pthread_join(p->tid, ppOut);
}
sqlite3_free(p);
return rc ? SQLITE_ERROR : SQLITE_OK;
}
#endif /* SQLITE_OS_UNIX && defined(SQLITE_MUTEX_PTHREADS) */
/******************************** End Unix Pthreads *************************/
/********************************* Win32 Threads ****************************/
#if SQLITE_OS_WIN && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
#include <process.h>
/* A running thread */
struct SQLiteThread {
uintptr_t tid; /* The thread handle */
void *(*xTask)(void*); /* The routine to run as a thread */
void *pIn; /* Argument to xTask */
void *pResult; /* Result of xTask */
};
/* Thread procedure Win32 compatibility shim */
static void sqlite3ThreadProc(
void *pArg /* IN: Pointer to the SQLiteThread structure */
){
SQLiteThread *p = (SQLiteThread *)pArg;
assert( p!=0 );
assert( p->xTask!=0 );
p->pResult = p->xTask(p->pIn);
_endthread();
}
/* Create a new thread */
int sqlite3ThreadCreate(
SQLiteThread **ppThread, /* OUT: Write the thread object here */
void *(*xTask)(void*), /* Routine to run in a separate thread */
void *pIn /* Argument passed into xTask() */
){
SQLiteThread *p;
assert( ppThread!=0 );
assert( xTask!=0 );
*ppThread = 0;
p = sqlite3Malloc(sizeof(*p));
if( p==0 ) return SQLITE_NOMEM;
if( sqlite3GlobalConfig.bCoreMutex==0 ){
memset(p, 0, sizeof(*p));
}else{
p->xTask = xTask;
p->pIn = pIn;
p->tid = _beginthread(sqlite3ThreadProc, 0, p);
if( p->tid==(uintptr_t)-1 ){
memset(p, 0, sizeof(*p));
}
}
if( p->xTask==0 ){
p->pResult = xTask(pIn);
}
*ppThread = p;
return SQLITE_OK;
}
/* Get the results of the thread */
int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
DWORD rc;
assert( ppOut!=0 );
if( p==0 ) return SQLITE_NOMEM;
if( p->xTask==0 ){
rc = WAIT_OBJECT_O;
}else{
rc = sqlite3Win32Wait((HANDLE)p->tid);
assert( rc!=WAIT_IO_COMPLETION );
}
if( rc==WAIT_OBJECT_0 ) *ppOut = p->pResult;
sqlite3_free(p);
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
}
#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINRT */
/******************************** End Win32 Threads *************************/
/********************************* Single-Threaded **************************/
#ifndef SQLITE_THREADS_IMPLEMENTED
/*
** This implementation does not actually create a new thread. It does the
** work of the thread in the main thread, when either the thread is created
** or when it is joined
*/
/* A running thread */
struct SQLiteThread {
void *(*xTask)(void*); /* The routine to run as a thread */
void *pIn; /* Argument to xTask */
void *pResult; /* Result of xTask */
};
/* Create a new thread */
int sqlite3ThreadCreate(
SQLiteThread **ppThread, /* OUT: Write the thread object here */
void *(*xTask)(void*), /* Routine to run in a separate thread */
void *pIn /* Argument passed into xTask() */
){
SQLiteThread *p;
assert( ppThread!=0 );
assert( xTask!=0 );
*ppThread = 0;
p = sqlite3Malloc(sizeof(*p));
if( p==0 ) return SQLITE_NOMEM;
if( (SQLITE_PTR_TO_INT(p)/17)&1 ){
p->xTask = xTask;
p->pIn = pIn;
}else{
p->xTask = 0;
p->pResult = xTask(pIn);
}
*ppThread = p;
return SQLITE_OK;
}
/* Get the results of the thread */
int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
assert( ppOut!=0 );
if( p==0 ) return SQLITE_NOMEM;
if( p->xTask ){
*ppOut = p->xTask(p->pIn);
}else{
*ppOut = p->pResult;
}
sqlite3_free(p);
return SQLITE_OK;
}
#endif /* !defined(SQLITE_THREADS_IMPLEMENTED) */
/****************************** End Single-Threaded *************************/
+1 -1
View File
@@ -187,7 +187,7 @@ void sqlite3Update(
iIdxCur = iDataCur+1;
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){
if( IsPrimaryKeyIndex(pIdx) && pPk!=0 ){
if( pIdx->autoIndex==2 && pPk!=0 ){
iDataCur = pParse->nTab;
pTabList->a[0].iCursor = iDataCur;
}
+2 -20
View File
@@ -31,24 +31,6 @@ void sqlite3Coverage(int x){
}
#endif
/*
** Give a callback to the test harness that can be used to simulate faults
** in places where it is difficult or expensive to do so purely by means
** of inputs.
**
** The intent of the integer argument is to let the fault simulator know
** which of multiple sqlite3FaultSim() calls has been hit.
**
** Return whatever integer value the test callback returns, or return
** SQLITE_OK if no test callback is installed.
*/
#ifndef SQLITE_OMIT_BUILTIN_TEST
int sqlite3FaultSim(int iTest){
int (*xCallback)(int) = sqlite3GlobalConfig.xTestCallback;
return xCallback ? xCallback(iTest) : SQLITE_OK;
}
#endif
#ifndef SQLITE_OMIT_FLOATING_POINT
/*
** Return true if the floating point value is Not a Number (NaN).
@@ -1264,8 +1246,8 @@ LogEst sqlite3LogEstAdd(LogEst a, LogEst b){
}
/*
** Convert an integer into a LogEst. In other words, compute an
** approximation for 10*log2(x).
** Convert an integer into a LogEst. In other words, compute a
** good approximatation for 10*log2(x).
*/
LogEst sqlite3LogEst(u64 x){
static LogEst a[] = { 0, 2, 3, 5, 6, 7, 8, 9 };
+29 -10
View File
@@ -3410,6 +3410,24 @@ case OP_SorterOpen: {
break;
}
/* Opcode: SequenceTest P1 P2 * * *
** Synopsis: if( cursor[P1].ctr++ ) pc = P2
**
** P1 is a sorter cursor. If the sequence counter is currently zero, jump
** to P2. Regardless of whether or not the jump is taken, increment the
** the sequence value.
*/
case OP_SequenceTest: {
VdbeCursor *pC;
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC->pSorter );
if( (pC->seqCount++)==0 ){
pc = pOp->p2 - 1;
}
break;
}
/* Opcode: OpenPseudo P1 P2 P3 * *
** Synopsis: P3 columns in r[P2]
**
@@ -3464,7 +3482,7 @@ case OP_Close: {
** is greater than or equal to the key value. If there are no records
** greater than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, SeekLt, SeekGt, SeekLe
** See also: Found, NotFound, Distinct, SeekLt, SeekGt, SeekLe
*/
/* Opcode: SeekGt P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -3478,7 +3496,7 @@ case OP_Close: {
** is greater than the key value. If there are no records greater than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, SeekLt, SeekGe, SeekLe
** See also: Found, NotFound, Distinct, SeekLt, SeekGe, SeekLe
*/
/* Opcode: SeekLt P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -3492,7 +3510,7 @@ case OP_Close: {
** is less than the key value. If there are no records less than
** the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLe
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLe
*/
/* Opcode: SeekLe P1 P2 P3 P4 *
** Synopsis: key=r[P3@P4]
@@ -3506,7 +3524,7 @@ case OP_Close: {
** is less than or equal to the key value. If there are no records
** less than or equal to the key and P2 is not zero, then jump to P2.
**
** See also: Found, NotFound, SeekGt, SeekGe, SeekLt
** See also: Found, NotFound, Distinct, SeekGt, SeekGe, SeekLt
*/
case OP_SeekLT: /* jump, in3 */
case OP_SeekLE: /* jump, in3 */
@@ -4232,7 +4250,6 @@ case OP_SorterData: {
pC = p->apCsr[pOp->p1];
assert( isSorter(pC) );
rc = sqlite3VdbeSorterRowkey(pC, pOut);
assert( rc!=SQLITE_OK || (pOut->flags & MEM_Blob) );
break;
}
@@ -5228,7 +5245,9 @@ case OP_RowSetTest: { /* jump, in1, in3 */
assert( pOp->p4type==P4_INT32 );
assert( iSet==-1 || iSet>=0 );
if( iSet ){
exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
exists = sqlite3RowSetTest(pIn1->u.pRowSet,
(u8)(iSet>=0 ? iSet & 0xf : 0xff),
pIn3->u.i);
VdbeBranchTaken(exists!=0,2);
if( exists ){
pc = pOp->p2 - 1;
@@ -5928,7 +5947,7 @@ case OP_VOpen: {
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VFilter P1 P2 P3 P4 *
** Synopsis: iplan=r[P3] zplan='P4'
** Synopsis: iPlan=r[P3] zPlan='P4'
**
** P1 is a cursor opened using VOpen. P2 is an address to jump to if
** the filtered result set is empty.
@@ -6281,7 +6300,7 @@ case OP_Init: { /* jump */
if( zTrace ){
int i;
for(i=0; i<db->nDb; i++){
if( (MASKBIT(i) & p->btreeMask)==0 ) continue;
if( MASKBIT(i) & p->btreeMask)==0 ) continue;
sqlite3_file_control(db, db->aDb[i].zName, SQLITE_FCNTL_TRACE, zTrace);
}
}
@@ -6324,8 +6343,8 @@ default: { /* This is really OP_Noop and OP_Explain */
#ifdef VDBE_PROFILE
{
u64 endTime = sqlite3Hwtime();
if( endTime>start ) pOp->cycles += endTime - start;
u64 elapsed = sqlite3Hwtime() - start;
pOp->cycles += elapsed;
pOp->cnt++;
}
#endif
+1 -1
View File
@@ -276,7 +276,7 @@ void sqlite3VdbeResolveLabel(Vdbe *v, int x){
int j = -1-x;
assert( v->magic==VDBE_MAGIC_INIT );
assert( j<p->nLabel );
if( ALWAYS(j>=0) && p->aLabel ){
if( j>=0 && p->aLabel ){
p->aLabel[j] = v->nOp;
}
p->iFixedOp = v->nOp - 1;
+3 -1
View File
@@ -77,7 +77,9 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
p->iOffset = pC->aType[p->iCol + pC->nField];
p->nByte = sqlite3VdbeSerialTypeLen(type);
p->pCsr = pC->pCursor;
sqlite3BtreeIncrblobCursor(p->pCsr);
sqlite3BtreeEnterCursor(p->pCsr);
sqlite3BtreeCacheOverflow(p->pCsr);
sqlite3BtreeLeaveCursor(p->pCsr);
}
}
+909 -371
View File
File diff suppressed because it is too large Load Diff
+253 -576
View File
File diff suppressed because it is too large Load Diff
-2
View File
@@ -398,7 +398,6 @@ struct WhereInfo {
LogEst nRowOut; /* Estimated number of output rows */
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
u8 sorted; /* True if really sorted (not just grouped) */
u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */
@@ -458,4 +457,3 @@ struct WhereInfo {
#define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */
#define WHERE_SKIPSCAN 0x00008000 /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED 0x00010000 /* WHERE_ONEROW would have been helpful*/
#define WHERE_LIKELIHOOD 0x00020000 /* A likelihood() is affecting nOut */
-38
View File
@@ -875,42 +875,4 @@ do_execsql_test alter-16.2 {
SELECT * FROM t16a_rn ORDER BY a;
} {abc 1.25 99 xyzzy cba 5.5 98 fizzle}
#-------------------------------------------------------------------------
# Verify that NULL values into the internal-use-only sqlite_rename_*()
# functions do not cause problems.
#
do_execsql_test alter-17.1 {
SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)','abc');
} {{CREATE TABLE "abc"(a,b,c)}}
do_execsql_test alter-17.2 {
SELECT sqlite_rename_table('CREATE TABLE xyz(a,b,c)',NULL);
} {{CREATE TABLE "(NULL)"(a,b,c)}}
do_execsql_test alter-17.3 {
SELECT sqlite_rename_table(NULL,'abc');
} {{}}
do_execsql_test alter-17.4 {
SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN','abc');
} {{CREATE TRIGGER r1 ON "abc" WHEN}}
do_execsql_test alter-17.5 {
SELECT sqlite_rename_trigger('CREATE TRIGGER r1 ON xyz WHEN',NULL);
} {{CREATE TRIGGER r1 ON "(NULL)" WHEN}}
do_execsql_test alter-17.6 {
SELECT sqlite_rename_trigger(NULL,'abc');
} {{}}
do_execsql_test alter-17.7 {
SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
'xyzzy','lmnop');
} {{CREATE TABLE t1(a REFERENCES "lmnop")}}
do_execsql_test alter-17.8 {
SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
'xyzzy',NULL);
} {{CREATE TABLE t1(a REFERENCES "(NULL)")}}
do_execsql_test alter-17.9 {
SELECT sqlite_rename_parent('CREATE TABLE t1(a REFERENCES "xyzzy")',
NULL, 'lmnop');
} {{}}
do_execsql_test alter-17.10 {
SELECT sqlite_rename_parent(NULL,'abc','xyz');
} {{}}
finish_test
+12 -30
View File
@@ -103,21 +103,12 @@ do_test analyze3-1.1.1 {
}
} {1}
do_execsql_test analyze3-1.1.x {
SELECT count(*) FROM t1 WHERE x>200 AND x<300;
SELECT count(*) FROM t1 WHERE x>0 AND x<1100;
} {99 1000}
# The first of the following two SELECT statements visits 99 rows. So
# it is better to use the index. But the second visits every row in
# the table (1000 in total) so it is better to do a full-table scan.
#
do_eqp_test analyze3-1.1.2 {
SELECT sum(y) FROM t1 WHERE x>200 AND x<300
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
do_eqp_test analyze3-1.1.3 {
SELECT sum(y) FROM t1 WHERE x>0 AND x<1100
} {0 0 0 {SCAN TABLE t1}}
} {0 0 0 {SEARCH TABLE t1 USING INDEX i1 (x>? AND x<?)}}
do_test analyze3-1.1.4 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>200 AND x<300 }
@@ -134,17 +125,17 @@ do_test analyze3-1.1.6 {
} {199 0 14850}
do_test analyze3-1.1.7 {
sf_execsql { SELECT sum(y) FROM t1 WHERE x>0 AND x<1100 }
} {999 999 499500}
} {2000 0 499500}
do_test analyze3-1.1.8 {
set l [string range "0" 0 end]
set u [string range "1100" 0 end]
sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
} {999 999 499500}
} {2000 0 499500}
do_test analyze3-1.1.9 {
set l [expr int(0)]
set u [expr int(1100)]
sf_execsql { SELECT sum(y) FROM t1 WHERE x>$l AND x<$u }
} {999 999 499500}
} {2000 0 499500}
# The following tests are similar to the block above. The difference is
@@ -161,17 +152,12 @@ do_test analyze3-1.2.1 {
ANALYZE;
}
} {}
do_execsql_test analyze3-2.1.x {
SELECT count(*) FROM t2 WHERE x>1 AND x<2;
SELECT count(*) FROM t2 WHERE x>0 AND x<99;
} {200 990}
do_eqp_test analyze3-1.2.2 {
SELECT sum(y) FROM t2 WHERE x>1 AND x<2
} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
do_eqp_test analyze3-1.2.3 {
SELECT sum(y) FROM t2 WHERE x>0 AND x<99
} {0 0 0 {SCAN TABLE t2}}
} {0 0 0 {SEARCH TABLE t2 USING INDEX i2 (x>? AND x<?)}}
do_test analyze3-1.2.4 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>12 AND x<20 }
} {161 0 4760}
@@ -187,17 +173,17 @@ do_test analyze3-1.2.6 {
} {161 0 integer integer 4760}
do_test analyze3-1.2.7 {
sf_execsql { SELECT sum(y) FROM t2 WHERE x>0 AND x<99 }
} {999 999 490555}
} {1981 0 490555}
do_test analyze3-1.2.8 {
set l [string range "0" 0 end]
set u [string range "99" 0 end]
sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
} {999 999 text text 490555}
} {1981 0 text text 490555}
do_test analyze3-1.2.9 {
set l [expr int(0)]
set u [expr int(99)]
sf_execsql {SELECT typeof($l), typeof($u), sum(y) FROM t2 WHERE x>$l AND x<$u}
} {999 999 integer integer 490555}
} {1981 0 integer integer 490555}
# Same tests a third time. This time, column x has INTEGER affinity and
# is not the leftmost column of the table. This triggered a bug causing
@@ -213,16 +199,12 @@ do_test analyze3-1.3.1 {
ANALYZE;
}
} {}
do_execsql_test analyze3-1.3.x {
SELECT count(*) FROM t3 WHERE x>200 AND x<300;
SELECT count(*) FROM t3 WHERE x>0 AND x<1100
} {99 1000}
do_eqp_test analyze3-1.3.2 {
SELECT sum(y) FROM t3 WHERE x>200 AND x<300
} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
do_eqp_test analyze3-1.3.3 {
SELECT sum(y) FROM t3 WHERE x>0 AND x<1100
} {0 0 0 {SCAN TABLE t3}}
} {0 0 0 {SEARCH TABLE t3 USING INDEX i3 (x>? AND x<?)}}
do_test analyze3-1.3.4 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>200 AND x<300 }
@@ -239,17 +221,17 @@ do_test analyze3-1.3.6 {
} {199 0 14850}
do_test analyze3-1.3.7 {
sf_execsql { SELECT sum(y) FROM t3 WHERE x>0 AND x<1100 }
} {999 999 499500}
} {2000 0 499500}
do_test analyze3-1.3.8 {
set l [string range "0" 0 end]
set u [string range "1100" 0 end]
sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
} {999 999 499500}
} {2000 0 499500}
do_test analyze3-1.3.9 {
set l [expr int(0)]
set u [expr int(1100)]
sf_execsql { SELECT sum(y) FROM t3 WHERE x>$l AND x<$u }
} {999 999 499500}
} {2000 0 499500}
#-------------------------------------------------------------------------
# Test that the values of bound SQL variables may be used for the LIKE
+5 -5
View File
@@ -566,7 +566,7 @@ foreach {tn schema} {
drop_all_tables
do_test 13.1 {
execsql {
CREATE TABLE t1(a, b, c, d);
CREATE TABLE t1(a, b, c);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(b, c);
}
@@ -577,16 +577,16 @@ do_test 13.1 {
execsql ANALYZE
} {}
do_eqp_test 13.2.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<12
SELECT * FROM t1 WHERE a='abc' AND rowid<15 AND b<20
} {/SEARCH TABLE t1 USING INDEX i1/}
do_eqp_test 13.2.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<12
SELECT * FROM t1 WHERE a='abc' AND rowid<'15' AND b<20
} {/SEARCH TABLE t1 USING INDEX i1/}
do_eqp_test 13.3.1 {
SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<12
SELECT * FROM t1 WHERE a='abc' AND rowid<100 AND b<20
} {/SEARCH TABLE t1 USING INDEX i2/}
do_eqp_test 13.3.2 {
SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<12
SELECT * FROM t1 WHERE a='abc' AND rowid<'100' AND b<20
} {/SEARCH TABLE t1 USING INDEX i2/}
#-------------------------------------------------------------------------
-2
View File
@@ -97,8 +97,6 @@ do_test autoindex1-210 {
PRAGMA automatic_index=ON;
ANALYZE;
UPDATE sqlite_stat1 SET stat='10000' WHERE tbl='t1';
-- Table t2 actually contains 8 rows.
UPDATE sqlite_stat1 SET stat='16' WHERE tbl='t2';
ANALYZE sqlite_master;
SELECT b, (SELECT d FROM t2 WHERE c=a) FROM t1;
}
-54
View File
@@ -58,24 +58,12 @@ proc do_backcompat_test {rv bin1 bin2 script} {
code1 { sqlite3 db test.db }
code2 { sqlite3 db test.db }
foreach c {code1 code2} {
$c {
set v [split [db version] .]
if {[llength $v]==3} {lappend v 0}
set ::sqlite_libversion [format \
"%d%.2d%.2d%2d" [lindex $v 0] [lindex $v 1] [lindex $v 2] [lindex $v 3]
]
}
}
uplevel $script
catch { code1 { db close } }
catch { code2 { db close } }
catch { close $::bc_chan2 }
catch { close $::bc_chan1 }
}
array set ::incompatible [list]
@@ -393,48 +381,6 @@ ifcapable fts3 {
} {
do_test backcompat-3.7 [list sql1 $q] [sql2 $q]
}
# Now test that an incremental merge can be started by one version
# and finished by another. And that the integrity-check still
# passes.
do_test backcompat-3.8 {
sql1 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS t2;
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE t2 USING fts3(words);
}
code1 [list source $testdir/genesis.tcl]
code1 { fts_kjv_genesis }
sql1 {
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
INSERT INTO t2 SELECT words FROM t1;
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
}
} {0 {0 1 2 3 4 5}}
if {[code1 { set ::sqlite_libversion }] >=3071200
&& [code2 { set ::sqlite_libversion }] >=3071200
} {
do_test backcompat-3.9 {
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql2 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql1 { INSERT INTO t2(t2) VALUES('merge=100,4'); }
sql2 { INSERT INTO t2(t2) VALUES('merge=2500,4'); }
sql2 {
SELECT level, group_concat(idx, ' ') FROM t2_segdir GROUP BY level;
}
} {0 {0 1} 1 0}
do_test backcompat-3.10 {
sql1 { INSERT INTO t2(t2) VALUES('integrity-check') }
sql2 { INSERT INTO t2(t2) VALUES('integrity-check') }
} {}
}
}
}
}
-251
View File
@@ -1,251 +0,0 @@
# 2014-04-26
#
# 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.
#
#***********************************************************************
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix cost
do_execsql_test 1.1 {
CREATE TABLE t3(id INTEGER PRIMARY KEY, b NOT NULL);
CREATE TABLE t4(c, d, e);
CREATE UNIQUE INDEX i3 ON t3(b);
CREATE UNIQUE INDEX i4 ON t4(c, d);
}
do_eqp_test 1.2 {
SELECT e FROM t3, t4 WHERE b=c ORDER BY b, d;
} {
0 0 0 {SCAN TABLE t3 USING COVERING INDEX i3}
0 1 1 {SEARCH TABLE t4 USING INDEX i4 (c=?)}
}
do_execsql_test 2.1 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
}
# It is better to use an index for ORDER BY than sort externally, even
# if the index is a non-covering index.
do_eqp_test 2.2 {
SELECT * FROM t1 ORDER BY a;
} {
0 0 0 {SCAN TABLE t1 USING INDEX i1}
}
do_execsql_test 3.1 {
CREATE TABLE t5(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
CREATE INDEX t5b ON t5(b);
CREATE INDEX t5c ON t5(c);
CREATE INDEX t5d ON t5(d);
CREATE INDEX t5e ON t5(e);
CREATE INDEX t5f ON t5(f);
CREATE INDEX t5g ON t5(g);
}
do_eqp_test 3.2 {
SELECT a FROM t5
WHERE b IS NULL OR c IS NULL OR d IS NULL
ORDER BY a;
} {
0 0 0 {SEARCH TABLE t5 USING INDEX t5b (b=?)}
0 0 0 {SEARCH TABLE t5 USING INDEX t5c (c=?)}
0 0 0 {SEARCH TABLE t5 USING INDEX t5d (d=?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
#-------------------------------------------------------------------------
# If there is no likelihood() or stat3 data, SQLite assumes that a closed
# range scan (e.g. one constrained by "col BETWEEN ? AND ?" constraint)
# visits 1/64 of the rows in a table.
#
# Note: 1/63 =~ 0.016
# Note: 1/65 =~ 0.015
#
reset_db
do_execsql_test 4.1 {
CREATE TABLE t1(a, b);
CREATE INDEX i1 ON t1(a);
CREATE INDEX i2 ON t1(b);
}
do_eqp_test 4.2 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.014) AND b BETWEEN ? AND ?;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX i1 (a=?)}
}
do_eqp_test 4.3 {
SELECT * FROM t1 WHERE likelihood(a=?, 0.016) AND b BETWEEN ? AND ?;
} {
0 0 0 {SEARCH TABLE t1 USING INDEX i2 (b>? AND b<?)}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.1 {
CREATE TABLE t2(x, y);
CREATE INDEX t2i1 ON t2(x);
}
do_eqp_test 5.2 {
SELECT * FROM t2 ORDER BY x, y;
} {
0 0 0 {SCAN TABLE t2 USING INDEX t2i1}
0 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
}
do_eqp_test 5.3 {
SELECT * FROM t2 WHERE x BETWEEN ? AND ? ORDER BY rowid;
} {
0 0 0 {SEARCH TABLE t2 USING INDEX t2i1 (x>? AND x<?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
# where7.test, where8.test:
#
do_execsql_test 6.1 {
CREATE TABLE t3(a INTEGER PRIMARY KEY, b, c);
CREATE INDEX t3i1 ON t3(b);
CREATE INDEX t3i2 ON t3(c);
}
do_eqp_test 6.2 {
SELECT a FROM t3 WHERE (b BETWEEN 2 AND 4) OR c=100 ORDER BY a
} {
0 0 0 {SEARCH TABLE t3 USING INDEX t3i1 (b>? AND b<?)}
0 0 0 {SEARCH TABLE t3 USING INDEX t3i2 (c=?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 7.1 {
CREATE TABLE t1(a INTEGER PRIMARY KEY,b,c,d,e,f,g);
CREATE INDEX t1b ON t1(b);
CREATE INDEX t1c ON t1(c);
CREATE INDEX t1d ON t1(d);
CREATE INDEX t1e ON t1(e);
CREATE INDEX t1f ON t1(f);
CREATE INDEX t1g ON t1(g);
}
do_eqp_test 7.2 {
SELECT a FROM t1
WHERE (b>=950 AND b<=1010) OR (b IS NULL AND c NOT NULL)
ORDER BY a
} {
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b>? AND b<?)}
0 0 0 {SEARCH TABLE t1 USING INDEX t1b (b=?)}
0 0 0 {USE TEMP B-TREE FOR ORDER BY}
}
do_eqp_test 7.3 {
SELECT rowid FROM t1
WHERE (+b IS NULL AND c NOT NULL AND d NOT NULL)
OR (b NOT NULL AND c IS NULL AND d NOT NULL)
OR (b NOT NULL AND c NOT NULL AND d IS NULL)
} {
0 0 0 {SCAN TABLE t1}
}
do_eqp_test 7.4 {
SELECT rowid FROM t1 WHERE (+b IS NULL AND c NOT NULL) OR c IS NULL
} {
0 0 0 {SCAN TABLE t1}
}
#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 8.1 {
CREATE TABLE composer(
cid INTEGER PRIMARY KEY,
cname TEXT
);
CREATE TABLE album(
aid INTEGER PRIMARY KEY,
aname TEXT
);
CREATE TABLE track(
tid INTEGER PRIMARY KEY,
cid INTEGER REFERENCES composer,
aid INTEGER REFERENCES album,
title TEXT
);
CREATE INDEX track_i1 ON track(cid);
CREATE INDEX track_i2 ON track(aid);
}
do_eqp_test 8.2 {
SELECT DISTINCT aname
FROM album, composer, track
WHERE cname LIKE '%bach%'
AND unlikely(composer.cid=track.cid)
AND unlikely(album.aid=track.aid);
} {
0 0 2 {SCAN TABLE track}
0 1 0 {SEARCH TABLE album USING INTEGER PRIMARY KEY (rowid=?)}
0 2 1 {SEARCH TABLE composer USING INTEGER PRIMARY KEY (rowid=?)}
0 0 0 {USE TEMP B-TREE FOR DISTINCT}
}
#-------------------------------------------------------------------------
#
do_execsql_test 9.1 {
CREATE TABLE t1(
a,b,c,d,e, f,g,h,i,j,
k,l,m,n,o, p,q,r,s,t
);
CREATE INDEX i1 ON t1(k,l,m,n,o,p,q,r,s,t);
}
do_test 9.2 {
for {set i 0} {$i < 100} {incr i} {
execsql { INSERT INTO t1 DEFAULT VALUES }
}
execsql {
ANALYZE;
CREATE INDEX i2 ON t1(a,b,c,d,e,f,g,h,i,j);
}
} {}
set L [list a=? b=? c=? d=? e=? f=? g=? h=? i=? j=?]
foreach {tn nTerm nRow} {
1 1 10
2 2 9
3 3 8
4 4 7
5 5 6
6 6 5
7 7 5
8 8 5
9 9 5
10 10 5
} {
set w [join [lrange $L 0 [expr $nTerm-1]] " AND "]
set p1 [expr ($nRow-1) / 100.0]
set p2 [expr ($nRow+1) / 100.0]
set sql1 "SELECT * FROM t1 WHERE likelihood(k=?, $p1) AND $w"
set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w"
do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/}
do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/}
}
finish_test
+2 -3
View File
@@ -884,10 +884,9 @@ do_execsql_test e_createtable-3.3.1 {
);
} {}
# EVIDENCE-OF: R-36381-62919 For the purposes of the DEFAULT clause, an
# EVIDENCE-OF: R-10288-43169 For the purposes of the DEFAULT clause, an
# expression is considered constant provided that it does not contain
# any sub-queries, column or table references, or string literals
# enclosed in double-quotes instead of single-quotes.
# any sub-queries or string constants enclosed in double quotes.
#
do_createtable_tests 3.4.1 -error {
default value of column [x] is not constant
+5 -6
View File
@@ -135,9 +135,9 @@ reset_db
#
# This also tests that foreign key constraints are disabled by default.
#
# EVIDENCE-OF: R-44261-39702 Foreign key constraints are disabled by
# EVIDENCE-OF: R-59578-04990 Foreign key constraints are disabled by
# default (for backwards compatibility), so must be enabled separately
# for each database connection.
# for each database connection separately.
#
drop_all_tables
do_test e_fkey-4.1 {
@@ -163,10 +163,9 @@ do_test e_fkey-4.2 {
} {world}
#-------------------------------------------------------------------------
# EVIDENCE-OF: R-08013-37737 The application can also use a PRAGMA
# EVIDENCE-OF: R-15278-54456 The application can can also use a PRAGMA
# foreign_keys statement to determine if foreign keys are currently
# enabled.
#
# This also tests the example code in section 2 of foreignkeys.in.
#
@@ -2991,8 +2990,8 @@ if {[clang_sanitize_address]==0} {
# The setting of the recursive_triggers pragma does not affect foreign
# key actions.
#
# EVIDENCE-OF: R-44355-00270 The PRAGMA recursive_triggers setting does
# not affect the operation of foreign key actions.
# EVIDENCE-OF: R-51769-32730 The PRAGMA recursive_triggers setting does
# not not affect the operation of foreign key actions.
#
foreach recursive_triggers_setting [list 0 1 ON OFF] {
drop_all_tables
+6 -50
View File
@@ -312,8 +312,8 @@ do_eqp_test 4.2.3 {
} {
1 0 0 {SCAN TABLE t1}
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
2 0 0 {SCAN TABLE t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION)}
}
do_eqp_test 4.2.4 {
@@ -321,8 +321,8 @@ do_eqp_test 4.2.4 {
} {
1 0 0 {SCAN TABLE t1}
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
2 0 0 {SCAN TABLE t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (INTERSECT)}
}
do_eqp_test 4.2.5 {
@@ -330,8 +330,8 @@ do_eqp_test 4.2.5 {
} {
1 0 0 {SCAN TABLE t1}
1 0 0 {USE TEMP B-TREE FOR ORDER BY}
2 0 0 {SCAN TABLE t2 USING INDEX t2i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
2 0 0 {SCAN TABLE t2}
2 0 0 {USE TEMP B-TREE FOR ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (EXCEPT)}
}
@@ -598,49 +598,5 @@ det 7.5 "SELECT count(*) FROM t2" {
0 0 0 {SCAN TABLE t2 USING COVERING INDEX i1}
}
#-------------------------------------------------------------------------
# The following tests - eqp-8.* - test that queries that use the OP_Count
# optimization return something sensible with EQP.
#
drop_all_tables
do_execsql_test 8.0 {
CREATE TABLE t1(a, b, c, PRIMARY KEY(b, c)) WITHOUT ROWID;
CREATE TABLE t2(a, b, c);
}
det 8.1.1 "SELECT * FROM t2" {
0 0 0 {SCAN TABLE t2}
}
det 8.1.2 "SELECT * FROM t2 WHERE rowid=?" {
0 0 0 {SEARCH TABLE t2 USING INTEGER PRIMARY KEY (rowid=?)}
}
det 8.1.3 "SELECT count(*) FROM t2" {
0 0 0 {SCAN TABLE t2}
}
det 8.2.1 "SELECT * FROM t1" {
0 0 0 {SCAN TABLE t1}
}
det 8.2.2 "SELECT * FROM t1 WHERE b=?" {
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=?)}
}
det 8.2.3 "SELECT * FROM t1 WHERE b=? AND c=?" {
0 0 0 {SEARCH TABLE t1 USING PRIMARY KEY (b=? AND c=?)}
}
det 8.2.4 "SELECT count(*) FROM t1" {
0 0 0 {SCAN TABLE t1}
}
finish_test
+9 -10
View File
@@ -213,17 +213,16 @@ do_test fts3d-4.matches {
{0 1 0 4 0 2 5 3 0 3 9 1 0 5 11 4} \
{0 0 0 4 0 4 5 2 0 3 8 1 0 5 10 4}]
puts [db eval {SELECT c FROM t1 } ]
check_terms_all fts3d-4.1 {a four is test that this was}
check_terms_all fts3d-4.1 {a four is one test that this three two was}
check_doclist_all fts3d-4.1.1 a {[1 0[2]] [2 0[2]] [3 0[2]]}
check_doclist_all fts3d-4.1.2 four {}
check_doclist_all fts3d-4.1.3 is {[1 0[1]] [3 0[1]]}
#check_doclist_all fts3d-4.1.4 one {}
check_doclist_all fts3d-4.1.4 one {}
check_doclist_all fts3d-4.1.5 test {[1 0[3]] [2 0[3]] [3 0[3]]}
check_doclist_all fts3d-4.1.6 that {[2 0[0]]}
check_doclist_all fts3d-4.1.7 this {[1 0[0]] [3 0[0]]}
#check_doclist_all fts3d-4.1.8 three {}
#check_doclist_all fts3d-4.1.9 two {}
check_doclist_all fts3d-4.1.8 three {}
check_doclist_all fts3d-4.1.9 two {}
check_doclist_all fts3d-4.1.10 was {[2 0[1]]}
check_terms fts3d-4.2 0 0 {a four test that was}
@@ -240,16 +239,16 @@ check_doclist fts3d-4.3.3 0 1 is {[3 0[1]]}
check_doclist fts3d-4.3.4 0 1 test {[3 0[3]]}
check_doclist fts3d-4.3.5 0 1 this {[3 0[0]]}
check_terms fts3d-4.4 1 0 {a four is test that this was}
check_terms fts3d-4.4 1 0 {a four is one test that this three two was}
check_doclist fts3d-4.4.1 1 0 a {[1 0[2]] [2 0[2]] [3 0[2]]}
check_doclist fts3d-4.4.2 1 0 four {[2 0[4]] [3 0[4]]}
check_doclist fts3d-4.4.2 1 0 four {[1] [2 0[4]] [3 0[4]]}
check_doclist fts3d-4.4.3 1 0 is {[1 0[1]] [3 0[1]]}
#check_doclist fts3d-4.4.4 1 0 one {[1] [2] [3]}
check_doclist fts3d-4.4.4 1 0 one {[1] [2] [3]}
check_doclist fts3d-4.4.5 1 0 test {[1 0[3]] [2 0[3]] [3 0[3]]}
check_doclist fts3d-4.4.6 1 0 that {[2 0[0]]}
check_doclist fts3d-4.4.7 1 0 this {[1 0[0]] [3 0[0]]}
#check_doclist fts3d-4.4.8 1 0 three {[1] [2] [3]}
#check_doclist fts3d-4.4.9 1 0 two {[1] [2] [3]}
check_doclist fts3d-4.4.8 1 0 three {[1] [2] [3]}
check_doclist fts3d-4.4.9 1 0 two {[1] [2] [3]}
check_doclist fts3d-4.4.10 1 0 was {[2 0[1]]}
# Optimize should leave the result in the level of the highest-level
-1
View File
@@ -59,7 +59,6 @@ do_execsql_test 1.2.1 {
SELECT content FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
} {{a b c d e f a x y}}
do_execsql_test 1.2.2 {
SELECT snippet(t1, '[', ']'), offsets(t1), mit(matchinfo(t1, 'pcxnal'))
FROM t1 WHERE t1 MATCH 'f (e NEAR/2 a)';
-5
View File
@@ -509,9 +509,4 @@ do_test fts3expr-8.7 { test_fts3expr "((((blah!))))" } {PHRASE 3 0 blah}
do_test fts3expr-8.8 { test_fts3expr "(,(blah-),)" } {PHRASE 3 0 blah}
set sqlite_fts3_enable_parentheses 0
do_test fts3expr-9.1 {
test_fts3expr "f (e NEAR/2 a)"
} {AND {PHRASE 3 0 f} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}}
finish_test
-57
View File
@@ -1,57 +0,0 @@
# 2014 May 7
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS3 module.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts3expr4
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3||!icu {
finish_test
return
}
set sqlite_fts3_enable_parentheses 1
proc test_icu_fts3expr {expr} {
db one {SELECT fts3_exprtest('icu', $expr, 'a', 'b', 'c')}
}
proc do_icu_expr_test {tn expr res} {
uplevel [list do_test $tn [list test_icu_fts3expr $expr] $res]
}
#-------------------------------------------------------------------------
#
do_icu_expr_test 1.1 "abcd" {PHRASE 3 0 abcd}
do_icu_expr_test 1.2 " tag " {PHRASE 3 0 tag}
do_icu_expr_test 1.3 {"x y z"} {PHRASE 3 0 x y z}
do_icu_expr_test 1.4 {x OR y} {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
do_icu_expr_test 1.5 {(x OR y)} {OR {PHRASE 3 0 x} {PHRASE 3 0 y}}
do_icu_expr_test 1.6 { "(x OR y)" } {PHRASE 3 0 ( x or y )}
# In "col:word", if "col" is not the name of a column, the entire thing
# is passed to the tokenizer.
#
do_icu_expr_test 1.7 {a:word} {PHRASE 0 0 word}
do_icu_expr_test 1.8 {d:word} {PHRASE 3 0 d:word}
set sqlite_fts3_enable_parentheses 0
do_icu_expr_test 2.1 {
f (e NEAR/2 a)
} {AND {AND {AND {PHRASE 3 0 f} {PHRASE 3 0 (}} {NEAR/2 {PHRASE 3 0 e} {PHRASE 3 0 a}}} {PHRASE 3 0 )}}
finish_test
-437
View File
@@ -1,437 +0,0 @@
# 2014 May 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS4 module.
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4growth
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
finish_test
return
}
source $testdir/genesis.tcl
do_execsql_test 1.1 { CREATE VIRTUAL TABLE x1 USING fts3; }
do_test 1.2 {
foreach L {
{"See here, young man," said Mulga Bill, "from Walgett to the sea,}
{From Conroy's Gap to Castlereagh, there's none can ride like me.}
{I'm good all round at everything as everybody knows,}
{Although I'm not the one to talk -- I hate a man that blows.}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql { SELECT end_block, length(root) FROM x1_segdir }
} {{0 114} 114 {0 118} 118 {0 95} 95 {0 115} 115}
do_execsql_test 1.3 {
INSERT INTO x1(x1) VALUES('optimize');
SELECT level, end_block, length(root) FROM x1_segdir;
} {0 {0 394} 394}
do_test 1.4 {
foreach L {
{But riding is my special gift, my chiefest, sole delight;}
{Just ask a wild duck can it swim, a wildcat can it fight.}
{There's nothing clothed in hair or hide, or built of flesh or steel,}
{There's nothing walks or jumps, or runs, on axle, hoof, or wheel,}
{But what I'll sit, while hide will hold and girths and straps are tight:}
{I'll ride this here two-wheeled concern right straight away at sight."}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql {
INSERT INTO x1(x1) VALUES('merge=4,4');
SELECT level, end_block, length(root) FROM x1_segdir;
}
} {0 {0 110} 110 0 {0 132} 132 0 {0 129} 129 1 {128 658} 2}
do_execsql_test 1.5 {
SELECT length(block) FROM x1_segments;
} {658 {}}
do_test 1.6 {
foreach L {
{'Twas Mulga Bill, from Eaglehawk, that sought his own abode,}
{That perched above Dead Man's Creek, beside the mountain road.}
{He turned the cycle down the hill and mounted for the fray,}
{But 'ere he'd gone a dozen yards it bolted clean away.}
{It left the track, and through the trees, just like a silver steak,}
{It whistled down the awful slope towards the Dead Man's Creek.}
{It shaved a stump by half an inch, it dodged a big white-box:}
{The very wallaroos in fright went scrambling up the rocks,}
{The wombats hiding in their caves dug deeper underground,}
{As Mulga Bill, as white as chalk, sat tight to every bound.}
{It struck a stone and gave a spring that cleared a fallen tree,}
{It raced beside a precipice as close as close could be;}
{And then as Mulga Bill let out one last despairing shriek}
{It made a leap of twenty feet into the Dead Man's Creek.}
} {
execsql { INSERT INTO x1 VALUES($L) }
}
execsql {
SELECT level, end_block, length(root) FROM x1_segdir;
}
} {1 {128 658} 2 1 {130 1377} 6 0 {0 117} 117}
do_execsql_test 1.7 {
SELECT sum(length(block)) FROM x1_segments WHERE blockid IN (129, 130);
} {1377}
#-------------------------------------------------------------------------
#
do_execsql_test 2.1 {
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE x2 USING fts4;
}
fts_kjv_genesis
do_test 2.2 {
foreach id [db eval {SELECT docid FROM t1}] {
execsql {
INSERT INTO x2(docid, content) SELECT $id, words FROM t1 WHERE docid=$id
}
}
foreach id [db eval {SELECT docid FROM t1}] {
execsql {
INSERT INTO x2(docid, content) SELECT NULL, words FROM t1 WHERE docid=$id
}
if {[db one {SELECT count(*) FROM x2_segdir WHERE level<2}]==2} break
}
} {}
do_execsql_test 2.3 {
SELECT count(*) FROM x2_segdir WHERE level=2;
SELECT count(*) FROM x2_segdir WHERE level=3;
} {6 0}
do_execsql_test 2.4 {
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT count(*) FROM x2_segdir WHERE level=2;
SELECT count(*) FROM x2_segdir WHERE level=3;
} {6 1}
do_execsql_test 2.5 {
SELECT end_block FROM x2_segdir WHERE level=3;
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT end_block FROM x2_segdir WHERE level=3;
INSERT INTO x2(x2) VALUES('merge=4,4');
SELECT end_block FROM x2_segdir WHERE level=3;
} {{3828 -3430} {3828 -10191} {3828 -14109}}
do_execsql_test 2.6 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
} {14109}
do_execsql_test 2.7 {
INSERT INTO x2(x2) VALUES('merge=1000,4');
SELECT end_block FROM x2_segdir WHERE level=3;
} {{3828 86120}}
do_execsql_test 2.8 {
SELECT sum(length(block)) FROM x2_segdir, x2_segments WHERE
blockid BETWEEN start_block AND leaves_end_block
AND level=3
} {86120}
#--------------------------------------------------------------------------
# Test that delete markers are removed from FTS segments when possible.
# It is only possible to remove delete markers when the output of the
# merge operation will become the oldest segment in the index.
#
# 3.1 - when the oldest segment is created by an 'optimize'.
# 3.2 - when the oldest segment is created by an incremental merge.
# 3.3 - by a crisis merge.
#
proc insert_doc {args} {
foreach iDoc $args {
set L [lindex {
{In your eagerness to engage the Trojans,}
{dont any of you charge ahead of others,}
{trusting in your strength and horsemanship.}
{And dont lag behind. That will hurt our charge.}
{Any man whose chariot confronts an enemys}
{should thrust with his spear at him from there.}
{Thats the most effective tactic, the way}
{men wiped out city strongholds long ago —}
{their chests full of that style and spirit.}
} [expr $iDoc%9]]
execsql { REPLACE INTO x3(docid, content) VALUES($iDoc, $L) }
}
}
proc delete_doc {args} {
foreach iDoc $args {
execsql { DELETE FROM x3 WHERE docid = $iDoc }
}
}
proc second {x} { lindex $x 1 }
db func second second
do_execsql_test 3.0 { CREATE VIRTUAL TABLE x3 USING fts4 }
do_test 3.1.1 {
db transaction { insert_doc 1 2 3 4 5 6 }
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {0 0 412}
do_test 3.1.2 {
delete_doc 1 2 3 4 5 6
execsql { SELECT count(*) FROM x3_segdir }
} {0}
do_test 3.1.3 {
db transaction {
insert_doc 1 2 3 4 5 6 7 8 9
delete_doc 9 8 7
}
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {0 0 591 0 1 65 0 2 72 0 3 76}
do_test 3.1.4 {
execsql { INSERT INTO x3(x3) VALUES('optimize') }
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {0 0 412}
do_test 3.2.1 {
execsql { DELETE FROM x3 }
insert_doc 8 7 6 5 4 3 2 1
delete_doc 7 8
execsql { SELECT count(*) FROM x3_segdir }
} {10}
do_test 3.2.2 {
execsql { INSERT INTO x3(x3) VALUES('merge=500,10') }
execsql { SELECT level, idx, second(end_block) FROM x3_segdir }
} {1 0 412}
# This assumes the crisis merge happens when there are already 16
# segments and one more is added.
#
do_test 3.3.1 {
execsql { DELETE FROM x3 }
insert_doc 1 2 3 4 5 6 7 8 9 10 11
delete_doc 11 10 9 8 7
execsql { SELECT count(*) FROM x3_segdir }
} {16}
do_test 3.3.2 {
insert_doc 12
execsql { SELECT level, idx, second(end_block) FROM x3_segdir WHERE level=1 }
} {1 0 412}
#--------------------------------------------------------------------------
# Check a theory on a bug in fts4 - that segments with idx==0 were not
# being incrementally merged correctly. Theory turned out to be false.
#
do_execsql_test 4.1 {
DROP TABLE IF EXISTS x4;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE x4 USING fts4(words);
}
do_test 4.2 {
fts_kjv_genesis
execsql { INSERT INTO x4 SELECT words FROM t1 }
execsql { INSERT INTO x4 SELECT words FROM t1 }
} {}
do_execsql_test 4.3 {
SELECT level, idx, second(end_block) FROM x4_segdir
} {0 0 117483 0 1 118006}
do_execsql_test 4.4 {
INSERT INTO x4(x4) VALUES('merge=10,2');
SELECT count(*) FROM x4_segdir;
} {3}
do_execsql_test 4.5 {
INSERT INTO x4(x4) VALUES('merge=10,2');
SELECT count(*) FROM x4_segdir;
} {3}
do_execsql_test 4.6 {
INSERT INTO x4(x4) VALUES('merge=1000,2');
SELECT count(*) FROM x4_segdir;
} {1}
#--------------------------------------------------------------------------
# Check that segments are not promoted if the "end_block" field does not
# contain a size.
#
do_execsql_test 5.1 {
DROP TABLE IF EXISTS x2;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(docid, words);
CREATE VIRTUAL TABLE x2 USING fts4;
}
fts_kjv_genesis
proc first {L} {lindex $L 0}
db func first first
do_test 5.2 {
foreach r [db eval { SELECT rowid FROM t1 }] {
execsql {
INSERT INTO x2(docid, content) SELECT docid, words FROM t1 WHERE rowid=$r
}
}
foreach d [db eval { SELECT docid FROM t1 LIMIT -1 OFFSET 20 }] {
execsql { DELETE FROM x2 WHERE docid = $d }
}
execsql {
INSERT INTO x2(x2) VALUES('optimize');
SELECT level, idx, end_block FROM x2_segdir
}
} {2 0 {752 1926}}
do_execsql_test 5.3 {
UPDATE x2_segdir SET end_block = CAST( first(end_block) AS INTEGER );
SELECT end_block, typeof(end_block) FROM x2_segdir;
} {752 integer}
do_execsql_test 5.4 {
INSERT INTO x2 SELECT words FROM t1 LIMIT 50;
SELECT level, idx, end_block FROM x2_segdir
} {2 0 752 0 0 {758 5174}}
do_execsql_test 5.5 {
UPDATE x2_segdir SET end_block = end_block || ' 1926' WHERE level=2;
INSERT INTO x2 SELECT words FROM t1 LIMIT 40;
SELECT level, idx, end_block FROM x2_segdir
} {0 0 {752 1926} 0 1 {758 5174} 0 2 {763 4170}}
proc t1_to_x2 {} {
foreach id [db eval {SELECT docid FROM t1 LIMIT 2}] {
execsql {
DELETE FROM x2 WHERE docid=$id;
INSERT INTO x2(docid, content) SELECT $id, words FROM t1 WHERE docid=$id;
}
}
}
#--------------------------------------------------------------------------
# Check that segments created by auto-merge are not promoted until they
# are completed.
#
do_execsql_test 6.1 {
CREATE VIRTUAL TABLE x5 USING fts4;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 0;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 25;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 50;
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 75;
SELECT count(*) FROM x5_segdir
} {4}
do_execsql_test 6.2 {
INSERT INTO x5(x5) VALUES('merge=2,4');
SELECT level, idx, end_block FROM x5_segdir;
} {0 0 {10 9216} 0 1 {21 9330} 0 2 {31 8850} 0 3 {40 8689} 1 0 {1320 -3117}}
do_execsql_test 6.3 {
INSERT INTO x5 SELECT words FROM t1 LIMIT 100 OFFSET 100;
SELECT level, idx, end_block FROM x5_segdir;
} {
0 0 {10 9216} 0 1 {21 9330} 0 2 {31 8850}
0 3 {40 8689} 1 0 {1320 -3117} 0 4 {1329 8297}
}
do_execsql_test 6.4 {
INSERT INTO x5(x5) VALUES('merge=200,4');
SELECT level, idx, end_block FROM x5_segdir;
} {0 0 {1329 8297} 1 0 {1320 28009}}
do_execsql_test 6.5 {
INSERT INTO x5 SELECT words FROM t1;
SELECT level, idx, end_block FROM x5_segdir;
} {
0 1 {1329 8297} 0 0 {1320 28009} 0 2 {1449 118006}
}
#--------------------------------------------------------------------------
# Ensure that if part of an incremental merge is performed by an old
# version that does not support storing segment sizes in the end_block
# field, no size is stored in the final segment (as it would be incorrect).
#
do_execsql_test 7.1 {
CREATE VIRTUAL TABLE x6 USING fts4;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
INSERT INTO x6 SELECT words FROM t1;
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
}
do_execsql_test 7.2 {
INSERT INTO x6(x6) VALUES('merge=25,4');
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 {16014 -51226}
}
do_execsql_test 7.3 {
UPDATE x6_segdir SET end_block = first(end_block) WHERE level=1;
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 16014
}
do_execsql_test 7.4 {
INSERT INTO x6(x6) VALUES('merge=25,4');
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {118 117483} 0 1 {238 118006} 0 2 {358 118006}
0 3 {478 118006} 0 4 {598 118006} 0 5 {718 118006}
1 0 16014
}
do_execsql_test 7.5 {
INSERT INTO x6(x6) VALUES('merge=2500,4');
SELECT level, idx, end_block FROM x6_segdir;
} {
0 0 {598 118006} 0 1 {718 118006} 1 0 16014
}
do_execsql_test 7.6 {
INSERT INTO x6(x6) VALUES('merge=2500,2');
SELECT level, idx, start_block, leaves_end_block, end_block FROM x6_segdir;
} {
2 0 23695 24147 {41262 633507}
}
do_execsql_test 7.7 {
SELECT sum(length(block)) FROM x6_segments
WHERE blockid BETWEEN 23695 AND 24147
} {633507}
finish_test
-93
View File
@@ -1,93 +0,0 @@
# 2014 May 12
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS4 module.
#
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix fts4growth2
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts3 {
finish_test
return
}
source $testdir/genesis.tcl
do_execsql_test 1.0 { CREATE TABLE t1(docid, words); }
fts_kjv_genesis
proc structure {} {
puts [ db eval {SELECT level, count(*) FROM x1_segdir GROUP BY level} ]
}
proc tt {val} {
execsql {
DELETE FROM x1
WHERE docid IN (SELECT docid FROM t1 WHERE (rowid-1)%4==$val+0);
}
execsql {
INSERT INTO x1(docid, content)
SELECT docid, words FROM t1 WHERE (rowid%4)==$val+0;
}
}
do_execsql_test 1.1 {
CREATE VIRTUAL TABLE x1 USING fts4;
INSERT INTO x1(x1) VALUES('automerge=2');
}
do_test 1.2 {
for {set i 0} {$i < 40} {incr i} {
tt 0 ; tt 1 ; tt 2 ; tt 3
}
execsql {
SELECT max(level) FROM x1_segdir;
SELECT count(*) FROM x1_segdir WHERE level=2;
}
} {2 1}
do_test 1.3 {
for {set i 0} {$i < 40} {incr i} {
tt 0 ; tt 1 ; tt 2 ; tt 3
}
execsql {
SELECT max(level) FROM x1_segdir;
SELECT count(*) FROM x1_segdir WHERE level=2;
}
} {2 1}
#-------------------------------------------------------------------------
#
do_execsql_test 2.1 {
DELETE FROM t1 WHERE rowid>16;
DROP TABLE IF EXISTS x1;
CREATE VIRTUAL TABLE x1 USING fts4;
}
db func second second
proc second {L} {lindex $L 1}
for {set tn 0} {$tn < 40} {incr tn} {
do_test 2.2.$tn {
for {set i 0} {$i < 100} {incr i} {
tt 0 ; tt 1 ; tt 2 ; tt 3
}
execsql { SELECT max(level) FROM x1_segdir }
} {1}
}
finish_test
-44
View File
@@ -53,50 +53,6 @@ do_execsql_test 2.2 { SELECT count(*) FROM t1_segdir; } 35
do_execsql_test 2.3 { INSERT INTO t1(t1) VALUES('optimize') } {}
do_execsql_test 2.4 { SELECT count(*) FROM t1_segdir; } 1
#-------------------------------------------------------------------------
# Now test that the automerge=? option appears to work.
#
do_execsql_test 2.1 { CREATE VIRTUAL TABLE t2 USING fts4; }
set doc ""
foreach c1 "a b c d e f g h i j" {
foreach c2 "a b c d e f g h i j" {
foreach c3 "a b c d e f g h i j" {
lappend doc "$c1$c2$c3"
}
}
}
set doc [string repeat $doc 10]
foreach {tn am expected} {
1 {automerge=2} {1 1 2 1 4 1 6 1}
2 {automerge=4} {1 2 2 1 3 1}
3 {automerge=8} {0 4 1 3 2 1}
4 {automerge=1} {0 4 1 3 2 1}
} {
foreach {tn2 openclose} {1 {} 2 { db close ; sqlite3 db test.db }} {
do_test 2.2.$tn.$tn2 {
execsql { DELETE FROM t2 }
execsql { INSERT INTO t2(t2) VALUES($am) };
eval $openclose
for {set i 0} {$i < 100} {incr i} {
execsql {
BEGIN;
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
INSERT INTO t2 VALUES($doc);
COMMIT;
}
}
execsql { SELECT level, count(*) FROM t2_segdir GROUP BY level }
} [list {*}$expected]
}
}
sqlite3_enable_shared_cache $::enable_shared_cache
finish_test
-45
View File
@@ -165,51 +165,6 @@ do_execsql_test 5.4 { SELECT docid FROM t2 WHERE t2 MATCH 'c' } {3}
do_execsql_test 5.x { DROP TABLE t2 }
#-------------------------------------------------------------------------
# Check that if an indexed column name is a prefix of a notindexed column
# name, the column is still correctly tokenized. This was a problem at one
# point.
do_execsql_test 6.1.1 {
CREATE VIRTUAL TABLE t1 USING fts4(
poiCategory, poiCategoryId, notindexed=poiCategoryId
);
INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
}
do_execsql_test 6.1.2 {
SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
} { Restaurant 6021 }
do_execsql_test 6.1.3 {
SELECT * FROM t1 WHERE t1 MATCH 're*';
} { Restaurant 6021 }
do_execsql_test 6.1.4 {
SELECT * FROM t1 WHERE t1 MATCH '6021';
} {}
do_execsql_test 6.1.5 {
SELECT * FROM t1 WHERE t1 MATCH '60*';
} {}
do_execsql_test 6.2.1 {
DROP TABLE t1;
CREATE VIRTUAL TABLE t1 USING fts4(
poiCategory, poiCategoryId, notindexed=poiCategory
);
INSERT INTO t1(poiCategory, poiCategoryId) values ("Restaurant", 6021);
}
do_execsql_test 6.2.2 {
SELECT * FROM t1 WHERE t1 MATCH 'restaurant';
} {}
do_execsql_test 6.2.3 {
SELECT * FROM t1 WHERE t1 MATCH 're*';
} {}
do_execsql_test 6.2.4 {
SELECT * FROM t1 WHERE t1 MATCH '6021';
} { Restaurant 6021 }
do_execsql_test 6.2.5 {
SELECT * FROM t1 WHERE t1 MATCH '60*';
} { Restaurant 6021 }
finish_test
+5 -19
View File
@@ -1194,18 +1194,6 @@ do_test func-24.12 {
WHEN 'program' THEN null ELSE t1 END) FROM tbl1
}
} {,is,free,software}
# Tests to verify ticket http://www.sqlite.org/src/tktview/55746f9e65f8587c0
do_test func-24.13 {
execsql {
SELECT typeof(group_concat(x)) FROM (SELECT '' AS x);
}
} {text}
do_test func-24.14 {
execsql {
SELECT typeof(group_concat(x,''))
FROM (SELECT '' AS x UNION ALL SELECT '');
}
} {text}
# Use the test_isolation function to make sure that type conversions
@@ -1313,13 +1301,11 @@ do_test func-29.3 {
db eval {SELECT typeof(+x) FROM t29 ORDER BY id}
} {integer null real blob text}
if {[permutation] != "mmap"} {
ifcapable !direct_read {
do_test func-29.4 {
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
if {$x>100} {set x many}
set x
} {many}
}
do_test func-29.4 {
set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
if {$x>100} {set x many}
set x
} {many}
}
do_test func-29.5 {
db close
+1 -1
View File
@@ -285,7 +285,7 @@ do_test fuzz-1.18 {
)
))
}
} {0 {{}}}
} {0 -4294967298}
# At one point the following INSERT statement caused an assert() to fail.
#
+2 -22
View File
@@ -145,11 +145,11 @@ do_test index6-2.1 {
execsql {
CREATE TABLE t2(a,b);
INSERT INTO t2(a,b) SELECT value, value FROM nums WHERE value<1000;
UPDATE t2 SET a=NULL WHERE b%2==0;
UPDATE t2 SET a=NULL WHERE b%5==0;
CREATE INDEX t2a1 ON t2(a) WHERE a IS NOT NULL;
SELECT count(*) FROM t2 WHERE a IS NOT NULL;
}
} {500}
} {800}
do_test index6-2.2 {
execsql {
EXPLAIN QUERY PLAN
@@ -157,7 +157,6 @@ do_test index6-2.2 {
}
} {/.* TABLE t2 USING INDEX t2a1 .*/}
ifcapable stat4||stat3 {
execsql ANALYZE
do_test index6-2.3stat4 {
execsql {
EXPLAIN QUERY PLAN
@@ -249,23 +248,4 @@ do_execsql_test index6-5.0 {
SELECT stat+0 FROM sqlite_stat1 WHERE idx='t3b';
} {6 6}
# Test case for ticket [2ea3e9fe6379fc3f6ce7e090ce483c1a3a80d6c9] from
# 2014-04-13: Partial index causes assertion fault on UPDATE OR REPLACE.
#
do_execsql_test index6-6.0 {
CREATE TABLE t6(a,b);
CREATE UNIQUE INDEX t6ab ON t1(a,b);
CREATE INDEX t6b ON t6(b) WHERE b=1;
INSERT INTO t6(a,b) VALUES(123,456);
SELECT * FROM t6;
} {123 456}
do_execsql_test index6-6.1 {
UPDATE OR REPLACE t6 SET b=789;
SELECT * FROM t6;
} {123 789}
do_execsql_test index6-6.2 {
PRAGMA integrity_check;
} {ok}
finish_test
-23
View File
@@ -413,29 +413,6 @@ do_execsql_test insert-11.1 {
} {123456789 '123456789' '123456789'}
# More columns of input than there are columns in the table.
# Ticket http://www.sqlite.org/src/info/e9654505cfda9361
#
do_execsql_test insert-12.1 {
CREATE TABLE t12a(a,b,c,d,e,f,g);
INSERT INTO t12a VALUES(101,102,103,104,105,106,107);
CREATE TABLE t12b(x);
INSERT INTO t12b(x,rowid,x,x,x,x,x) SELECT * FROM t12a;
SELECT rowid, x FROM t12b;
} {102 101}
do_execsql_test insert-12.2 {
CREATE TABLE tab1( value INTEGER);
INSERT INTO tab1 (value, _rowid_) values( 11, 1);
INSERT INTO tab1 (value, _rowid_) SELECT 22,999;
SELECT * FROM tab1;
} {11 22}
do_execsql_test insert-12.3 {
CREATE TABLE t12c(a, b DEFAULT 'xyzzy', c);
INSERT INTO t12c(a, rowid, c) SELECT 'one', 999, 'two';
SELECT * FROM t12c;
} {one xyzzy two}
integrity_check insert-99.0
finish_test
-16
View File
@@ -604,21 +604,5 @@ do_execsql_test misc1-19.2 {
SELECT * FROM t19b;
} {4 5 6}
# 2014-05-16: Tests for the SQLITE_TESTCTRL_FAULT_INSTALL feature.
#
unset -nocomplain fault_callbacks
set fault_callbacks {}
proc fault_callback {n} {
lappend ::fault_callbacks $n
return 0
}
do_test misc1-19.1 {
sqlite3_test_control_fault_install fault_callback
set fault_callbacks
} {0}
do_test misc1-19.2 {
sqlite3_test_control_fault_install
set fault_callbacks
} {0}
finish_test
-185
View File
@@ -1,185 +0,0 @@
# 2014-05-07
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file implements regression tests for SQLite library. The
# focus of this file is testing the nolock=1 and immutable=1 query
# parameters and the SQLITE_IOCAP_IMMUTABLE device characteristic.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
unset -nocomplain tvfs_calls
proc tvfs_reset {} {
global tvfs_calls
array set tvfs_calls {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
}
proc tvfs_callback {op args} {
global tvfs_calls
incr tvfs_calls($op)
return SQLITE_OK
}
tvfs_reset
testvfs tvfs
tvfs script tvfs_callback
tvfs filter {xLock xUnlock xCheckReservedLock xAccess}
############################################################################
# Verify that the nolock=1 query parameter for URI filenames disables all
# calls to xLock and xUnlock for rollback databases.
#
do_test nolock-1.0 {
db close
forcedelete test.db
tvfs_reset
sqlite db test.db -vfs tvfs
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 7 xUnlock 5 xCheckReservedLock 0}
do_test nolock-1.1 {
db close
forcedelete test.db
tvfs_reset
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 7 xUnlock 5 xCheckReservedLock 0}
do_test nolock-1.2 {
db close
forcedelete test.db
tvfs_reset
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1
db eval {CREATE TABLE t1(a,b,c); INSERT INTO t1 VALUES(1,2,3);}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 0 xUnlock 0 xCheckReservedLock 0}
do_test nolock-1.3 {
db close
tvfs_reset
sqlite db file:test.db?nolock=0 -vfs tvfs -uri 1 -readonly 1
db eval {SELECT * FROM t1}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 2 xUnlock 2 xCheckReservedLock 0}
do_test nolock-1.4 {
db close
tvfs_reset
sqlite db file:test.db?nolock=1 -vfs tvfs -uri 1 -readonly 1
db eval {SELECT * FROM t1}
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock)
} {xLock 0 xUnlock 0 xCheckReservedLock 0}
#############################################################################
# Verify that immutable=1 disables both locking and xAccess calls to the
# journal files.
#
do_test nolock-2.0 {
db close
forcedelete test.db
# begin by creating a test database
sqlite3 db test.db
db eval {
CREATE TABLE t1(a,b);
INSERT INTO t1 VALUES('hello','world');
CREATE TABLE t2(x,y);
INSERT INTO t2 VALUES(12345,67890);
SELECT * FROM t1, t2;
}
} {hello world 12345 67890}
do_test nolock-2.1 {
tvfs_reset
sqlite3 db2 test.db -vfs tvfs
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.2 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
do_test nolock-2.11 {
db2 close
tvfs_reset
sqlite3 db2 file:test.db?immutable=0 -vfs tvfs -uri 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.12 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 2 xUnlock 2 xCheckReservedLock 0 xAccess 4}
do_test nolock-2.21 {
db2 close
tvfs_reset
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.22 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
do_test nolock-2.31 {
db2 close
tvfs_reset
sqlite3 db2 file:test.db?immutable=1 -vfs tvfs -uri 1 -readonly 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-2.32 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
############################################################################
# Verify that the SQLITE_IOCAP_IMMUTABLE flag works
#
do_test nolock-3.1 {
db2 close
tvfs devchar immutable
tvfs_reset
sqlite3 db2 test.db -vfs tvfs
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-3.2 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
do_test nolock-3.11 {
db2 close
tvfs_reset
sqlite3 db2 test.db -vfs tvfs -readonly 1
db2 eval {SELECT * FROM t1, t2}
} {hello world 12345 67890}
do_test nolock-3.12 {
list xLock $::tvfs_calls(xLock) xUnlock $::tvfs_calls(xUnlock) \
xCheckReservedLock $::tvfs_calls(xCheckReservedLock) \
xAccess $::tvfs_calls(xAccess)
} {xLock 0 xUnlock 0 xCheckReservedLock 0 xAccess 0}
db2 close
db close
tvfs delete
finish_test
+2 -2
View File
@@ -80,12 +80,12 @@ do_execsql_test 2.1a {
EXPLAIN QUERY PLAN
SELECT * FROM t2 WHERE a=0 ORDER BY a, b, c;
} {~/B-TREE/}
do_execsql_test 2.1b {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE likelihood(a=0, 0.05) ORDER BY a, b, c;
SELECT * FROM t1 WHERE a=0 ORDER BY a, b, c;
} {/B-TREE/}
do_execsql_test 2.2 {
EXPLAIN QUERY PLAN
SELECT * FROM t1 WHERE +a=0 ORDER BY a, b, c;
-106
View File
@@ -1,106 +0,0 @@
# 2014-04-25
#
# 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 ORDER BY optimizations on joins
# that involve virtual tables.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix orderby7
ifcapable !fts3 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE fts USING fts3(content TEXT);
INSERT INTO fts(rowid,content)
VALUES(1,'this is a test of the fts3 virtual'),
(2,'table used as part of a join together'),
(3,'with the DISTINCT keyword. There was'),
(4,'a bug at one time (2013-06 through 2014-04)'),
(5,'that prevented this from working correctly.'),
(11,'a row that occurs twice'),
(12,'a row that occurs twice');
CREATE TABLE t1(x TEXT PRIMARY KEY, y);
INSERT OR IGNORE INTO t1 SELECT content, rowid+100 FROM fts;
} {}
do_execsql_test 1.1 {
SELECT DISTINCT fts.rowid, t1.y
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY y;
} {11 111 12 111}
do_execsql_test 1.2 {
SELECT DISTINCT fts.rowid, t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY 1;
} {11 {a row that occurs twice} 12 {a row that occurs twice}}
do_execsql_test 1.3 {
SELECT DISTINCT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY 1;
} {{a row that occurs twice}}
do_execsql_test 1.4 {
SELECT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x
ORDER BY 1;
} {{a row that occurs twice} {a row that occurs twice}}
do_execsql_test 1.5 {
SELECT DISTINCT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x;
} {{a row that occurs twice}}
do_execsql_test 1.6 {
SELECT t1.x
FROM fts, t1
WHERE fts MATCH 'that twice'
AND content=x;
} {{a row that occurs twice} {a row that occurs twice}}
do_execsql_test 2.1 {
SELECT DISTINCT t1.x
FROM fts, t1
WHERE fts.rowid=11
AND content=x
ORDER BY fts.rowid;
} {{a row that occurs twice}}
do_execsql_test 2.2 {
SELECT DISTINCT t1.*
FROM fts, t1
WHERE fts.rowid=11
AND content=x
ORDER BY fts.rowid;
} {{a row that occurs twice} 111}
do_execsql_test 2.3 {
SELECT DISTINCT t1.*
FROM fts, t1
WHERE fts.rowid=11
AND content=x
ORDER BY t1.y
} {{a row that occurs twice} 111}
finish_test
-2
View File
@@ -112,7 +112,6 @@ set allquicktests [test_set $alltests -exclude {
incrvacuum_ioerr.test autovacuum_crash.test btree8.test shared_err.test
vtab_err.test walslow.test walcrash.test walcrash3.test
walthread.test rtree3.test indexfault.test securedel2.test
fts4growth.test fts4growth2.test
}]
if {[info exists ::env(QUICKTEST_INCLUDE)]} {
set allquicktests [concat $allquicktests $::env(QUICKTEST_INCLUDE)]
@@ -197,7 +196,6 @@ test_suite "fts3" -prefix "" -description {
fts3corrupt2.test fts3first.test fts4langid.test fts4merge.test
fts4check.test fts4unicode.test fts4noti.test
fts3varint.test
fts4growth.test fts4growth2.test
}
test_suite "nofaultsim" -prefix "" -description {
-6
View File
@@ -32,9 +32,6 @@ do_test rdonly-1.1 {
SELECT * FROM t1;
}
} {1}
do_test rdonly-1.1.1 {
sqlite3_db_readonly db main
} {0}
# Changes the write version from 1 to 3. Verify that the database
# can be read but not written.
@@ -50,9 +47,6 @@ do_test rdonly-1.3 {
SELECT * FROM t1;
}
} {1}
do_test rdonly-1.3.1 {
sqlite3_db_readonly db main
} {1}
do_test rdonly-1.4 {
catchsql {
INSERT INTO t1 VALUES(2)
-65
View File
@@ -21,7 +21,6 @@
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix selectA
ifcapable !compound {
finish_test
@@ -1311,68 +1310,4 @@ do_execsql_test selectA-3.98 {
SELECT n FROM xyz ORDER BY +n;
} {MAD MAD+ MAD++}
#-------------------------------------------------------------------------
# At one point the following code exposed a temp register reuse problem.
#
proc f {args} { return 1 }
db func f f
do_execsql_test 4.1.1 {
CREATE TABLE t4(a, b);
CREATE TABLE t5(c, d);
INSERT INTO t5 VALUES(1, 'x');
INSERT INTO t5 VALUES(2, 'x');
INSERT INTO t4 VALUES(3, 'x');
INSERT INTO t4 VALUES(4, 'x');
CREATE INDEX i1 ON t4(a);
CREATE INDEX i2 ON t5(c);
}
do_eqp_test 4.1.2 {
SELECT c, d FROM t5
UNION ALL
SELECT a, b FROM t4 WHERE f()==f()
ORDER BY 1,2
} {
1 0 0 {SCAN TABLE t5 USING INDEX i2}
1 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
2 0 0 {SCAN TABLE t4 USING INDEX i1}
2 0 0 {USE TEMP B-TREE FOR RIGHT PART OF ORDER BY}
0 0 0 {COMPOUND SUBQUERIES 1 AND 2 (UNION ALL)}
}
do_execsql_test 4.1.3 {
SELECT c, d FROM t5
UNION ALL
SELECT a, b FROM t4 WHERE f()==f()
ORDER BY 1,2
} {
1 x 2 x 3 x 4 x
}
do_execsql_test 4.2.1 {
CREATE TABLE t6(a, b);
CREATE TABLE t7(c, d);
INSERT INTO t7 VALUES(2, 9);
INSERT INTO t6 VALUES(3, 0);
INSERT INTO t6 VALUES(4, 1);
INSERT INTO t7 VALUES(5, 6);
INSERT INTO t6 VALUES(6, 0);
INSERT INTO t7 VALUES(7, 6);
CREATE INDEX i6 ON t6(a);
CREATE INDEX i7 ON t7(c);
}
do_execsql_test 4.2.2 {
SELECT c, f(d,c,d,c,d) FROM t7
UNION ALL
SELECT a, b FROM t6
ORDER BY 1,2
} {/2 . 3 . 4 . 5 . 6 . 7 ./}
finish_test
+2 -54
View File
@@ -302,60 +302,8 @@ do_test shell5-1.11 {
sqlite3 db test.db
db eval {SELECT *, '|' FROM t1}
} {a b { } | x y {} | p q r |}
db close
#----------------------------------------------------------------------------
#
reset_db
sqlite3 db test.db
do_test shell5-2.1 {
set fd [open shell5.csv w]
puts $fd ",hello"
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t1(a, b);
.import shell5.csv t1
}]
db eval { SELECT * FROM t1 }
} {{} hello}
do_test shell5-2.2 {
set fd [open shell5.csv w]
puts $fd {"",hello}
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t2(a, b);
.import shell5.csv t2
}]
db eval { SELECT * FROM t2 }
} {{} hello}
do_test shell5-2.3 {
set fd [open shell5.csv w]
puts $fd {"x""y",hello}
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t3(a, b);
.import shell5.csv t3
}]
db eval { SELECT * FROM t3 }
} {x\"y hello}
do_test shell5-2.4 {
set fd [open shell5.csv w]
puts $fd {"xy""",hello}
close $fd
catchcmd test.db [string trim {
.mode csv
CREATE TABLE t4(a, b);
.import shell5.csv t4
}]
db eval { SELECT * FROM t4 }
} {xy\" hello}
finish_test
-57
View File
@@ -1,57 +0,0 @@
#!/usr/bin/tclsh
#
# This script displays the field of rectangles used by --testset rtree
# of speedtest1. Run this script as follows:
#
# rm test.db
# ./speedtest1 --testset rtree --size 25 test.db
# sqlite3 --separator ' ' test.db 'SELECT * FROM rt1' >data.txt
# wish show_speedtest1_rtree.tcl
#
# The filename "data.txt" is hard coded into this script and so that name
# must be used on lines 3 and 4 above. Elsewhere, different filenames can
# be used. The --size N parameter can be adjusted as desired.
#
package require Tk
set f [open data.txt rb]
set data [read $f]
close $f
canvas .c
frame .b
button .b.b1 -text X-Y -command refill-xy
button .b.b2 -text X-Z -command refill-xz
button .b.b3 -text Y-Z -command refill-yz
pack .b.b1 .b.b2 .b.b3 -side left
pack .c -side top -fill both -expand 1
pack .b -side top
proc resize_canvas_to_fit {} {
foreach {x0 y0 x1 y1} [.c bbox all] break
set w [expr {$x1-$x0}]
set h [expr {$y1-$y0}]
.c config -width $w -height $h
}
proc refill-xy {} {
.c delete all
foreach {id x0 x1 y0 y1 z0 z1} $::data {
.c create rectangle $x0 $y0 $x1 $y1
}
.c scale all 0 0 0.05 0.05
resize_canvas_to_fit
}
proc refill-xz {} {
.c delete all
foreach {id x0 x1 y0 y1 z0 z1} $::data {
.c create rectangle $x0 $z0 $x1 $z1
}
.c scale all 0 0 0.05 0.05
resize_canvas_to_fit
}
proc refill-yz {} {
.c delete all
foreach {id x0 x1 y0 y1 z0 z1} $::data {
.c create rectangle $y0 $z0 $y1 $z1
}
.c scale all 0 0 0.05 0.05
resize_canvas_to_fit
}
refill-xy
+1 -1
View File
@@ -181,7 +181,7 @@ do_execsql_test skipscan1-3.2 {
do_execsql_test skipscan1-3.2eqp {
EXPLAIN QUERY PLAN
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
} {/* PRIMARY KEY (ANY(a) AND b=?)*/}
} {/* INDEX sqlite_autoindex_t3_1 (ANY(a) AND b=?)*/}
do_execsql_test skipscan1-3.2sort {
EXPLAIN QUERY PLAN
SELECT a,b,c,d,'|' FROM t3 WHERE b=345 ORDER BY a;
-15
View File
@@ -74,7 +74,6 @@ do_execsql_test skipscan2-1.4 {
-- of a skip-scan. So make a manual adjustment to the stat1 table
-- to make it seem like there are many more.
UPDATE sqlite_stat1 SET stat='10000 5000 20' WHERE idx='people_idx1';
UPDATE sqlite_stat1 SET stat='10000 1' WHERE idx='sqlite_autoindex_people_1';
ANALYZE sqlite_master;
}
db cache flush
@@ -186,20 +185,6 @@ do_execsql_test skipscan2-2.5eqp {
SELECT name FROM peoplew WHERE height>=180 ORDER BY +name;
} {/*INDEX peoplew_idx1 */}
# A skip-scan on a PK index of a WITHOUT ROWID table.
#
do_execsql_test skipscan2-3.1 {
CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)) WITHOUT ROWID;
}
do_test skipscan2-3.2 {
for {set i 0} {$i < 1000} {incr i} {
execsql { INSERT INTO t3 VALUES($i%2, $i, 'xyz') }
}
execsql { ANALYZE }
} {}
do_eqp_test skipscan2-3.3eqp {
SELECT * FROM t3 WHERE b=42;
} {0 0 0 {SEARCH TABLE t3 USING PRIMARY KEY (ANY(a) AND b=?)}}
finish_test
+22
View File
@@ -464,4 +464,26 @@ do_test sort-12.1 {
}
} {1 2 xxx 1 3 yyy 1 1 zzz}
#-------------------------------------------------------------------------
# Check that the sorter in vdbesort.c sorts in a stable fashion.
#
do_execsql_test sort-13.0 {
CREATE TABLE t10(a, b);
}
do_test sort-13.1 {
db transaction {
for {set i 0} {$i < 100000} {incr i} {
execsql { INSERT INTO t10 VALUES( $i/10, $i%10 ) }
}
}
} {}
do_execsql_test sort-13.2 {
SELECT a, b FROM t10 ORDER BY a;
} [db eval {SELECT a, b FROM t10 ORDER BY a, b}]
do_execsql_test sort-13.3 {
PRAGMA cache_size = 5;
SELECT a, b FROM t10 ORDER BY a;
} [db eval {SELECT a, b FROM t10 ORDER BY a, b}]
finish_test
+1 -185
View File
@@ -29,7 +29,6 @@ static const char zHelp[] =
" --trace Turn on SQL tracing\n"
" --utf16be Set text encoding to UTF-16BE\n"
" --utf16le Set text encoding to UTF-16LE\n"
" --verify Run additional verification steps.\n"
" --without-rowid Use WITHOUT ROWID where appropriate\n"
;
@@ -52,7 +51,6 @@ static struct Global {
int bReprepare; /* True to reprepare the SQL on each rerun */
int bSqlOnly; /* True to print the SQL once only */
int bExplain; /* Print SQL with EXPLAIN prefix */
int bVerify; /* Try to verify that results are correct */
int szTest; /* Scale factor for test iterations */
const char *zWR; /* Might be WITHOUT ROWID */
const char *zNN; /* Might be NOT NULL */
@@ -933,183 +931,6 @@ void testset_cte(void){
}
/* Generate two numbers between 1 and mx. The first number is less than
** the second. Usually the numbers are near each other but can sometimes
** be far apart.
*/
static void twoCoords(
int p1, int p2, /* Parameters adjusting sizes */
unsigned mx, /* Range of 1..mx */
unsigned *pX0, unsigned *pX1 /* OUT: write results here */
){
unsigned d, x0, x1, span;
span = mx/100 + 1;
if( speedtest1_random()%3==0 ) span *= p1;
if( speedtest1_random()%p2==0 ) span = mx/2;
d = speedtest1_random()%span + 1;
x0 = speedtest1_random()%(mx-d) + 1;
x1 = x0 + d;
*pX0 = x0;
*pX1 = x1;
}
/* The following routine is an R-Tree geometry callback. It returns
** true if the object overlaps a slice on the Y coordinate between the
** two values given as arguments. In other words
**
** SELECT count(*) FROM rt1 WHERE id MATCH xslice(10,20);
**
** Is the same as saying:
**
** SELECT count(*) FROM rt1 WHERE y1>=10 AND y0<=20;
*/
static int xsliceGeometryCallback(
sqlite3_rtree_geometry *p,
int nCoord,
double *aCoord,
int *pRes
){
*pRes = aCoord[3]>=p->aParam[0] && aCoord[2]<=p->aParam[1];
return SQLITE_OK;
}
/*
** A testset for the R-Tree virtual table
*/
void testset_rtree(int p1, int p2){
unsigned i, n;
unsigned mxCoord;
unsigned x0, x1, y0, y1, z0, z1;
unsigned iStep;
int *aCheck = sqlite3_malloc( sizeof(int)*g.szTest*100 );
mxCoord = 15000;
n = g.szTest*100;
speedtest1_begin_test(100, "%d INSERTs into an r-tree", n);
speedtest1_exec("BEGIN");
speedtest1_exec("CREATE VIRTUAL TABLE rt1 USING rtree(id,x0,x1,y0,y1,z0,z1)");
speedtest1_prepare("INSERT INTO rt1(id,x0,x1,y0,y1,z0,z1)"
"VALUES(?1,?2,?3,?4,?5,?6,?7)");
for(i=1; i<=n; i++){
twoCoords(p1, p2, mxCoord, &x0, &x1);
twoCoords(p1, p2, mxCoord, &y0, &y1);
twoCoords(p1, p2, mxCoord, &z0, &z1);
sqlite3_bind_int(g.pStmt, 1, i);
sqlite3_bind_int(g.pStmt, 2, x0);
sqlite3_bind_int(g.pStmt, 3, x1);
sqlite3_bind_int(g.pStmt, 4, y0);
sqlite3_bind_int(g.pStmt, 5, y1);
sqlite3_bind_int(g.pStmt, 6, z0);
sqlite3_bind_int(g.pStmt, 7, z1);
speedtest1_run();
}
speedtest1_exec("COMMIT");
speedtest1_end_test();
speedtest1_begin_test(101, "Copy from rtree to a regular table");
speedtest1_exec("CREATE TABLE t1(id INTEGER PRIMARY KEY,x0,x1,y0,y1,z0,z1)");
speedtest1_exec("INSERT INTO t1 SELECT * FROM rt1");
speedtest1_end_test();
n = g.szTest*20;
speedtest1_begin_test(110, "%d one-dimensional intersect slice queries", n);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x0>=?1 AND x1<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
speedtest1_run();
aCheck[i] = atoi(g.zResult);
}
speedtest1_end_test();
if( g.bVerify ){
n = g.szTest*20;
speedtest1_begin_test(111, "Verify result from 1-D intersect slice queries");
speedtest1_prepare("SELECT count(*) FROM t1 WHERE x0>=?1 AND x1<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
speedtest1_run();
if( aCheck[i]!=atoi(g.zResult) ){
fatal_error("Count disagree step %d: %d..%d. %d vs %d",
i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult));
}
}
speedtest1_end_test();
}
n = g.szTest*20;
speedtest1_begin_test(120, "%d one-dimensional overlap slice queries", n);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE y1>=?1 AND y0<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
speedtest1_run();
aCheck[i] = atoi(g.zResult);
}
speedtest1_end_test();
if( g.bVerify ){
n = g.szTest*20;
speedtest1_begin_test(121, "Verify result from 1-D overlap slice queries");
speedtest1_prepare("SELECT count(*) FROM t1 WHERE y1>=?1 AND y0<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
speedtest1_run();
if( aCheck[i]!=atoi(g.zResult) ){
fatal_error("Count disagree step %d: %d..%d. %d vs %d",
i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult));
}
}
speedtest1_end_test();
}
n = g.szTest*20;
speedtest1_begin_test(125, "%d custom geometry callback queries", n);
sqlite3_rtree_geometry_callback(g.db, "xslice", xsliceGeometryCallback, 0);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE id MATCH xslice(?1,?2)");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
speedtest1_run();
if( aCheck[i]!=atoi(g.zResult) ){
fatal_error("Count disagree step %d: %d..%d. %d vs %d",
i, i*iStep, (i+1)*iStep, aCheck[i], atoi(g.zResult));
}
}
speedtest1_end_test();
n = g.szTest*80;
speedtest1_begin_test(130, "%d three-dimensional intersect box queries", n);
speedtest1_prepare("SELECT count(*) FROM rt1 WHERE x1>=?1 AND x0<=?2"
" AND y1>=?1 AND y0<=?2 AND z1>=?1 AND z0<=?2");
iStep = mxCoord/n;
for(i=0; i<n; i++){
sqlite3_bind_int(g.pStmt, 1, i*iStep);
sqlite3_bind_int(g.pStmt, 2, (i+1)*iStep);
speedtest1_run();
aCheck[i] = atoi(g.zResult);
}
speedtest1_end_test();
n = g.szTest*100;
speedtest1_begin_test(140, "%d rowid queries", n);
speedtest1_prepare("SELECT * FROM rt1 WHERE id=?1");
for(i=1; i<=n; i++){
sqlite3_bind_int(g.pStmt, 1, i);
speedtest1_run();
}
speedtest1_end_test();
}
/*
** A testset used for debugging speedtest1 itself.
*/
@@ -1229,8 +1050,6 @@ int main(int argc, char **argv){
zEncoding = "utf16le";
}else if( strcmp(z,"utf16be")==0 ){
zEncoding = "utf16be";
}else if( strcmp(z,"verify")==0 ){
g.bVerify = 1;
}else if( strcmp(z,"without-rowid")==0 ){
g.zWR = "WITHOUT ROWID";
g.zPK = "PRIMARY KEY";
@@ -1322,11 +1141,8 @@ int main(int argc, char **argv){
testset_debug1();
}else if( strcmp(zTSet,"cte")==0 ){
testset_cte();
}else if( strcmp(zTSet,"rtree")==0 ){
testset_rtree(6, 147);
}else{
fatal_error("unknown testset: \"%s\"\nChoices: main debug1 cte rtree\n",
zTSet);
fatal_error("unknown testset: \"%s\"\n", zTSet);
}
speedtest1_final();
+2
View File
@@ -1076,6 +1076,7 @@ proc explain_i {sql {db db}} {
foreach opcode {
Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind
NoConflict Next Prev VNext VPrev VFilter
SorterSort SorterNext
} {
set color($opcode) $B
}
@@ -1098,6 +1099,7 @@ proc explain_i {sql {db db}} {
if {$opcode=="Next" || $opcode=="Prev"
|| $opcode=="VNext" || $opcode=="VPrev"
|| $opcode=="SorterNext"
} {
for {set i $p2} {$i<$addr} {incr i} {
incr x($i) 2
-77
View File
@@ -1,77 +0,0 @@
# 2014-04-21
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
# Test that ticket [b75a9ca6b0] has been fixed.
#
# Ticket [b75a9ca6b0] concerns queries that have both a GROUP BY
# and an ORDER BY. This code verifies that SQLite is able to
# optimize out the ORDER BY in some circumstances, but retains the
# ORDER BY when necessary.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-b75a9ca6b0
do_execsql_test 1 {
CREATE TABLE t1 (x, y);
INSERT INTO t1 VALUES (1, 3);
INSERT INTO t1 VALUES (2, 2);
INSERT INTO t1 VALUES (3, 1);
}
do_execsql_test 1.1 {
CREATE INDEX i1 ON t1(x, y);
}
set idxscan {0 0 0 {SCAN TABLE t1 USING COVERING INDEX i1}}
set tblscan {0 0 0 {SCAN TABLE t1}}
set grpsort {0 0 0 {USE TEMP B-TREE FOR GROUP BY}}
set sort {0 0 0 {USE TEMP B-TREE FOR ORDER BY}}
foreach {tn q res eqp} [subst -nocommands {
1 "SELECT * FROM t1 GROUP BY x, y ORDER BY x,y"
{1 3 2 2 3 1} {$idxscan}
2 "SELECT * FROM t1 GROUP BY x, y ORDER BY x"
{1 3 2 2 3 1} {$idxscan $sort}
3 "SELECT * FROM t1 GROUP BY y, x ORDER BY y, x"
{3 1 2 2 1 3} {$idxscan $sort}
4 "SELECT * FROM t1 GROUP BY x ORDER BY x"
{1 3 2 2 3 1} {$idxscan}
5 "SELECT * FROM t1 GROUP BY y ORDER BY y"
{3 1 2 2 1 3} {$tblscan $grpsort}
6 "SELECT * FROM t1 GROUP BY y ORDER BY x"
{1 3 2 2 3 1} {$tblscan $grpsort $sort}
7 "SELECT * FROM t1 GROUP BY x, y ORDER BY x, y DESC"
{1 3 2 2 3 1} {$idxscan $sort}
8 "SELECT * FROM t1 GROUP BY x, y ORDER BY x DESC, y DESC"
{3 1 2 2 1 3} {$idxscan $sort}
9 "SELECT * FROM t1 GROUP BY x, y ORDER BY x ASC, y ASC"
{1 3 2 2 3 1} {$idxscan}
10 "SELECT * FROM t1 GROUP BY x, y ORDER BY x COLLATE nocase, y"
{1 3 2 2 3 1} {$idxscan $sort}
}] {
do_execsql_test 1.$tn.1 $q $res
do_eqp_test 1.$tn.2 $q $eqp
}
finish_test
-53
View File
@@ -1,53 +0,0 @@
# 2014 April 26
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#***********************************************************************
# Test that ticket f67b41381a has been resolved.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix tkt-f67b41381a
do_execsql_test 1.0 {
CREATE TABLE t1(a);
INSERT INTO t1 VALUES(1);
ALTER TABLE t1 ADD COLUMN b DEFAULT 2;
CREATE TABLE t2(a, b);
INSERT INTO t2 SELECT * FROM t1;
SELECT * FROM t2;
} {1 2}
db cache size 0
foreach {tn tbls xfer} {
1 { CREATE TABLE t1(a, b); CREATE TABLE t2(a, b) } 1
2 { CREATE TABLE t1(a, b DEFAULT 'x'); CREATE TABLE t2(a, b) } 0
3 { CREATE TABLE t1(a, b DEFAULT 'x'); CREATE TABLE t2(a, b DEFAULT 'x') } 1
4 { CREATE TABLE t1(a, b DEFAULT NULL); CREATE TABLE t2(a, b) } 0
5 { CREATE TABLE t1(a DEFAULT 2, b); CREATE TABLE t2(a DEFAULT 1, b) } 1
6 { CREATE TABLE t1(a DEFAULT 1, b); CREATE TABLE t2(a DEFAULT 1, b) } 1
7 { CREATE TABLE t1(a DEFAULT 1, b DEFAULT 1);
CREATE TABLE t2(a DEFAULT 3, b DEFAULT 1) } 1
8 { CREATE TABLE t1(a DEFAULT 1, b DEFAULT 1);
CREATE TABLE t2(a DEFAULT 3, b DEFAULT 3) } 0
} {
execsql { DROP TABLE t1; DROP TABLE t2 }
execsql $tbls
set res 1
db eval { EXPLAIN INSERT INTO t1 SELECT * FROM t2 } {
if {$opcode == "Column"} { set res 0 }
}
do_test 2.$tn [list set res] $xfer
}
finish_test
-1
View File
@@ -136,7 +136,6 @@ ifcapable fts3 {
"-- SELECT (SELECT max(idx) FROM 'main'.'x1_segdir' WHERE level = ?) + 1"
"-- SELECT coalesce((SELECT max(blockid) FROM 'main'.'x1_segments') + 1, 1)"
"-- REPLACE INTO 'main'.'x1_segdir' VALUES(?,?,?,?,?,?)"
"-- SELECT level, idx, end_block FROM 'main'.'x1_segdir' WHERE level BETWEEN ? AND ? ORDER BY level DESC, idx ASC"
}
do_trace_test 2.3 {

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