Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 813646c182 | |||
| 989412a1cf | |||
| c436a03d02 | |||
| 432697467f | |||
| 013ae68b25 | |||
| 83465a662f | |||
| ef74652ceb | |||
| 90b2fe6b1e | |||
| 48590fcb37 | |||
| ea5e5f0b89 | |||
| e5ec01c481 | |||
| dfe4e6bb33 | |||
| 320d4c304d | |||
| e288992e19 | |||
| 642f0146d7 | |||
| e3c6b61cee | |||
| 4e59344a4c | |||
| da5c62400f | |||
| e0251d44fa | |||
| 4eda15e715 | |||
| 44728d7e01 | |||
| a71c743aae | |||
| c9b39288ae | |||
| de25a88c50 | |||
| 87c05f0c58 | |||
| cca8a4ad6f | |||
| 1dd518cfcd | |||
| cb43a937e5 | |||
| 1a7df58c1a | |||
| 445f3d564c | |||
| 216b70ff82 | |||
| 230368c30d | |||
| d8e4b13256 | |||
| 8dfef1175e | |||
| 76336d5b9d | |||
| ab3182f7c4 | |||
| cd9af608e1 | |||
| 94881d732b | |||
| 9b40d13f43 | |||
| e05950d878 | |||
| 1d96cc60d0 | |||
| 2a1df937ab | |||
| dd3bfe8648 | |||
| 2831c4d123 | |||
| 42735c7d30 | |||
| 22fa36dc04 | |||
| 5f33eaa6a4 | |||
| 5e769a50ad | |||
| ed204d1f44 | |||
| 96fdcb40af | |||
| 2e34326555 | |||
| 4c5ebee0b5 | |||
| 0cd874bd57 | |||
| 410c301fea | |||
| 87f0e9863d | |||
| 209bc522b0 | |||
| e1c03b6233 | |||
| 8dd099bbaa | |||
| 28f17017ee | |||
| 511f9e8d29 | |||
| 5a0da94302 | |||
| 98ef26b0d4 | |||
| 49377a8fb7 | |||
| 30f8c23657 | |||
| fb04a36c20 | |||
| b6ea12cc05 | |||
| b390681622 | |||
| 48a72ebfa3 | |||
| 09952c6490 | |||
| d8992cef36 | |||
| e0736da15a | |||
| ff535a2499 | |||
| 8aaf7bcc8d | |||
| fadd2b1972 | |||
| 9a2e5169a4 | |||
| c332cc30d9 | |||
| d43075bcaf | |||
| 9e5eb9c8cc | |||
| 598f7c59e1 | |||
| 85f071b850 | |||
| fd7459e0aa | |||
| 8145fc6eda | |||
| 7152cc0641 | |||
| d145915a59 | |||
| 0882da8001 | |||
| edc3537c61 | |||
| 72d5003ed8 | |||
| 4313f045c2 | |||
| a0daa751f8 | |||
| 760c8162ff | |||
| cd0509e256 | |||
| 2db8211526 | |||
| 98365be030 | |||
| 21e19b44f0 | |||
| 95489c58f7 | |||
| 72ceae01e5 | |||
| 5f6eb1a0dc | |||
| 481fd50cb4 | |||
| 12c56aa452 | |||
| ff02e200c0 | |||
| d562ec277c | |||
| 2eb22af03d | |||
| 9871664ed6 | |||
| 35cd8b1eb5 | |||
| 27fe1c3fcc | |||
| 000f95b1ba | |||
| 64caee4086 | |||
| b80dbdc2f7 | |||
| fe3765828a | |||
| 2c33183d11 | |||
| eedeb92caa | |||
| 0e4125a311 | |||
| 1fbd008cf4 | |||
| f78dcd1b96 | |||
| d609bdb9d3 | |||
| cc0164b5df | |||
| c55c8dbf7f | |||
| 4ef916e233 | |||
| 2a1d1e452e |
@@ -382,6 +382,7 @@ TESTSRC = \
|
||||
$(TOP)/src/test_blob.c \
|
||||
$(TOP)/src/test_btree.c \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_delete.c \
|
||||
$(TOP)/src/test_demovfs.c \
|
||||
$(TOP)/src/test_devsym.c \
|
||||
$(TOP)/src/test_fs.c \
|
||||
|
||||
+123
-15
@@ -31,6 +31,13 @@ USE_FULLWARN = 0
|
||||
USE_RUNTIME_CHECKS = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to create a SQLite amalgamation file that excludes the
|
||||
# various built-in extensions.
|
||||
#
|
||||
!IFNDEF MINIMAL_AMALGAMATION
|
||||
MINIMAL_AMALGAMATION = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to use "stdcall" calling convention for the core library
|
||||
# and shell executable.
|
||||
#
|
||||
@@ -270,12 +277,39 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# <<mark>>
|
||||
# These are the names of the customized Tcl header files used by various parts
|
||||
# of this makefile when the stdcall calling convention is in use. It is not
|
||||
# used for any other purpose.
|
||||
#
|
||||
!IFNDEF SQLITETCLH
|
||||
SQLITETCLH = sqlite_tcl.h
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF SQLITETCLDECLSH
|
||||
SQLITETCLDECLSH = sqlite_tclDecls.h
|
||||
!ENDIF
|
||||
|
||||
# These are the additional targets that the targets that integrate with the
|
||||
# Tcl library should depend on when compiling, etc.
|
||||
#
|
||||
!IFNDEF SQLITE_TCL_DEP
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
SQLITE_TCL_DEP = $(SQLITETCLDECLSH) $(SQLITETCLH)
|
||||
!ELSE
|
||||
SQLITE_TCL_DEP =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
# <</mark>>
|
||||
|
||||
# These are the "standard" SQLite compilation options used when compiling for
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
@@ -471,20 +505,32 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) -I$(TOP)\src $(RCOPTS) $(RCCOPTS)
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
# <</mark>>
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall -DINCLUDE_SQLITE_TCL_H=1 -DSQLITE_TCLAPI=__cdecl
|
||||
# <</mark>>
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS =
|
||||
# <</mark>>
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
# <<mark>>
|
||||
TEST_CCONV_OPTS =
|
||||
# <</mark>>
|
||||
!ENDIF
|
||||
|
||||
# These are additional compiler options used for the core library.
|
||||
@@ -637,12 +683,35 @@ RCC = $(RCC) -I$(TOP)\ext\session
|
||||
# options are necessary in order to allow debugging symbols to
|
||||
# work correctly with Visual Studio when using the amalgamation.
|
||||
#
|
||||
!IFNDEF MKSQLITE3C_TOOL
|
||||
!IF $(MINIMAL_AMALGAMATION)!=0
|
||||
MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c-noext.tcl
|
||||
!ELSE
|
||||
MKSQLITE3C_TOOL = $(TOP)\tool\mksqlite3c.tcl
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
!IFNDEF MKSQLITE3C_ARGS
|
||||
!IF $(DEBUG)>1
|
||||
MKSQLITE3C_ARGS = --linemacros
|
||||
!ELSE
|
||||
MKSQLITE3C_ARGS =
|
||||
!ENDIF
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
MKSQLITE3C_ARGS = $(MKSQLITE3C_ARGS) --useapicall
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
# The mksqlite3h.tcl script accepts some options on the command line.
|
||||
# When compiling with stdcall support, some of these options are
|
||||
# necessary.
|
||||
#
|
||||
!IFNDEF MKSQLITE3H_ARGS
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
MKSQLITE3H_ARGS = --useapicall
|
||||
!ELSE
|
||||
MKSQLITE3H_ARGS =
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
# <</mark>>
|
||||
|
||||
@@ -1246,6 +1315,16 @@ SRC11 = \
|
||||
parse.h \
|
||||
$(SQLITE3H)
|
||||
|
||||
# Generated Tcl header files
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
SRC12 = \
|
||||
$(SQLITETCLH) \
|
||||
$(SQLITETCLDECLSH)
|
||||
!ELSE
|
||||
SRC12 =
|
||||
!ENDIF
|
||||
|
||||
# All source code files.
|
||||
#
|
||||
SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
|
||||
@@ -1269,6 +1348,7 @@ TESTSRC = \
|
||||
$(TOP)\src\test_blob.c \
|
||||
$(TOP)\src\test_btree.c \
|
||||
$(TOP)\src\test_config.c \
|
||||
$(TOP)\src\test_delete.c \
|
||||
$(TOP)\src\test_demovfs.c \
|
||||
$(TOP)\src\test_devsym.c \
|
||||
$(TOP)\src\test_fs.c \
|
||||
@@ -1352,7 +1432,7 @@ HDR = \
|
||||
parse.h \
|
||||
$(TOP)\src\pragma.h \
|
||||
$(SQLITE3H) \
|
||||
$(TOP)\src\sqlite3ext.h \
|
||||
sqlite3ext.h \
|
||||
$(TOP)\src\sqliteInt.h \
|
||||
$(TOP)\src\sqliteLimit.h \
|
||||
$(TOP)\src\vdbe.h \
|
||||
@@ -1510,7 +1590,7 @@ mptest: mptester.exe
|
||||
# files are automatically generated. This target takes care of
|
||||
# all that automatic generation.
|
||||
#
|
||||
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c
|
||||
.target_source: $(SRC) $(TOP)\tool\vdbe-compress.tcl fts5.c $(SQLITE_TCL_DEP)
|
||||
-rmdir /Q/S tsrc 2>NUL
|
||||
-mkdir tsrc
|
||||
for %i in ($(SRC00)) do copy /Y %i tsrc
|
||||
@@ -1525,6 +1605,7 @@ mptest: mptester.exe
|
||||
for %i in ($(SRC09)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC10)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC11)) do copy /Y %i tsrc
|
||||
for %i in ($(SRC12)) do copy /Y %i tsrc
|
||||
copy /Y fts5.c tsrc
|
||||
copy /Y fts5.h tsrc
|
||||
del /Q tsrc\sqlite.h.in tsrc\parse.y 2>NUL
|
||||
@@ -1532,8 +1613,8 @@ mptest: mptester.exe
|
||||
move vdbe.new tsrc\vdbe.c
|
||||
echo > .target_source
|
||||
|
||||
sqlite3.c: .target_source sqlite3ext.h $(TOP)\tool\mksqlite3c.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl $(MKSQLITE3C_ARGS)
|
||||
sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
|
||||
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
|
||||
copy tsrc\shell.c .
|
||||
copy $(TOP)\ext\session\sqlite3session.h .
|
||||
|
||||
@@ -1806,10 +1887,10 @@ wherecode.lo: $(TOP)\src\wherecode.c $(HDR)
|
||||
whereexpr.lo: $(TOP)\src\whereexpr.c $(HDR)
|
||||
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\whereexpr.c
|
||||
|
||||
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
||||
tclsqlite.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
|
||||
$(LTCOMPILE) $(NO_WARN) -DUSE_TCL_STUBS=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
|
||||
|
||||
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR)
|
||||
tclsqlite-shell.lo: $(TOP)\src\tclsqlite.c $(HDR) $(SQLITE_TCL_DEP)
|
||||
$(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
|
||||
|
||||
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
|
||||
@@ -1835,10 +1916,16 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
|
||||
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
|
||||
|
||||
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H)
|
||||
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
|
||||
|
||||
sqlite3ext.h: .target_source
|
||||
copy tsrc\sqlite3ext.h .
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
type tsrc\sqlite3ext.h | $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*\)" "(SQLITE_CALLBACK *)" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_APICALL *" > sqlite3ext.h
|
||||
copy /Y sqlite3ext.h tsrc\sqlite3ext.h
|
||||
!ELSE
|
||||
copy /Y tsrc\sqlite3ext.h sqlite3ext.h
|
||||
!ENDIF
|
||||
|
||||
mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
|
||||
$(BCC) $(NO_WARN) -Fe$@ $(REQ_FEATURE_FLAGS) $(OPT_FEATURE_FLAGS) $(EXT_FEATURE_FLAGS) $(OPTS) \
|
||||
@@ -1971,6 +2058,7 @@ TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERVER=1 -DSQLITE_PRIVATE=""
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_CORE $(NO_WARN)
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_DEFAULT_PAGE_SIZE=1024
|
||||
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
|
||||
|
||||
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
|
||||
TESTFIXTURE_SRC1 = $(TESTEXT) $(SQLITE3C)
|
||||
@@ -1980,7 +2068,27 @@ TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC0)
|
||||
TESTFIXTURE_SRC = $(TESTSRC) $(TOP)\src\tclsqlite.c $(TESTFIXTURE_SRC1)
|
||||
!ENDIF
|
||||
|
||||
testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR)
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
sqlite_tclDecls.h:
|
||||
echo #ifndef SQLITE_TCLAPI > $(SQLITETCLDECLSH)
|
||||
echo # define SQLITE_TCLAPI >> $(SQLITETCLDECLSH)
|
||||
echo #endif >> $(SQLITETCLDECLSH)
|
||||
type "$(TCLINCDIR)\tclDecls.h" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN(?: CONST\d+?)?\s+?[^\(]*?\s+?)Tcl_" "\1 SQLITE_TCLAPI Tcl_" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "^(EXTERN\s+?(?:void|VOID)\s+?)TclFreeObj" "\1 SQLITE_TCLAPI TclFreeObj" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tcl_" "(SQLITE_TCLAPI *tcl_" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*tclFreeObj" "(SQLITE_TCLAPI *tclFreeObj" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "\(\*" "(SQLITE_TCLAPI *" >> $(SQLITETCLDECLSH)
|
||||
|
||||
sqlite_tcl.h:
|
||||
type "$(TCLINCDIR)\tcl.h" | $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact tclDecls.h sqlite_tclDecls.h \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl regsub "typedef (.*?)\(Tcl_" "typedef \1 (SQLITE_TCLAPI Tcl_" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "void (*freeProc)" "void (SQLITE_TCLAPI *freeProc)" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*findProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *findProc)" \
|
||||
| $(TCLSH_CMD) $(TOP)\tool\replace.tcl exact "Tcl_HashEntry *(*createProc)" "Tcl_HashEntry *(SQLITE_TCLAPI *createProc)" >> $(SQLITETCLH)
|
||||
!ENDIF
|
||||
|
||||
testfixture.exe: $(TESTFIXTURE_SRC) $(SQLITE3H) $(LIBRESOBJS) $(HDR) $(SQLITE_TCL_DEP)
|
||||
$(LTLINK) -DSQLITE_NO_SYNC=1 $(TESTFIXTURE_FLAGS) \
|
||||
-DBUILD_sqlite -I$(TCLINCDIR) \
|
||||
$(TESTFIXTURE_SRC) \
|
||||
@@ -2029,7 +2137,7 @@ smoketest: $(TESTPROGS)
|
||||
@set PATH=$(LIBTCLPATH);$(PATH)
|
||||
.\testfixture.exe $(TOP)\test\main.test $(TESTOPTS)
|
||||
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl
|
||||
sqlite3_analyzer.c: $(SQLITE3C) $(SQLITE3H) $(TOP)\src\tclsqlite.c $(TOP)\tool\spaceanal.tcl $(SQLITE_TCL_DEP)
|
||||
echo #define TCLSH 2 > $@
|
||||
echo #define SQLITE_ENABLE_DBSTAT_VTAB 1 >> $@
|
||||
copy $@ + $(SQLITE3C) + $(TOP)\src\tclsqlite.c $@
|
||||
@@ -2109,7 +2217,7 @@ clean:
|
||||
-rmdir /Q/S .libs 2>NUL
|
||||
-rmdir /Q/S tsrc 2>NUL
|
||||
del /Q .target_source 2>NUL
|
||||
del /Q tclsqlite3.exe 2>NUL
|
||||
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
|
||||
del /Q testloadext.dll 2>NUL
|
||||
del /Q testfixture.exe test.db 2>NUL
|
||||
del /Q LogEst.exe fts3view.exe rollback-test.exe showdb.exe 2>NUL
|
||||
|
||||
+14
-4
@@ -31,6 +31,13 @@ USE_FULLWARN = 0
|
||||
USE_RUNTIME_CHECKS = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to create a SQLite amalgamation file that excludes the
|
||||
# various built-in extensions.
|
||||
#
|
||||
!IFNDEF MINIMAL_AMALGAMATION
|
||||
MINIMAL_AMALGAMATION = 0
|
||||
!ENDIF
|
||||
|
||||
# Set this non-0 to use "stdcall" calling convention for the core library
|
||||
# and shell executable.
|
||||
#
|
||||
@@ -255,12 +262,15 @@ SQLITE3EXEPDB = /pdb:sqlite3sh.pdb
|
||||
!ENDIF
|
||||
!ENDIF
|
||||
|
||||
|
||||
# These are the "standard" SQLite compilation options used when compiling for
|
||||
# the Windows platform.
|
||||
#
|
||||
!IFNDEF OPT_FEATURE_FLAGS
|
||||
!IF $(MINIMAL_AMALGAMATION)==0
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_FTS3=1
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_RTREE=1
|
||||
!ENDIF
|
||||
OPT_FEATURE_FLAGS = $(OPT_FEATURE_FLAGS) -DSQLITE_ENABLE_COLUMN_METADATA=1
|
||||
!ENDIF
|
||||
|
||||
@@ -456,12 +466,12 @@ RCC = $(RC) -DSQLITE_OS_WIN=1 -I. -I$(TOP) $(RCOPTS) $(RCCOPTS)
|
||||
#
|
||||
!IF $(USE_STDCALL)!=0 || $(FOR_WIN10)!=0
|
||||
!IF "$(PLATFORM)"=="x86"
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
!ELSE
|
||||
!IFNDEF PLATFORM
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_STDCALL=__stdcall
|
||||
CORE_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
SHELL_CCONV_OPTS = -Gz -DSQLITE_CDECL=__cdecl -DSQLITE_APICALL=__stdcall -DSQLITE_CALLBACK=__stdcall -DSQLITE_SYSAPI=__stdcall
|
||||
!ELSE
|
||||
CORE_CCONV_OPTS =
|
||||
SHELL_CCONV_OPTS =
|
||||
|
||||
+2
-2
@@ -85,7 +85,7 @@ Define C preprocessor macro <i>name</i>. This macro is useable by
|
||||
Do not generate a parser. Instead write the input grammar to standard
|
||||
output with all comments, actions, and other extraneous text removed.
|
||||
<li><b>-l</b>
|
||||
Omit "#line" directives int the generated parser C code.
|
||||
Omit "#line" directives in the generated parser C code.
|
||||
<li><b>-m</b>
|
||||
Cause the output C source code to be compatible with the "makeheaders"
|
||||
program.
|
||||
@@ -929,7 +929,7 @@ token structure. Like this:</p>
|
||||
</pre></p>
|
||||
|
||||
<p>If the data type of terminals is not specified, the default value
|
||||
is "int".</p>
|
||||
is "void*".</p>
|
||||
|
||||
<p>Non-terminal symbols can each have their own data types. Typically
|
||||
the data type of a non-terminal is a pointer to the root of a parse-tree
|
||||
|
||||
+3
-1
@@ -292,6 +292,9 @@ static int fts5SentenceFinderCb(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
UNUSED_PARAM2(pToken, nToken);
|
||||
UNUSED_PARAM(iEndOff);
|
||||
|
||||
if( (tflags & FTS5_TOKEN_COLOCATED)==0 ){
|
||||
Fts5SFinder *p = (Fts5SFinder*)pContext;
|
||||
if( p->iPos>0 ){
|
||||
@@ -447,7 +450,6 @@ static void fts5SnippetFunction(
|
||||
}
|
||||
|
||||
if( sFinder.aFirst[jj]<io ){
|
||||
int nScore;
|
||||
memset(aSeen, 0, nPhrase);
|
||||
rc = fts5SnippetScore(pApi, pFts, nDocsize, aSeen, i,
|
||||
sFinder.aFirst[jj], nToken, &nScore, 0
|
||||
|
||||
+22
-17
@@ -754,6 +754,7 @@ static int fts5ExprNearInitAll(
|
||||
Fts5ExprNearset *pNear = pNode->pNear;
|
||||
int i, j;
|
||||
int rc = SQLITE_OK;
|
||||
int bEof = 1;
|
||||
|
||||
assert( pNode->bNomatch==0 );
|
||||
for(i=0; rc==SQLITE_OK && i<pNear->nPhrase; i++){
|
||||
@@ -761,7 +762,6 @@ static int fts5ExprNearInitAll(
|
||||
for(j=0; j<pPhrase->nTerm; j++){
|
||||
Fts5ExprTerm *pTerm = &pPhrase->aTerm[j];
|
||||
Fts5ExprTerm *p;
|
||||
int bEof = 1;
|
||||
|
||||
for(p=pTerm; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
if( p->pIter ){
|
||||
@@ -781,13 +781,12 @@ static int fts5ExprNearInitAll(
|
||||
}
|
||||
}
|
||||
|
||||
if( bEof ){
|
||||
pNode->bEof = 1;
|
||||
return rc;
|
||||
}
|
||||
if( bEof ) break;
|
||||
}
|
||||
if( bEof ) break;
|
||||
}
|
||||
|
||||
pNode->bEof = bEof;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -1638,7 +1637,6 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
|
||||
int i; /* Used to iterate through phrase terms */
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
TokenCtx sCtx = {0,0}; /* Context object for fts5ParseTokenize */
|
||||
|
||||
@@ -1668,18 +1666,25 @@ int sqlite3Fts5ExprClonePhrase(
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
|
||||
int tflags = 0;
|
||||
Fts5ExprTerm *p;
|
||||
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
const char *zTerm = p->zTerm;
|
||||
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
|
||||
0, 0);
|
||||
tflags = FTS5_TOKEN_COLOCATED;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
if( pOrig->nTerm ){
|
||||
int i; /* Used to iterate through phrase terms */
|
||||
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
|
||||
int tflags = 0;
|
||||
Fts5ExprTerm *p;
|
||||
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
const char *zTerm = p->zTerm;
|
||||
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, (int)strlen(zTerm),
|
||||
0, 0);
|
||||
tflags = FTS5_TOKEN_COLOCATED;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
/* This happens when parsing a token or quoted phrase that contains
|
||||
** no token characters at all. (e.g ... MATCH '""'). */
|
||||
sCtx.pPhrase = sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprPhrase));
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
|
||||
+12
-1
@@ -279,8 +279,19 @@ static int fts5VocabBestIndexMethod(
|
||||
}
|
||||
}
|
||||
|
||||
pInfo->idxNum = idxNum;
|
||||
/* This virtual table always delivers results in ascending order of
|
||||
** the "term" column (column 0). So if the user has requested this
|
||||
** specifically - "ORDER BY term" or "ORDER BY term ASC" - set the
|
||||
** sqlite3_index_info.orderByConsumed flag to tell the core the results
|
||||
** are already in sorted order. */
|
||||
if( pInfo->nOrderBy==1
|
||||
&& pInfo->aOrderBy[0].iColumn==0
|
||||
&& pInfo->aOrderBy[0].desc==0
|
||||
){
|
||||
pInfo->orderByConsumed = 1;
|
||||
}
|
||||
|
||||
pInfo->idxNum = idxNum;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,23 @@ do_catchsql_test 2.1 {
|
||||
SELECT fts5_expr_tcl()
|
||||
} {1 {wrong number of arguments to function fts5_expr_tcl}}
|
||||
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE e1 USING fts5(text, tokenize = 'porter unicode61');
|
||||
INSERT INTO e1 VALUES ("just a few words with a / inside");
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"just"' ORDER BY rank;
|
||||
} {1 -1e-06}
|
||||
do_execsql_test 3.2 {
|
||||
SELECT rowid FROM e1 WHERE e1 MATCH '"/" OR "just"'
|
||||
} 1
|
||||
do_execsql_test 3.3 {
|
||||
SELECT rowid, bm25(e1) FROM e1 WHERE e1 MATCH '"/" OR "just"' ORDER BY rank;
|
||||
} {1 -1e-06}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
|
||||
@@ -442,8 +442,44 @@ if {[detail_is_none]} {
|
||||
}
|
||||
|
||||
sqlite3_fts5_may_be_corrupt 0
|
||||
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test that both "ORDER BY term" and "ORDER BY term DESC" work.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 9.1 {
|
||||
CREATE VIRTUAL TABLE x1 USING fts5(x);
|
||||
INSERT INTO x1 VALUES('def ABC ghi');
|
||||
INSERT INTO x1 VALUES('DEF abc GHI');
|
||||
}
|
||||
|
||||
do_execsql_test 9.2 {
|
||||
CREATE VIRTUAL TABLE rrr USING fts5vocab(x1, row);
|
||||
SELECT * FROM rrr
|
||||
} {
|
||||
abc 2 2 def 2 2 ghi 2 2
|
||||
}
|
||||
do_execsql_test 9.3 {
|
||||
SELECT * FROM rrr ORDER BY term ASC
|
||||
} {
|
||||
abc 2 2 def 2 2 ghi 2 2
|
||||
}
|
||||
do_execsql_test 9.4 {
|
||||
SELECT * FROM rrr ORDER BY term DESC
|
||||
} {
|
||||
ghi 2 2 def 2 2 abc 2 2
|
||||
}
|
||||
do_test 9.5 {
|
||||
set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term ASC }]
|
||||
expr [lsearch $e2 SorterSort]<0
|
||||
} 1
|
||||
do_test 9.6 {
|
||||
set e2 [db eval { EXPLAIN SELECT * FROM rrr ORDER BY term DESC }]
|
||||
expr [lsearch $e2 SorterSort]<0
|
||||
} 0
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
|
||||
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
** 2016-09-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 is an in-memory read-only VFS implementation. The application
|
||||
** supplies a block of memory which is the database file, and this VFS
|
||||
** uses that block of memory.
|
||||
**
|
||||
** Because there is no place to store journals and no good way to lock
|
||||
** the "file", this VFS is read-only.
|
||||
**
|
||||
** USAGE:
|
||||
**
|
||||
** sqlite3_open_v2("file:/whatever?ptr=0xf05538&sz=14336", &db,
|
||||
** SQLITE_OPEN_READONLY | SQLITE_OPEN_URI,
|
||||
** "memvfs");
|
||||
**
|
||||
** The ptr= and sz= query parameters are required or the open will fail.
|
||||
** The ptr= parameter gives the memory address of the buffer holding the
|
||||
** read-only database and sz= gives the size of the database. The parameter
|
||||
** values may be in hexadecimal or decimal. The filename is ignored.
|
||||
*/
|
||||
#include <sqlite3ext.h>
|
||||
SQLITE_EXTENSION_INIT1
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
/*
|
||||
** Forward declaration of objects used by this utility
|
||||
*/
|
||||
typedef struct sqlite3_vfs MemVfs;
|
||||
typedef struct MemFile MemFile;
|
||||
|
||||
/* Access to a lower-level VFS that (might) implement dynamic loading,
|
||||
** access to randomness, etc.
|
||||
*/
|
||||
#define ORIGVFS(p) ((sqlite3_vfs*)((p)->pAppData))
|
||||
|
||||
/* An open file */
|
||||
struct MemFile {
|
||||
sqlite3_file base; /* IO methods */
|
||||
sqlite3_int64 sz; /* Size of the file */
|
||||
unsigned char *aData; /* content of the file */
|
||||
};
|
||||
|
||||
/*
|
||||
** Methods for MemFile
|
||||
*/
|
||||
static int memClose(sqlite3_file*);
|
||||
static int memRead(sqlite3_file*, void*, int iAmt, sqlite3_int64 iOfst);
|
||||
static int memWrite(sqlite3_file*,const void*,int iAmt, sqlite3_int64 iOfst);
|
||||
static int memTruncate(sqlite3_file*, sqlite3_int64 size);
|
||||
static int memSync(sqlite3_file*, int flags);
|
||||
static int memFileSize(sqlite3_file*, sqlite3_int64 *pSize);
|
||||
static int memLock(sqlite3_file*, int);
|
||||
static int memUnlock(sqlite3_file*, int);
|
||||
static int memCheckReservedLock(sqlite3_file*, int *pResOut);
|
||||
static int memFileControl(sqlite3_file*, int op, void *pArg);
|
||||
static int memSectorSize(sqlite3_file*);
|
||||
static int memDeviceCharacteristics(sqlite3_file*);
|
||||
static int memShmMap(sqlite3_file*, int iPg, int pgsz, int, void volatile**);
|
||||
static int memShmLock(sqlite3_file*, int offset, int n, int flags);
|
||||
static void memShmBarrier(sqlite3_file*);
|
||||
static int memShmUnmap(sqlite3_file*, int deleteFlag);
|
||||
static int memFetch(sqlite3_file*, sqlite3_int64 iOfst, int iAmt, void **pp);
|
||||
static int memUnfetch(sqlite3_file*, sqlite3_int64 iOfst, void *p);
|
||||
|
||||
/*
|
||||
** Methods for MemVfs
|
||||
*/
|
||||
static int memOpen(sqlite3_vfs*, const char *, sqlite3_file*, int , int *);
|
||||
static int memDelete(sqlite3_vfs*, const char *zName, int syncDir);
|
||||
static int memAccess(sqlite3_vfs*, const char *zName, int flags, int *);
|
||||
static int memFullPathname(sqlite3_vfs*, const char *zName, int, char *zOut);
|
||||
static void *memDlOpen(sqlite3_vfs*, const char *zFilename);
|
||||
static void memDlError(sqlite3_vfs*, int nByte, char *zErrMsg);
|
||||
static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char*zSym))(void);
|
||||
static void memDlClose(sqlite3_vfs*, void*);
|
||||
static int memRandomness(sqlite3_vfs*, int nByte, char *zOut);
|
||||
static int memSleep(sqlite3_vfs*, int microseconds);
|
||||
static int memCurrentTime(sqlite3_vfs*, double*);
|
||||
static int memGetLastError(sqlite3_vfs*, int, char *);
|
||||
static int memCurrentTimeInt64(sqlite3_vfs*, sqlite3_int64*);
|
||||
|
||||
static sqlite3_vfs mem_vfs = {
|
||||
2, /* iVersion */
|
||||
0, /* szOsFile (set when registered) */
|
||||
1024, /* mxPathname */
|
||||
0, /* pNext */
|
||||
"memvfs", /* zName */
|
||||
0, /* pAppData (set when registered) */
|
||||
memOpen, /* xOpen */
|
||||
memDelete, /* xDelete */
|
||||
memAccess, /* xAccess */
|
||||
memFullPathname, /* xFullPathname */
|
||||
memDlOpen, /* xDlOpen */
|
||||
memDlError, /* xDlError */
|
||||
memDlSym, /* xDlSym */
|
||||
memDlClose, /* xDlClose */
|
||||
memRandomness, /* xRandomness */
|
||||
memSleep, /* xSleep */
|
||||
memCurrentTime, /* xCurrentTime */
|
||||
memGetLastError, /* xGetLastError */
|
||||
memCurrentTimeInt64 /* xCurrentTimeInt64 */
|
||||
};
|
||||
|
||||
static const sqlite3_io_methods mem_io_methods = {
|
||||
3, /* iVersion */
|
||||
memClose, /* xClose */
|
||||
memRead, /* xRead */
|
||||
memWrite, /* xWrite */
|
||||
memTruncate, /* xTruncate */
|
||||
memSync, /* xSync */
|
||||
memFileSize, /* xFileSize */
|
||||
memLock, /* xLock */
|
||||
memUnlock, /* xUnlock */
|
||||
memCheckReservedLock, /* xCheckReservedLock */
|
||||
memFileControl, /* xFileControl */
|
||||
memSectorSize, /* xSectorSize */
|
||||
memDeviceCharacteristics, /* xDeviceCharacteristics */
|
||||
memShmMap, /* xShmMap */
|
||||
memShmLock, /* xShmLock */
|
||||
memShmBarrier, /* xShmBarrier */
|
||||
memShmUnmap, /* xShmUnmap */
|
||||
memFetch, /* xFetch */
|
||||
memUnfetch /* xUnfetch */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Close an mem-file.
|
||||
**
|
||||
** The pData pointer is owned by the application, so there is nothing
|
||||
** to free.
|
||||
*/
|
||||
static int memClose(sqlite3_file *pFile){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Read data from an mem-file.
|
||||
*/
|
||||
static int memRead(
|
||||
sqlite3_file *pFile,
|
||||
void *zBuf,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
memcpy(zBuf, p->aData+iOfst, iAmt);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Write data to an mem-file.
|
||||
*/
|
||||
static int memWrite(
|
||||
sqlite3_file *pFile,
|
||||
const void *z,
|
||||
int iAmt,
|
||||
sqlite_int64 iOfst
|
||||
){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
** Truncate an mem-file.
|
||||
*/
|
||||
static int memTruncate(sqlite3_file *pFile, sqlite_int64 size){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
** Sync an mem-file.
|
||||
*/
|
||||
static int memSync(sqlite3_file *pFile, int flags){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current file-size of an mem-file.
|
||||
*/
|
||||
static int memFileSize(sqlite3_file *pFile, sqlite_int64 *pSize){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
*pSize = p->sz;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Lock an mem-file.
|
||||
*/
|
||||
static int memLock(sqlite3_file *pFile, int eLock){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
** Unlock an mem-file.
|
||||
*/
|
||||
static int memUnlock(sqlite3_file *pFile, int eLock){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Check if another file-handle holds a RESERVED lock on an mem-file.
|
||||
*/
|
||||
static int memCheckReservedLock(sqlite3_file *pFile, int *pResOut){
|
||||
*pResOut = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** File control method. For custom operations on an mem-file.
|
||||
*/
|
||||
static int memFileControl(sqlite3_file *pFile, int op, void *pArg){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
int rc = SQLITE_NOTFOUND;
|
||||
if( op==SQLITE_FCNTL_VFSNAME ){
|
||||
*(char**)pArg = sqlite3_mprintf("mem(%p,%lld)", p->aData, p->sz);
|
||||
rc = SQLITE_OK;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the sector-size in bytes for an mem-file.
|
||||
*/
|
||||
static int memSectorSize(sqlite3_file *pFile){
|
||||
return 1024;
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the device characteristic flags supported by an mem-file.
|
||||
*/
|
||||
static int memDeviceCharacteristics(sqlite3_file *pFile){
|
||||
return SQLITE_IOCAP_IMMUTABLE;
|
||||
}
|
||||
|
||||
/* Create a shared memory file mapping */
|
||||
static int memShmMap(
|
||||
sqlite3_file *pFile,
|
||||
int iPg,
|
||||
int pgsz,
|
||||
int bExtend,
|
||||
void volatile **pp
|
||||
){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/* Perform locking on a shared-memory segment */
|
||||
static int memShmLock(sqlite3_file *pFile, int offset, int n, int flags){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/* Memory barrier operation on shared memory */
|
||||
static void memShmBarrier(sqlite3_file *pFile){
|
||||
return;
|
||||
}
|
||||
|
||||
/* Unmap a shared memory segment */
|
||||
static int memShmUnmap(sqlite3_file *pFile, int deleteFlag){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Fetch a page of a memory-mapped file */
|
||||
static int memFetch(
|
||||
sqlite3_file *pFile,
|
||||
sqlite3_int64 iOfst,
|
||||
int iAmt,
|
||||
void **pp
|
||||
){
|
||||
MemFile *p = (MemFile *)pFile;
|
||||
*pp = (void*)(p->aData + iOfst);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/* Release a memory-mapped page */
|
||||
static int memUnfetch(sqlite3_file *pFile, sqlite3_int64 iOfst, void *pPage){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open an mem file handle.
|
||||
*/
|
||||
static int memOpen(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zName,
|
||||
sqlite3_file *pFile,
|
||||
int flags,
|
||||
int *pOutFlags
|
||||
){
|
||||
MemFile *p = (MemFile*)pFile;
|
||||
memset(p, 0, sizeof(*p));
|
||||
if( (flags & SQLITE_OPEN_MAIN_DB)==0 ) return SQLITE_CANTOPEN;
|
||||
p->aData = (unsigned char*)sqlite3_uri_int64(zName,"ptr",0);
|
||||
if( p->aData==0 ) return SQLITE_CANTOPEN;
|
||||
p->sz = sqlite3_uri_int64(zName,"sz",0);
|
||||
if( p->sz<0 ) return SQLITE_CANTOPEN;
|
||||
pFile->pMethods = &mem_io_methods;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete the file located at zPath. If the dirSync argument is true,
|
||||
** ensure the file-system modifications are synced to disk before
|
||||
** returning.
|
||||
*/
|
||||
static int memDelete(sqlite3_vfs *pVfs, const char *zPath, int dirSync){
|
||||
return SQLITE_READONLY;
|
||||
}
|
||||
|
||||
/*
|
||||
** Test for access permissions. Return true if the requested permission
|
||||
** is available, or false otherwise.
|
||||
*/
|
||||
static int memAccess(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int flags,
|
||||
int *pResOut
|
||||
){
|
||||
/* The spec says there are three possible values for flags. But only
|
||||
** two of them are actually used */
|
||||
assert( flags==SQLITE_ACCESS_EXISTS || flags==SQLITE_ACCESS_READWRITE );
|
||||
if( flags==SQLITE_ACCESS_READWRITE ){
|
||||
*pResOut = 0;
|
||||
}else{
|
||||
*pResOut = 1;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate buffer zOut with the full canonical pathname corresponding
|
||||
** to the pathname in zPath. zOut is guaranteed to point to a buffer
|
||||
** of at least (INST_MAX_PATHNAME+1) bytes.
|
||||
*/
|
||||
static int memFullPathname(
|
||||
sqlite3_vfs *pVfs,
|
||||
const char *zPath,
|
||||
int nOut,
|
||||
char *zOut
|
||||
){
|
||||
sqlite3_snprintf(nOut, zOut, "%s", zPath);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Open the dynamic library located at zPath and return a handle.
|
||||
*/
|
||||
static void *memDlOpen(sqlite3_vfs *pVfs, const char *zPath){
|
||||
return ORIGVFS(pVfs)->xDlOpen(ORIGVFS(pVfs), zPath);
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate the buffer zErrMsg (size nByte bytes) with a human readable
|
||||
** utf-8 string describing the most recent error encountered associated
|
||||
** with dynamic libraries.
|
||||
*/
|
||||
static void memDlError(sqlite3_vfs *pVfs, int nByte, char *zErrMsg){
|
||||
ORIGVFS(pVfs)->xDlError(ORIGVFS(pVfs), nByte, zErrMsg);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return a pointer to the symbol zSymbol in the dynamic library pHandle.
|
||||
*/
|
||||
static void (*memDlSym(sqlite3_vfs *pVfs, void *p, const char *zSym))(void){
|
||||
return ORIGVFS(pVfs)->xDlSym(ORIGVFS(pVfs), p, zSym);
|
||||
}
|
||||
|
||||
/*
|
||||
** Close the dynamic library handle pHandle.
|
||||
*/
|
||||
static void memDlClose(sqlite3_vfs *pVfs, void *pHandle){
|
||||
ORIGVFS(pVfs)->xDlClose(ORIGVFS(pVfs), pHandle);
|
||||
}
|
||||
|
||||
/*
|
||||
** Populate the buffer pointed to by zBufOut with nByte bytes of
|
||||
** random data.
|
||||
*/
|
||||
static int memRandomness(sqlite3_vfs *pVfs, int nByte, char *zBufOut){
|
||||
return ORIGVFS(pVfs)->xRandomness(ORIGVFS(pVfs), nByte, zBufOut);
|
||||
}
|
||||
|
||||
/*
|
||||
** Sleep for nMicro microseconds. Return the number of microseconds
|
||||
** actually slept.
|
||||
*/
|
||||
static int memSleep(sqlite3_vfs *pVfs, int nMicro){
|
||||
return ORIGVFS(pVfs)->xSleep(ORIGVFS(pVfs), nMicro);
|
||||
}
|
||||
|
||||
/*
|
||||
** Return the current time as a Julian Day number in *pTimeOut.
|
||||
*/
|
||||
static int memCurrentTime(sqlite3_vfs *pVfs, double *pTimeOut){
|
||||
return ORIGVFS(pVfs)->xCurrentTime(ORIGVFS(pVfs), pTimeOut);
|
||||
}
|
||||
|
||||
static int memGetLastError(sqlite3_vfs *pVfs, int a, char *b){
|
||||
return ORIGVFS(pVfs)->xGetLastError(ORIGVFS(pVfs), a, b);
|
||||
}
|
||||
static int memCurrentTimeInt64(sqlite3_vfs *pVfs, sqlite3_int64 *p){
|
||||
return ORIGVFS(pVfs)->xCurrentTimeInt64(ORIGVFS(pVfs), p);
|
||||
}
|
||||
|
||||
#ifdef MEMVFS_TEST
|
||||
/*
|
||||
** memload(FILENAME)
|
||||
**
|
||||
** This an SQL function used to help in testing the memvfs VFS. The
|
||||
** function reads the content of a file into memory and then returns
|
||||
** a string that gives the locate and size of the in-memory buffer.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
static void memvfsMemloadFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
unsigned char *p;
|
||||
sqlite3_int64 sz;
|
||||
FILE *in;
|
||||
const char *zFilename = (const char*)sqlite3_value_text(argv[0]);
|
||||
char zReturn[100];
|
||||
|
||||
if( zFilename==0 ) return;
|
||||
in = fopen(zFilename, "rb");
|
||||
if( in==0 ) return;
|
||||
fseek(in, 0, SEEK_END);
|
||||
sz = ftell(in);
|
||||
rewind(in);
|
||||
p = sqlite3_malloc( sz );
|
||||
if( p==0 ){
|
||||
fclose(in);
|
||||
sqlite3_result_error_nomem(context);
|
||||
return;
|
||||
}
|
||||
fread(p, sz, 1, in);
|
||||
fclose(in);
|
||||
sqlite3_snprintf(sizeof(zReturn),zReturn,"ptr=%lld&sz=%lld",
|
||||
(sqlite3_int64)p, sz);
|
||||
sqlite3_result_text(context, zReturn, -1, SQLITE_TRANSIENT);
|
||||
}
|
||||
/* Called for each new database connection */
|
||||
static int memvfsRegister(
|
||||
sqlite3 *db,
|
||||
const char **pzErrMsg,
|
||||
const struct sqlite3_api_routines *pThunk
|
||||
){
|
||||
return sqlite3_create_function(db, "memload", 1, SQLITE_UTF8, 0,
|
||||
memvfsMemloadFunc, 0, 0);
|
||||
}
|
||||
#endif /* MEMVFS_TEST */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
__declspec(dllexport)
|
||||
#endif
|
||||
/*
|
||||
** This routine is called when the extension is loaded.
|
||||
** Register the new VFS.
|
||||
*/
|
||||
int sqlite3_memvfs_init(
|
||||
sqlite3 *db,
|
||||
char **pzErrMsg,
|
||||
const sqlite3_api_routines *pApi
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
SQLITE_EXTENSION_INIT2(pApi);
|
||||
mem_vfs.pAppData = sqlite3_vfs_find(0);
|
||||
mem_vfs.szOsFile = sizeof(MemFile);
|
||||
rc = sqlite3_vfs_register(&mem_vfs, 1);
|
||||
#ifdef MEMVFS_TEST
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_auto_extension((void(*)(void))memvfsRegister);
|
||||
}
|
||||
#endif
|
||||
if( rc==SQLITE_OK ) rc = SQLITE_OK_LOAD_PERMANENTLY;
|
||||
return rc;
|
||||
}
|
||||
@@ -149,6 +149,15 @@ foreach {tn init mod} {
|
||||
INSERT INTO x1 VALUES('a', 'b', 'c');
|
||||
}
|
||||
|
||||
5 {
|
||||
CREATE TABLE t1(a PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(1, NULL);
|
||||
INSERT INTO t1 VALUES(2, X'');
|
||||
} {
|
||||
UPDATE t1 SET b = X'' WHERE a=1;
|
||||
UPDATE t1 SET b = NULL WHERE a=2;
|
||||
}
|
||||
|
||||
} {
|
||||
catch { db close }
|
||||
|
||||
|
||||
+5
-3
@@ -3012,10 +3012,12 @@ static int rtreeQueryStat1(sqlite3 *db, Rtree *pRtree){
|
||||
int rc;
|
||||
i64 nRow = 0;
|
||||
|
||||
if( sqlite3_table_column_metadata(db,pRtree->zDb,"sqlite_stat1",
|
||||
0,0,0,0,0,0)==SQLITE_ERROR ){
|
||||
rc = sqlite3_table_column_metadata(
|
||||
db, pRtree->zDb, "sqlite_stat1",0,0,0,0,0,0
|
||||
);
|
||||
if( rc!=SQLITE_OK ){
|
||||
pRtree->nRowEst = RTREE_DEFAULT_ROWEST;
|
||||
return SQLITE_OK;
|
||||
return rc==SQLITE_ERROR ? SQLITE_OK : rc;
|
||||
}
|
||||
zSql = sqlite3_mprintf(zFmt, pRtree->zDb, pRtree->zName);
|
||||
if( zSql==0 ){
|
||||
|
||||
@@ -30,7 +30,6 @@ do_test 1.0 {
|
||||
INSERT INTO x VALUES(19, 'domains', 'espouse', -94, 'throw');
|
||||
}
|
||||
|
||||
sqlite3session S db main
|
||||
set changeset [changeset_from_sql {
|
||||
DELETE FROM x WHERE e = -66;
|
||||
UPDATE x SET a = 'parameterizable', b = 31.8 WHERE c = 35;
|
||||
|
||||
@@ -157,7 +157,7 @@ int sqlite3session_attach(
|
||||
** CAPI3REF: Set a table filter on a Session Object.
|
||||
**
|
||||
** The second argument (xFilter) is the "filter callback". For changes to rows
|
||||
** in tables that are not attached to the Session oject, the filter is called
|
||||
** in tables that are not attached to the Session object, the filter is called
|
||||
** to determine whether changes to the table's rows should be tracked or not.
|
||||
** If xFilter returns 0, changes is not tracked. Note that once a table is
|
||||
** attached, xFilter will not be called again.
|
||||
@@ -423,7 +423,7 @@ int sqlite3session_isempty(sqlite3_session *pSession);
|
||||
** [sqlite3changeset_invert()] functions, all changes within the changeset
|
||||
** that apply to a single table are grouped together. This means that when
|
||||
** an application iterates through a changeset using an iterator created by
|
||||
** this function, all changes that relate to a single table are visted
|
||||
** this function, all changes that relate to a single table are visited
|
||||
** consecutively. There is no chance that the iterator will visit a change
|
||||
** the applies to table X, then one for table Y, and then later on visit
|
||||
** another change for table X.
|
||||
@@ -510,7 +510,7 @@ int sqlite3changeset_op(
|
||||
** 0x01 if the corresponding column is part of the tables primary key, or
|
||||
** 0x00 if it is not.
|
||||
**
|
||||
** If argumet pnCol is not NULL, then *pnCol is set to the number of columns
|
||||
** If argument pnCol is not NULL, then *pnCol is set to the number of columns
|
||||
** in the table.
|
||||
**
|
||||
** If this function is called when the iterator does not point to a valid
|
||||
@@ -785,7 +785,7 @@ int sqlite3changegroup_new(sqlite3_changegroup **pp);
|
||||
** apply to the same row as a change already present in the changegroup if
|
||||
** the two rows have the same primary key.
|
||||
**
|
||||
** Changes to rows that that do not already appear in the changegroup are
|
||||
** Changes to rows that do not already appear in the changegroup are
|
||||
** simply copied into it. Or, if both the new changeset and the changegroup
|
||||
** contain changes that apply to a single row, the final contents of the
|
||||
** changegroup depends on the type of each change, as follows:
|
||||
|
||||
@@ -293,6 +293,7 @@ TESTSRC = \
|
||||
$(TOP)/src/test_blob.c \
|
||||
$(TOP)/src/test_btree.c \
|
||||
$(TOP)/src/test_config.c \
|
||||
$(TOP)/src/test_delete.c \
|
||||
$(TOP)/src/test_demovfs.c \
|
||||
$(TOP)/src/test_devsym.c \
|
||||
$(TOP)/src/test_fs.c \
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
C Fix\sa\sproblem\shandling\sexpressions\slike\s"(a,\sb)\sIN\s(SELECT\s...\sORDER\sBY\s1,\s2)"\swhen\sthere\sis\san\sindex\son\s"a"\sbut\snot\s"b".
|
||||
D 2016-09-07T19:37:20.043
|
||||
F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088
|
||||
C Version\s3.15.0
|
||||
D 2016-10-14T10:20:30.806
|
||||
F Makefile.in 6fd48ffcf7c2deea7499062d1f3747f986c19678
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 5017381e4853b1472e01d5bb926be1268eba429c
|
||||
F Makefile.msc 5151cc64c4c05f3455f4f692ad11410a810d937f
|
||||
F README.md 8ecc12493ff9f820cdea6520a9016001cb2e59b7
|
||||
F VERSION 25e2e333adeff5965520bc8db999c658898c972d
|
||||
F aclocal.m4 a5c22d164aff7ed549d53a90fa56d56955281f50
|
||||
@@ -11,7 +11,7 @@ F art/sqlite370.ico af56c1d00fee7cd4753e8631ed60703ed0fc6e90
|
||||
F art/sqlite370.jpg d512473dae7e378a67e28ff96a34da7cb331def2
|
||||
F autoconf/INSTALL 83e4a25da9fd053c7b3665eaaaf7919707915903
|
||||
F autoconf/Makefile.am 1a47d071e3d5435f8f7ebff7eb6703848bbd65d4
|
||||
F autoconf/Makefile.msc a535edafb6165629715b0ba8e21c98ab80732e80
|
||||
F autoconf/Makefile.msc b6d27f735911fd09a589d3c966936c47a5850c17
|
||||
F autoconf/README.first 6c4f34fe115ff55d4e8dbfa3cecf04a0188292f7
|
||||
F autoconf/README.txt 4f04b0819303aabaa35fff5f7b257fb0c1ef95f1
|
||||
F autoconf/configure.ac cacf2616abf6e4a569bde2ef365c143caeec40bc
|
||||
@@ -33,7 +33,7 @@ F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
|
||||
F configure 3f44893bc0e51c30653e02b0fd4dc2ab585e446a x
|
||||
F configure.ac b5d3df43161374f8dffd2e5f4b88fbb51685b975
|
||||
F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
|
||||
F doc/lemon.html e2118945e5f07ed146b45c9cd2b2dd6eabb8ebf2
|
||||
F doc/lemon.html b5a3c07d33ecb8e019ce8f7660fe2dbbad9d7977
|
||||
F doc/pager-invariants.txt 27fed9a70ddad2088750c4a2b493b63853da2710
|
||||
F doc/vfs-shm.txt e101f27ea02a8387ce46a05be2b1a902a021d37a
|
||||
F ext/README.txt 913a7bd3f4837ab14d7e063304181787658b14e1
|
||||
@@ -99,10 +99,10 @@ F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl a36e54ec777172ddd3f9a88daf593b00848368e0
|
||||
F ext/fts5/fts5.h 62f3e33ceeb9a428db139f9c012186b371da1cc7
|
||||
F ext/fts5/fts5Int.h b2eda36e0f224365c8e23dc8f559311834f1c13f
|
||||
F ext/fts5/fts5_aux.c 2f20784a344701d4c72986e2e692062dd47d568c
|
||||
F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
|
||||
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
|
||||
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
|
||||
F ext/fts5/fts5_expr.c 1ee97156421919e497595bfa962bb88ad1665401
|
||||
F ext/fts5/fts5_expr.c c65c5629f4b3a49850fd84ea0731dee2360e144f
|
||||
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
|
||||
F ext/fts5/fts5_index.c 2d146d5c547f60d22d6fc4014d5e2b64248cd7c4
|
||||
F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2
|
||||
@@ -113,7 +113,7 @@ F ext/fts5/fts5_test_tok.c db08af63673c3a7d39f053b36fd6e065017706be
|
||||
F ext/fts5/fts5_tokenize.c 2ce7b44183538ec46b7907726262ee43ffdd39a8
|
||||
F ext/fts5/fts5_unicode2.c b450b209b157d598f7b9df9f837afb75a14c24bf
|
||||
F ext/fts5/fts5_varint.c a5aceacda04dafcbae725413d7a16818ecd65738
|
||||
F ext/fts5/fts5_vocab.c dba72ca393d71c2588548b51380387f6b44c77a8
|
||||
F ext/fts5/fts5_vocab.c e44fefa7f0c1db252998af071daf06a7147e17e7
|
||||
F ext/fts5/fts5parse.y e51b375403421b8b37428a89b095d00597129aae
|
||||
F ext/fts5/mkportersteps.tcl 5acf962d2e0074f701620bb5308155fa1e4a63ba
|
||||
F ext/fts5/test/fts5_common.tcl b01c584144b5064f30e6c648145a2dd6bc440841
|
||||
@@ -148,7 +148,7 @@ F ext/fts5/test/fts5determin.test 10648edb75ef1e196b10978fd21a9be0c31e09c3
|
||||
F ext/fts5/test/fts5dlidx.test 007e9390c94638760797dbec2990c97c3fa08dfe
|
||||
F ext/fts5/test/fts5doclist.test 8edb5b57e5f144030ed74ec00ef6fa4294fed79b
|
||||
F ext/fts5/test/fts5ea.test b01e3a18cdfabbff8104a96a5242a06a68a998a0
|
||||
F ext/fts5/test/fts5eb.test c516ae0c934be6fd29ec95ea8b5f11f461311535
|
||||
F ext/fts5/test/fts5eb.test 14597b5ecc9b2b7039ac5e0b0fca0311a7d22005
|
||||
F ext/fts5/test/fts5fault1.test e09040d3e17b8c0837101e8c79c8a874c4376fb7
|
||||
F ext/fts5/test/fts5fault2.test d8c6c7f916ccbdfc10b2c69530e9dd3bc8313232
|
||||
F ext/fts5/test/fts5fault3.test d6e9577d4312e331a913c72931bf131704efc8f3
|
||||
@@ -195,7 +195,7 @@ F ext/fts5/test/fts5unicode3.test 35c3d02aa7acf7d43d8de3bfe32c15ba96e8928e
|
||||
F ext/fts5/test/fts5unindexed.test e9539d5b78c677315e7ed8ea911d4fd25437c680
|
||||
F ext/fts5/test/fts5update.test 57c7012a7919889048947addae10e0613df45529
|
||||
F ext/fts5/test/fts5version.test 978f59541d8cef7e8591f8be2115ec5ccb863e2e
|
||||
F ext/fts5/test/fts5vocab.test 480d780aa6b699816c5066225fbd86f3a0239477
|
||||
F ext/fts5/test/fts5vocab.test 026799f8d24befc452cbddda79822f5ae8d5f4eb
|
||||
F ext/fts5/tool/fts5speed.tcl b0056f91a55b2d1a3684ec05729de92b042e2f85
|
||||
F ext/fts5/tool/fts5txt2db.tcl 526a9979c963f1c54fd50976a05a502e533a4c59
|
||||
F ext/fts5/tool/loadfts5.tcl 95b03429ee6b138645703c6ca192c3ac96eaf093
|
||||
@@ -214,6 +214,7 @@ F ext/misc/fileio.c d4171c815d6543a9edef8308aab2951413cd8d0f
|
||||
F ext/misc/fuzzer.c 7c64b8197bb77b7d64eff7cac7848870235d4c25
|
||||
F ext/misc/ieee754.c f190d0cc5182529acb15babd177781be1ac1718c
|
||||
F ext/misc/json1.c 9799e4252b305edcbe659329eec3ca80ed85f968
|
||||
F ext/misc/memvfs.c e5225bc22e79dde6b28380f3a068ddf600683a33
|
||||
F ext/misc/nextchar.c 35c8b8baacb96d92abbb34a83a997b797075b342
|
||||
F ext/misc/percentile.c 92699c8cd7d517ff610e6037e56506f8904dae2e
|
||||
F ext/misc/regexp.c a68d25c659bd2d893cd1215667bbf75ecb9dc7d4
|
||||
@@ -245,7 +246,7 @@ F ext/rbu/rbuB.test c25bc325b8072a766e56bb76c001866b405925c2
|
||||
F ext/rbu/rbuC.test efe47db508a0269b683cb2a1913a425ffd39a831
|
||||
F ext/rbu/rbu_common.tcl a38e8e2d4a50fd6aaf151633714c1b1d2fae3ead
|
||||
F ext/rbu/rbucrash.test 8d2ed5d4b05fef6c00c2a6b5f7ead71fa172a695
|
||||
F ext/rbu/rbudiff.test d099b56b073a737cfe1b8e9f67b77940130719cb
|
||||
F ext/rbu/rbudiff.test 3e605cf624d00d04d0fb1316a3acec4fbe3b3ac5
|
||||
F ext/rbu/rbufault.test cc0be8d5d392d98b0c2d6a51be377ea989250a89
|
||||
F ext/rbu/rbufault2.test 9a7f19edd6ea35c4c9f807d8a3db0a03a5670c06
|
||||
F ext/rbu/rbufault3.test 54a399888ac4af44c68f9f58afbed23149428bca
|
||||
@@ -258,7 +259,7 @@ F ext/rbu/sqlite3rbu.c e074c38798b90591f7f0cf0032d62f152ce5a95e
|
||||
F ext/rbu/sqlite3rbu.h 6fb6294c34a9ca93b5894a33bca530c6f08decba
|
||||
F ext/rbu/test_rbu.c 5aa22616afac6f71ebd3d9bc9bf1006cfabcca88
|
||||
F ext/rtree/README 6315c0d73ebf0ec40dedb5aa0e942bc8b54e3761
|
||||
F ext/rtree/rtree.c 0b450226001c8ae4622e382b2aff79127581a763
|
||||
F ext/rtree/rtree.c 078fc27417b48aaebe988621bf96ef0e1645b201
|
||||
F ext/rtree/rtree.h 834dbcb82dc85b2481cde6a07cdadfddc99e9b9e
|
||||
F ext/rtree/rtree1.test 42dadfc7b44a436cd74a1bebc0b9b689e4eaf7ec
|
||||
F ext/rtree/rtree2.test acbb3a4ce0f4fbc2c304d2b4b784cfa161856bba
|
||||
@@ -285,7 +286,7 @@ F ext/session/changeset.c 4ccbaa4531944c24584bf6a61ba3a39c62b6267a
|
||||
F ext/session/session1.test 98f384736e2bc21ccf5ed81bdadcff4ad863393b
|
||||
F ext/session/session2.test 284de45abae4cc1082bc52012ee81521d5ac58e0
|
||||
F ext/session/session3.test a7a9ce59b8d1e49e2cc23d81421ac485be0eea01
|
||||
F ext/session/session4.test a6ed685da7a5293c5d6f99855bcf41dbc352ca84
|
||||
F ext/session/session4.test 457b02bdc349eb01151e54de014df77abd3c08c8
|
||||
F ext/session/session5.test 716bc6fafd625ce60dfa62ae128971628c1a1169
|
||||
F ext/session/session6.test 443789bc2fca12e4f7075cf692c60b8a2bea1a26
|
||||
F ext/session/session8.test 8e194b3f655d861ca36de5d4de53f702751bab3b
|
||||
@@ -301,7 +302,7 @@ F ext/session/session_common.tcl 9b696a341cf1d3744823715ed92bb19749b6c3d4
|
||||
F ext/session/sessionfault.test da273f2712b6411e85e71465a1733b8501dbf6f7
|
||||
F ext/session/sessionfault2.test 04aa0bc9aa70ea43d8de82c4f648db4de1e990b0
|
||||
F ext/session/sqlite3session.c 37485891b4add26cf61495df193c419f36556a32
|
||||
F ext/session/sqlite3session.h 7b9037818ee61f7429ca83e9866885ca6de5f764
|
||||
F ext/session/sqlite3session.h 9345166bd8f80562145586cf817f707de5ecada2
|
||||
F ext/session/test_session.c eb0bd6c1ea791c1d66ee4ef94c16500dad936386
|
||||
F ext/userauth/sqlite3userauth.h 19cb6f0e31316d0ee4afdfb7a85ef9da3333a220
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
@@ -309,7 +310,7 @@ F ext/userauth/userauth.c 5fa3bdb492f481bbc1709fc83c91ebd13460c69e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
F main.mk 1883ecab643b136e8ab3fdc33785e6ea8b5ceb46
|
||||
F main.mk 06dc0b1a9c9e2d05c9275937dd5b894bfe7d17d8
|
||||
F mkso.sh fd21c06b063bb16a5d25deea1752c2da6ac3ed83
|
||||
F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
|
||||
F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
|
||||
@@ -323,34 +324,34 @@ F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c 299117695b1f21ac62dfc5b608588810ba22ed0d
|
||||
F src/analyze.c 8b62b2cf4da85451534ac0af82cafc418d837f68
|
||||
F src/attach.c 4711ff365df4072b8c3dcd55db5d12dcf8ffa0c6
|
||||
F src/attach.c 8c19066b4b5357b5d66154e856c61df01e71203a
|
||||
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
|
||||
F src/backup.c 92c2e3b5fcb47626413717138617f4d32f08aea4
|
||||
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
|
||||
F src/bitvec.c 3ee4c8b2c94ed3a7377256e18199e6ff5cf33f63
|
||||
F src/btmutex.c bc87dd3b062cc26edfe79918de2200ccb8d41e73
|
||||
F src/btree.c 2551bd3ecb8b8988fb8b23aabadfb214dbc38e46
|
||||
F src/btree.h 075c45707c0f8f8af118f739f36df8098a08b7da
|
||||
F src/btree.c 7a45743fb947c89bd6c972bfb18c8f80c070ad51
|
||||
F src/btree.h d05b2fcc290991a8a3d9ea1816ddd55a4359dcde
|
||||
F src/btreeInt.h c18b7d2a3494695133e4e60ee36061d37f45d9a5
|
||||
F src/build.c c2ccfcdd99e18894a8750e215b8d9c5398a3c073
|
||||
F src/build.c 59dcfdc1ee55439d069af301ef7f2e84421b5102
|
||||
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
|
||||
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
|
||||
F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7
|
||||
F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b
|
||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||
F src/delete.c 76c084f0265f4a3cd1ecf17eee112a94f1ccbc05
|
||||
F src/expr.c 028c34005cb804abe8f73453ac08baa44f4b63f9
|
||||
F src/delete.c cb3f6300df24c26c609778b2731f82644b5532ec
|
||||
F src/expr.c aac0b8d39373ce8f1d47829ce12c3d7af90c46a6
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e2be0968c1adc679c87e467aa5b4f167588f38a8
|
||||
F src/fkey.c b9ca262f6ad4d030a3cab737ebf9b0b3c8b4ac80
|
||||
F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771
|
||||
F src/global.c c45ea22aff29334f6a9ec549235ac3357c970015
|
||||
F src/hash.c 55b5fb474100cee0b901edaf203e26c970940f36
|
||||
F src/global.c 9da4ca5d74b90715f0ec4957f3d17a4749009f34
|
||||
F src/hash.c 63d0ee752a3b92d4695b2b1f5259c4621b2cfebd
|
||||
F src/hash.h ab34c5c54a9e9de2e790b24349ba5aab3dbb4fd4
|
||||
F src/hwtime.h 747c1bbe9df21a92e9c50f3bbec1de841dc5e5da
|
||||
F src/in-operator.md 10cd8f4bcd225a32518407c2fb2484089112fd71
|
||||
F src/insert.c 3edb5a1bda44df13531fedfcde5fbcc2fc04c222
|
||||
F src/insert.c 2d5e197f2f60351937b201196965fd14cd88489c
|
||||
F src/legacy.c 75d3023be8f0d2b99d60f905090341a03358c58e
|
||||
F src/loadext.c dd7a2b77902cc66c22555aef02e1a682554b7aec
|
||||
F src/main.c 9821bb4d2399bc5a0b8a5dfc06bede2d1520255c
|
||||
F src/loadext.c 5d6642d141c07d366e43d359e94ec9de47add41d
|
||||
F src/main.c c9e49e376820bccca55fa9bf2ca321a51725db91
|
||||
F src/malloc.c 1443d1ad95d67c21d77af7ae3f44678252f0efec
|
||||
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
|
||||
F src/mem1.c 6919bcf12f221868ea066eec27e579fed95ce98b
|
||||
@@ -374,30 +375,30 @@ F src/os_win.c 520f23475f1de530c435d30b67b7b15fe90874b0
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c bf5b71bde3e9b6110e7d6990607db881f6a471a2
|
||||
F src/pager.h 966d2769e76ae347c8a32c4165faf6e6cb64546d
|
||||
F src/parse.y 0e0b6d46a990d01e4ca1e9d7e1d2d9b5a98f6bcb
|
||||
F src/pcache.c 5583c8ade4b05075a60ba953ef471d1c1a9c05df
|
||||
F src/parse.y 0338f906b61e311c2b7e11a3f89b0092c780b664
|
||||
F src/pcache.c 5ff2a08f76a9c1b22f43eb063b7068fb085465ac
|
||||
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
|
||||
F src/pcache1.c 4bb7a6a5300c67d0b033d25adb509c120c03e812
|
||||
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
|
||||
F src/pragma.c d932ba278654617cdd281f88a790a3185fca7c44
|
||||
F src/pragma.h 64c78a648751b9f4f297276c4eb7507b14b4628c
|
||||
F src/prepare.c 0fcf16eaacc90c1059055519a76b75b516a59a88
|
||||
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
|
||||
F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1
|
||||
F src/random.c ba2679f80ec82c4190062d756f22d0c358180696
|
||||
F src/resolve.c 24f40fd0c3475821d1ad762a3f2c3455cc839b42
|
||||
F src/resolve.c 3fac1b2737ea5a724f20b921ac7e259c9be2100b
|
||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||
F src/select.c 244f9cc5e4662987cd2ef5c22d1b7027560f3425
|
||||
F src/shell.c de7c7e98846cacbfbe062cbd98bca899dfb720e3
|
||||
F src/sqlite.h.in 4a030e254e204570444b34bf7d40fb4a5416089e
|
||||
F src/select.c ea3af83e2d0f245fef81ea4cf04cb730ce67f722
|
||||
F src/shell.c b80396d2fadce4681397707e30078bf416e1dec2
|
||||
F src/sqlite.h.in 2683a291ed8db5228024267be6421f0de507b80e
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
|
||||
F src/sqliteInt.h c9e010a79ab4ed7bdc910a24d8f08f3c6d5f822c
|
||||
F src/sqliteInt.h 8d241c2c0a1a7b6611d3e9398f41d69426da850d
|
||||
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
F src/tclsqlite.c bdae822f21e229b6daced15938b6343ce44ef454
|
||||
F src/test1.c 8574e41c1bf103727909b37351b3690cc07bc8a7
|
||||
F src/tclsqlite.c aef87dcd8cb66564d560ab48d43d19ac812a1eab
|
||||
F src/test1.c 61a08ed5861f3396ea4ff83931387696b692e1f8
|
||||
F src/test2.c b7174313e993754303a8b33c43df7c44b46857ab
|
||||
F src/test3.c 1339a40be39650ae83894b6578f971dc7f96ea8a
|
||||
F src/test3.c d03f5b5da9a2410b7a91c64b0d3306ed28ab6fee
|
||||
F src/test4.c 18ec393bb4d0ad1de729f0b94da7267270f3d8e6
|
||||
F src/test5.c 328aae2c010c57a9829d255dc099d6899311672d
|
||||
F src/test6.c 55aa2775c154415dcf4ed7cd1e19a193122b3a02
|
||||
@@ -411,6 +412,7 @@ F src/test_bestindex.c d23f80d334c59662af69191854c76b8d3d0c8c96
|
||||
F src/test_blob.c a0f7ad49a0c9d4b72f693fe2a71c58d7e507174d
|
||||
F src/test_btree.c 8b2dc8b8848cf3a4db93f11578f075e82252a274
|
||||
F src/test_config.c 4d3d4a886416f369771d69a6dba926866deda788
|
||||
F src/test_delete.c 32690ea215abf29dda589a580cd1b790389759b6
|
||||
F src/test_demovfs.c a0c3bdd45ed044115c2c9f7779e56eafff18741e
|
||||
F src/test_devsym.c 4e58dec2602d8e139ca08659f62a62450587cb58
|
||||
F src/test_fs.c e16cbe68d3b107e00a907c20a9a02629870eb69b
|
||||
@@ -446,29 +448,29 @@ F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||
F src/tokenize.c 78c8085bc7af1922aa687f0f4bbd716821330de5
|
||||
F src/treeview.c f51b75a28b377adde9f79bc3deb6c7770bcf97c0
|
||||
F src/trigger.c 11e20b3b12c847b3b9055594c0f1631266bb53fc
|
||||
F src/trigger.c 3419bb9862983d84d70735fb4c94b21b934cd0c5
|
||||
F src/update.c 8179e699dbd45b92934fd02d3d8e3732e8da8802
|
||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||
F src/util.c 810ec3f22e2d1b62e66c30fe3621ebdedd23584d
|
||||
F src/util.c 3e2da6101888d073e79ecc6af5e0a2f70fa1e498
|
||||
F src/vacuum.c 913970b9d86dd6c2b8063ef1af421880f1464ec3
|
||||
F src/vdbe.c 3148d5d47816c5ad2ed3c62beb3086cbbcaab107
|
||||
F src/vdbe.h 67bc551f7faf04c33493892e4b378aada823ed10
|
||||
F src/vdbeInt.h c59381049af5c7751a83456c39b80d1a6fde1f9d
|
||||
F src/vdbeapi.c a32d61b7dd05e6890d8fd44d2805f55e2f5ba9f3
|
||||
F src/vdbeaux.c 83458783d241cfd6691141c8a105832ee50258e5
|
||||
F src/vdbe.c f43aa96f2efe9bc8a06d17115661af527a3318fa
|
||||
F src/vdbe.h c044be7050ac6bf596eecc6ab159f5dbc020a3b7
|
||||
F src/vdbeInt.h 0a18713d0a2fec6807d076bd333d9bf3e57530cd
|
||||
F src/vdbeapi.c 8272f9342c39ab8d7eb4b9decc6caa7bc75b7d83
|
||||
F src/vdbeaux.c 7229203e4e4a3b6eaeeddc807c2287d912c0da74
|
||||
F src/vdbeblob.c 3e82a797b60c3b9fed7b8de8c539ca7607874937
|
||||
F src/vdbemem.c e67dc6d8177fd1830efb5d15e17793408251a187
|
||||
F src/vdbemem.c fcdd73a2001a673f48a244a77b1038928ae729c9
|
||||
F src/vdbesort.c 91fda3909326860382b0ca8aa251e609c6a9d62c
|
||||
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
||||
F src/vtab.c e02cacb5c7ae742631edeb9ae9f53d399f093fd8
|
||||
F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
||||
F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a
|
||||
F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2
|
||||
F src/walker.c 2d2cc7fb0f320f7f415215d7247f3c584141ac09
|
||||
F src/where.c edbd73a87ba2e186928e9bfc14348b1bbb2628c5
|
||||
F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613
|
||||
F src/wherecode.c d172dcf99932ba698dd304edc9a368cd52b4b2e5
|
||||
F src/whereexpr.c e3db778ed205e982f31960896db71c50612ae009
|
||||
F src/walker.c 91a6df7435827e41cff6bb7df50ea00934ee78b0
|
||||
F src/where.c 5f846d94bb3d35b3146d9915eb301ee362957b0a
|
||||
F src/whereInt.h 2bcc3d176e6091cb8f50a30b65c006e88a73614d
|
||||
F src/wherecode.c 717a65294df46f30e9b9933d2a63a4bcbca5a9a8
|
||||
F src/whereexpr.c 379d0017fb7bc9e5a4d8cd4b056c747de946430e
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@@ -510,7 +512,7 @@ F test/attachmalloc.test 3a4bfca9545bfe906a8d2e622de10fbac5b711b0
|
||||
F test/auth.test 872a122b3977c1d1bb9fd637dc20016e5c01880f
|
||||
F test/auth2.test 9eb7fce9f34bf1f50d3f366fb3e606be5a2000a1
|
||||
F test/auth3.test b810826b193831929951c0d50783a200e5ef6b72
|
||||
F test/autoinc.test c58912526998a39e11f66b533e23cfabea7f25b7
|
||||
F test/autoinc.test c3a55c3667f429f4f4c7bed05f67b4d93e89e79d
|
||||
F test/autoindex1.test 14b63a9f1e405fe6d5bfc8c8d00249c2ebaf13ea
|
||||
F test/autoindex2.test 12ef578928102baaa0dc23ad397601a2f4ecb0df
|
||||
F test/autoindex3.test a3be0d1a53a7d2edff208a5e442312957047e972
|
||||
@@ -525,7 +527,7 @@ F test/backup2.test 34986ef926ea522911a51dfdb2f8e99b7b75ebcf
|
||||
F test/backup4.test 8f6fd48e0dfde77b9a3bb26dc471ede3e101df32
|
||||
F test/backup5.test ee5da6d7fe5082f5b9b0bbfa31d016f52412a2e4
|
||||
F test/backup_ioerr.test 4c3c7147cee85b024ecf6e150e090c32fdbb5135
|
||||
F test/backup_malloc.test 833d1b90561a6dbab00079b9591bd4fc90b7c2e1
|
||||
F test/backup_malloc.test 0c9abdf74c51e7bedb66d504cd684f28d4bd4027
|
||||
F test/badutf.test d5360fc31f643d37a973ab0d8b4fb85799c3169f
|
||||
F test/badutf2.test f5bc7f2d280670ecd79b9cf4f0f1760c607fe51f
|
||||
F test/bc_common.tcl b5e42d80305be95697e6370e015af571e5333a1c
|
||||
@@ -630,6 +632,7 @@ F test/delete.test acc38fca8ee4851467705b1c2cfea64cd26667e5
|
||||
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
|
||||
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
|
||||
F test/delete4.test 21d2113217eeaacac2d99defe14fe6611615ae86
|
||||
F test/delete_db.test c70a43629dd4d3e1dd03fdaf7a22153af6a69d92
|
||||
F test/descidx1.test 6d03b44c8538fe0eb4924e19fba10cdd8f3c9240
|
||||
F test/descidx2.test 9f1a0c83fd57f8667c82310ca21b30a350888b5d
|
||||
F test/descidx3.test 09ddbe3f5295f482d2f8b687cf6db8bad7acd9a2
|
||||
@@ -646,7 +649,7 @@ F test/e_delete.test ab39084f26ae1f033c940b70ebdbbd523dc4962e
|
||||
F test/e_droptrigger.test 3cd080807622c13e5bbb61fc9a57bd7754da2412
|
||||
F test/e_dropview.test 0c9f7f60989164a70a67a9d9c26d1083bc808306
|
||||
F test/e_expr.test 1ffa8866d38e7becc76893a8829e9432050e5716
|
||||
F test/e_fkey.test a1783fe1f759e1990e6a11adfcf0702dac4d0707
|
||||
F test/e_fkey.test 54cc0046d2d952d6c42b0dd94414e7a8f75f79f4
|
||||
F test/e_fts3.test 5c02288842e4f941896fd44afdef564dd5fc1459
|
||||
F test/e_insert.test 3de217e95094d3d165992a6de1164bbc4bd92dc7
|
||||
F test/e_reindex.test 2bebf7b393e519198b7c654407221cf171a439b8
|
||||
@@ -656,7 +659,7 @@ F test/e_select2.test aceb80ab927d46fba5ce7586ebabf23e2bb0604f
|
||||
F test/e_totalchanges.test b12ee5809d3e63aeb83238dd501a7bca7fd72c10
|
||||
F test/e_update.test f46c2554d915c9197548681e8d8c33a267e84528
|
||||
F test/e_uri.test 25385396082b67fd02ae0038b95a3b3575fe0519
|
||||
F test/e_vacuum.test 9e5e47e4059a779c777f47e0f560fc82c99336df
|
||||
F test/e_vacuum.test 1b8b4772d05374aa1b8958669138bbb4213ee26a
|
||||
F test/e_wal.test ae9a593207a77d711443ee69ffe081fda9243625
|
||||
F test/e_walauto.test 248af31e73c98df23476a22bdb815524c9dc3ba8
|
||||
F test/e_walckpt.test 28c371a6bb5e5fe7f31679c1df1763a19d19e8a0
|
||||
@@ -672,7 +675,7 @@ F test/exclusive.test 9a57bd66e39144b888ca75c309914fcdefb4e3f9
|
||||
F test/exclusive2.test 32798111aae78a5deec980eee383213f189df308
|
||||
F test/exec.test e949714dc127eaa5ecc7d723efec1ec27118fdd7
|
||||
F test/exists.test 79a75323c78f02bbe9c251ea502a092f9ef63dac
|
||||
F test/expr.test 79c3e7502d9e571553b85f0ecc8ff2ac7d0e4931
|
||||
F test/expr.test 66a2c9ac34f74f036faa4092f5402c7d3162fc93
|
||||
F test/extension01.test 00d13cec817f331a687a243e0e5a2d87b0e358c9
|
||||
F test/extraquick.test cb254400bd42bfb777ff675356aabf3287978f79
|
||||
F test/fallocate.test 3e979af17dfa7e5e9dda5eba1a696c04fa9d47f7
|
||||
@@ -743,7 +746,7 @@ F test/fts3an.test a49ccadc07a2f7d646ec1b81bc09da2d85a85b18
|
||||
F test/fts3ao.test 3e4e3d5e75c076520341d0bdf4eb17c00e8cbde2
|
||||
F test/fts3atoken.test 4b4c16fdcfc972f2cdbba212375a060a86ccf5f1
|
||||
F test/fts3auto.test b981fea19b132b4e6878f50d7c1f369b28f68eb9
|
||||
F test/fts3aux1.test f8f287a4a73f381f8fa15b6a70f36245f903d221
|
||||
F test/fts3aux1.test ca32c138aa777b476271df2da2c5538b7a43ada1
|
||||
F test/fts3aux2.test 7ae2b2c13aefdf4169279a27a5f51780ce57f6ba
|
||||
F test/fts3b.test e93bbb653e52afde110ad53bbd793f14fe7a8984
|
||||
F test/fts3c.test fc723a9cf10b397fdfc2b32e73c53c8b1ec02958
|
||||
@@ -828,7 +831,7 @@ F test/in.test 20c5529986998949908f889c8208b2cd894b2cc9
|
||||
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
|
||||
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
|
||||
F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068
|
||||
F test/in5.test acc710c12af118df5f8645eaba9479f5619eed81
|
||||
F test/in5.test 6c006e0bcd7351b69350ef566e65f244023489e9
|
||||
F test/incrblob.test c9b96afc292aeff43d6687bcb09b0280aa599822
|
||||
F test/incrblob2.test a5ce5ed1d0b01e2ed347245a21170372528af0a5
|
||||
F test/incrblob3.test d8d036fde015d4a159cd3cbae9d29003b37227a4
|
||||
@@ -845,11 +848,11 @@ F test/index2.test f835d5e13ca163bd78c4459ca15fd2e4ed487407
|
||||
F test/index3.test 81bc47890b8abfb181bc35f8d10b56c069803386
|
||||
F test/index4.test ab92e736d5946840236cd61ac3191f91a7856bf6
|
||||
F test/index5.test 8621491915800ec274609e42e02a97d67e9b13e7
|
||||
F test/index6.test 43b4e29258b978fcdab84fc61df4f5212119dd09
|
||||
F test/index7.test 9c6765a74fc3fcde7aebc5b3bd40d98df14a527c
|
||||
F test/index6.test b4fc812290067a578b98bb2667b676db89e202a7
|
||||
F test/index7.test 7feababe16f2091b229c22aff2bcc1d4d6b9d2bb
|
||||
F test/index8.test bc2e3db70e8e62459aaa1bd7e4a9b39664f8f9d7
|
||||
F test/indexedby.test 9c4cd331224e57f79fbf411ae245e6272d415985
|
||||
F test/indexexpr1.test cb71b6586177b840e28110dd952178bb2bdfedc2
|
||||
F test/indexexpr1.test 7d243fac508b4a99fb900ffe34eb488312cfce84
|
||||
F test/indexfault.test 31d4ab9a7d2f6e9616933eb079722362a883eb1d
|
||||
F test/init.test 15c823093fdabbf7b531fe22cf037134d09587a7
|
||||
F test/insert.test 38742b5e9601c8f8d76e9b7555f7270288c2d371
|
||||
@@ -890,7 +893,7 @@ F test/like.test 81632c437a947bf1f7130b19537da6a1a844806a
|
||||
F test/like2.test 3b2ee13149ba4a8a60b59756f4e5d345573852da
|
||||
F test/like3.test 3608a2042b6f922f900fbfd5d3ce4e7eca57f7c4
|
||||
F test/limit.test 0c99a27a87b14c646a9d583c7c89fd06c352663e
|
||||
F test/limit2.test ac97b8d07060a0280162ba4159e4c0c765861127
|
||||
F test/limit2.test e35f57bd3a62d7c5dcb5ac4306e675c75f974809
|
||||
F test/loadext.test d077450695ddb5c1ea3ad7d48e5f5850fe732ad9
|
||||
F test/loadext2.test 0408380b57adca04004247179837a18e866a74f7
|
||||
F test/lock.test be4fe08118fb988fed741f429b7dd5d65e1c90db
|
||||
@@ -921,7 +924,7 @@ F test/mallocE.test db1ed69d7eded1b080952e2a7c37f364ad241b08
|
||||
F test/mallocF.test 2d5c590ebc2fc7f0dcebdf5aa8498b9aed69107e
|
||||
F test/mallocG.test 0ff91b65c50bdaba680fb75d87fe4ad35bb7934f
|
||||
F test/mallocH.test 79b65aed612c9b3ed2dcdaa727c85895fd1bfbdb
|
||||
F test/mallocI.test a88c2b9627c8506bf4703d8397420043a786cdb6
|
||||
F test/mallocI.test 6c23a71df077fa5d387be90e7e669c5b368ca38a
|
||||
F test/mallocJ.test b5d1839da331d96223e5f458856f8ffe1366f62e
|
||||
F test/mallocK.test 27cb5566a6e5f2d76f9d4aa2eca45524401fd61e
|
||||
F test/mallocL.test fb311ff80afddf3b1a75e52289081f4754d901dc
|
||||
@@ -991,7 +994,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
|
||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test 544a2f317fc5045bc512ae432f89eae303c0d640
|
||||
F test/permutations.test cd0b7bc04bf5e50d3a993d24c834d591f7d4f5fe
|
||||
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
@@ -1012,7 +1015,7 @@ F test/rdonly.test 64e2696c322e3538df0b1ed624e21f9a23ed9ff8
|
||||
F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8
|
||||
F test/regexp2.test aa7ffcc21350007a78361b82bcf3b74d12227144
|
||||
F test/reindex.test 44edd3966b474468b823d481eafef0c305022254
|
||||
F test/releasetest.tcl 53560b838b79c468ec9973e0dfa3d8892628887f
|
||||
F test/releasetest.tcl cb06c4df0de4872e65b178316f8a87ccf7624d59 x
|
||||
F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb
|
||||
F test/rollback.test 458fe73eb3ffdfdf9f6ba3e9b7350a6220414dea
|
||||
F test/rollback2.test 8435d6ff0f13f51d2a4181c232e706005fa90fc5
|
||||
@@ -1024,7 +1027,7 @@ F test/rowvalue.test 753eb744b7efeb5ac643d35d6e1e5066452ccf79
|
||||
F test/rowvalue2.test 060d238b7e5639a7c5630cb5e63e311b44efef2b
|
||||
F test/rowvalue3.test 01399b7bf150b0d41abce76c18072da777c2500c
|
||||
F test/rowvalue4.test 4b556d7de161a0dd8cff095c336e913986398bea
|
||||
F test/rowvalue5.test c1adfb2ea104e181f70d55bbd80d803b9917b22b
|
||||
F test/rowvalue5.test c81c7d8cf36711ab37675ad7376084ae2a359cb6
|
||||
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test 5d06ff19d9e6969e574a2e662a531dd0c67801a8
|
||||
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
|
||||
@@ -1086,7 +1089,7 @@ F test/shortread1.test bb591ef20f0fd9ed26d0d12e80eee6d7ac8897a3
|
||||
F test/show_speedtest1_rtree.tcl 32e6c5f073d7426148a6936a0408f4b5b169aba5
|
||||
F test/shrink.test 1b4330b1fd9e818c04726d45cb28db73087535ce
|
||||
F test/sidedelete.test f0ad71abe6233e3b153100f3b8d679b19a488329
|
||||
F test/skipscan1.test f2d4482f195f018c3732374d3985fc34bcc3ae1a
|
||||
F test/skipscan1.test 8ab5d2c7c5cd3fe7f172d366e6e74e887cb33cb4
|
||||
F test/skipscan2.test d1d1450952b7275f0b0a3a981f0230532743951a
|
||||
F test/skipscan3.test ec5bab3f81c7038b43450e7b3062e04a198bdbb5
|
||||
F test/skipscan5.test 67817a4b6857c47e0e33ba3e506da6f23ef68de2
|
||||
@@ -1109,7 +1112,7 @@ F test/speed3.test 694affeb9100526007436334cf7d08f3d74b85ef
|
||||
F test/speed4.test abc0ad3399dcf9703abed2fff8705e4f8e416715
|
||||
F test/speed4p.explain 6b5f104ebeb34a038b2f714150f51d01143e59aa
|
||||
F test/speed4p.test 0e51908951677de5a969b723e03a27a1c45db38b
|
||||
F test/speedtest1.c 28221f433d358dd3fcf2ca504ed51409aa66ffaf
|
||||
F test/speedtest1.c 43b25ae8e303bcada98e00be036e710de17d346a
|
||||
F test/spellfix.test f9c1f431e2c096c8775fec032952320c0e4700db
|
||||
F test/spellfix2.test dfc8f519a3fc204cb2dfa8b4f29821ae90f6f8c3
|
||||
F test/spellfix3.test 0f9efaaa502a0e0a09848028518a6fb096c8ad33
|
||||
@@ -1299,7 +1302,7 @@ F test/tokenize.test ce430a7aed48fc98301611429595883fdfcab5d7
|
||||
F test/tpch01.test 04adbf8d8300fa60a222f28d901abd76e7be6dd4
|
||||
F test/trace.test 6f676313e3ebd2a50585036d2f212a3319dd5836
|
||||
F test/trace2.test f5cb67ad3bc09e0c58e8cca78dfd0b5639259983
|
||||
F test/trace3.test 01e4111d582c7b20ab1c63156169157d256bc3d5
|
||||
F test/trace3.test 56ab944fddacf628b118cc298503fc45c2e50ab0
|
||||
F test/trans.test 6e1b4c6a42dba31bd65f8fa5e61a2708e08ddde6
|
||||
F test/trans2.test 62bd045bfc7a1c14c5ba83ba64d21ade31583f76
|
||||
F test/trans3.test 91a100e5412b488e22a655fe423a14c26403ab94
|
||||
@@ -1338,8 +1341,8 @@ F test/vacuum.test ce91c39f7f91a4273bf620efad21086b5aa6ef1d
|
||||
F test/vacuum2.test aa048abee196c16c9ba308465494009057b79f9b
|
||||
F test/vacuum3.test 77ecdd54592b45a0bcb133339f99f1ae0ae94d0d
|
||||
F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
||||
F test/vacuum5.test 99d4a0629252f9ef2fc642caefe92436a744db3a
|
||||
F test/vacuummem.test e53a3fdca4612a99c515e1afe7934728a2383764
|
||||
F test/vacuum5.test 0b7ac80c64eed657b4ce2dd6535092c0d6afec6c
|
||||
F test/vacuummem.test 7b42abb3208bd82dd23a7536588396f295a314f2
|
||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||
F test/veryquick.test 57ab846bacf7b90cf4e9a672721ea5c5b669b661
|
||||
F test/view.test 765802c7a66d37fabd5ac8e2f2dbe572b43eb9ab
|
||||
@@ -1434,7 +1437,7 @@ F test/wordcount.c 97856eec21fd00d77da720007b1888c383f63dcf
|
||||
F test/zeroblob.test 3857870fe681b8185654414a9bccfde80b62a0fa
|
||||
F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||
F tool/GetTclKit.bat 629d87562e0487c386db630033931d12d62e6372
|
||||
F tool/GetTclKit.bat f94784e3bdc2f50c539266f5467cbf1f27612cb3
|
||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||
F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189
|
||||
F tool/build-all-msvc.bat 3e4e4043b53f1aede4308e0d2567bbd773614630 x
|
||||
@@ -1450,7 +1453,7 @@ F tool/genfkey.README cf68fddd4643bbe3ff8e31b8b6d8b0a1b85e20f4
|
||||
F tool/genfkey.test 4196a8928b78f51d54ef58e99e99401ab2f0a7e5
|
||||
F tool/getlock.c f4c39b651370156cae979501a7b156bdba50e7ce
|
||||
F tool/lemon.c e4fb7d888873ac88f20a41c84a7d1e61f5209a6d
|
||||
F tool/lempar.c 147e42a5cd83ce38275fde0d07a5df3330cb9b3b
|
||||
F tool/lempar.c 7cf047778e74433126cb02896e3f898d7b1e20aa
|
||||
F tool/libvers.c caafc3b689638a1d88d44bc5f526c2278760d9b9
|
||||
F tool/loadfts.c c3c64e4d5e90e8ba41159232c2189dba4be7b862
|
||||
F tool/logest.c 11346aa019e2e77a00902aa7d0cabd27bd2e8cca
|
||||
@@ -1462,9 +1465,9 @@ F tool/mkopcodeh.tcl a01d2c1d8a6205b03fc635adf3735b4c523befd3
|
||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e
|
||||
F tool/mkpragmatab.tcl f0d5bb266d1d388cf86fce5ba01a891e95d72d41
|
||||
F tool/mkspeedsql.tcl a1a334d288f7adfe6e996f2e712becf076745c97
|
||||
F tool/mksqlite3c-noext.tcl aa58ea3be311c81821c2cd3209f55e46b07ab656
|
||||
F tool/mksqlite3c.tcl 63af8429841f08552e6da1d93b3dee4a93ff8071
|
||||
F tool/mksqlite3h.tcl e7b106fc4f29fbc258e8ba9b88d9108332ea2ade
|
||||
F tool/mksqlite3c-noext.tcl fef88397668ae83166735c41af99d79f56afaabb
|
||||
F tool/mksqlite3c.tcl 06b2e6a0f21cc0a5d70fbbd136b3e0a96470645e
|
||||
F tool/mksqlite3h.tcl c006c4e5da57c649b24b689511dcd270dd7b0249
|
||||
F tool/mksqlite3internalh.tcl eb994013e833359137eb53a55acdad0b5ae1049b
|
||||
F tool/mkvsix.tcl 4abcaf3267171b2faadaf9b82a0dfbaa6e98f8b7
|
||||
F tool/offsets.c fe4262fdfa378e8f5499a42136d17bf3b98f6091
|
||||
@@ -1481,15 +1484,15 @@ F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||
F tool/showstat4.c bda40d6e395df7edb6e9ea630784d3d762c35b4b
|
||||
F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977
|
||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||
F tool/spaceanal.tcl 85d90e6674d8298e3eaf82dbcef3abc2d5317f3e
|
||||
F tool/speed-check.sh 45d3bf861b009993ff401f0d00e34a4cc937fce4
|
||||
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
|
||||
F tool/speed-check.sh da6ce45957c509ba6343fe3fef167e7e2b306262
|
||||
F tool/speedtest.tcl 06c76698485ccf597b9e7dbb1ac70706eb873355
|
||||
F tool/speedtest16.c ecb6542862151c3e6509bbc00509b234562ae81e
|
||||
F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||
F tool/speedtest8inst1.c 7ce07da76b5e745783e703a834417d725b7d45fd
|
||||
F tool/split-sqlite3c.tcl d9be87f1c340285a3e081eb19b4a247981ed290c
|
||||
F tool/sqldiff.c 7f567367d87fdb493e3e65169569a10d9f330c3f
|
||||
F tool/sqldiff.c 3fb48a6c6669d2d2c59a7f072a410dd2583579b4
|
||||
F tool/srcck1.c 371de5363b70154012955544f86fdee8f6e5326f
|
||||
F tool/stack_usage.tcl f8e71b92cdb099a147dad572375595eae55eca43
|
||||
F tool/symbols-mingw.sh 4dbcea7e74768305384c9fd2ed2b41bbf9f0414d
|
||||
@@ -1499,7 +1502,7 @@ F tool/varint.c 5d94cb5003db9dbbcbcc5df08d66f16071aee003
|
||||
F tool/vdbe-compress.tcl 5926c71f9c12d2ab73ef35c29376e756eb68361c
|
||||
F tool/vdbe_profile.tcl 246d0da094856d72d2c12efec03250d71639d19f
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh a98af506df552f3b3c0d904f94e4cdc4e1a6d598
|
||||
F tool/warnings.sh d9ded5274b3cb947e98e70d587f71d6263f803b5
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
F vsixtest/App.xaml b76d3b48860e7454775c47ea38ffea9c4abe3e85
|
||||
F vsixtest/App.xaml.cpp c465147f50871165c60ca16955219f6c5812d6d8
|
||||
@@ -1522,7 +1525,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P bbab9621f512b04684163b98b6fc669c68038044
|
||||
R 09b192e18dc26d97d5a589656b60205f
|
||||
U dan
|
||||
Z 3d9ebf68fced17edbc91ddfab98198fe
|
||||
P 4d66ac98deaa85218be7ff0eb254f78b96d8e8d4
|
||||
R a065c821855a0dd84a6e1c87c8d5ef05
|
||||
T +bgcolor * #d0c0ff
|
||||
T +sym-release *
|
||||
T +sym-version-3.15.0 *
|
||||
U drh
|
||||
Z 64923968438b03dca07652ab710e8b24
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
7f2c5c9ee3628c968306a5ab2e5a9a761f1b8055
|
||||
707875582fcba352b4906a595ad89198d84711d8
|
||||
+2
-2
@@ -192,7 +192,7 @@ static void attachFunc(
|
||||
case SQLITE_NULL:
|
||||
/* No key specified. Use the key from the main database */
|
||||
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
|
||||
if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
|
||||
if( nKey || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
|
||||
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
|
||||
}
|
||||
break;
|
||||
@@ -530,7 +530,7 @@ int sqlite3FixExpr(
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly) ) break;
|
||||
if( ExprHasProperty(pExpr, EP_TokenOnly|EP_Leaf) ) break;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( sqlite3FixSelect(pFix, pExpr->x.pSelect) ) return 1;
|
||||
}else{
|
||||
|
||||
+8
-14
@@ -83,22 +83,16 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
|
||||
int i = sqlite3FindDbName(pDb, zDb);
|
||||
|
||||
if( i==1 ){
|
||||
Parse *pParse;
|
||||
Parse sParse;
|
||||
int rc = 0;
|
||||
pParse = sqlite3StackAllocZero(pErrorDb, sizeof(*pParse));
|
||||
if( pParse==0 ){
|
||||
sqlite3ErrorWithMsg(pErrorDb, SQLITE_NOMEM, "out of memory");
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
}else{
|
||||
pParse->db = pDb;
|
||||
if( sqlite3OpenTempDatabase(pParse) ){
|
||||
sqlite3ErrorWithMsg(pErrorDb, pParse->rc, "%s", pParse->zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
|
||||
sqlite3ParserReset(pParse);
|
||||
sqlite3StackFree(pErrorDb, pParse);
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
sParse.db = pDb;
|
||||
if( sqlite3OpenTempDatabase(&sParse) ){
|
||||
sqlite3ErrorWithMsg(pErrorDb, sParse.rc, "%s", sParse.zErrMsg);
|
||||
rc = SQLITE_ERROR;
|
||||
}
|
||||
sqlite3DbFree(pErrorDb, sParse.zErrMsg);
|
||||
sqlite3ParserReset(&sParse);
|
||||
if( rc ){
|
||||
return 0;
|
||||
}
|
||||
|
||||
+6
-5
@@ -763,7 +763,7 @@ static int btreeMoveto(
|
||||
){
|
||||
int rc; /* Status code */
|
||||
UnpackedRecord *pIdxKey; /* Unpacked index key */
|
||||
char aSpace[200]; /* Temp space for pIdxKey - to avoid a malloc */
|
||||
char aSpace[384]; /* Temp space for pIdxKey - to avoid a malloc */
|
||||
char *pFree = 0;
|
||||
|
||||
if( pKey ){
|
||||
@@ -1605,8 +1605,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){
|
||||
if( data[iPtr+1]==0 && data[iPtr]==0 ){
|
||||
iFreeBlk = 0; /* Shortcut for the case when the freelist is empty */
|
||||
}else{
|
||||
while( (iFreeBlk = get2byte(&data[iPtr]))>0 && iFreeBlk<iStart ){
|
||||
if( iFreeBlk<iPtr+4 ) return SQLITE_CORRUPT_BKPT;
|
||||
while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){
|
||||
if( iFreeBlk<iPtr+4 ){
|
||||
if( iFreeBlk==0 ) break;
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
iPtr = iFreeBlk;
|
||||
}
|
||||
if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT;
|
||||
@@ -6097,8 +6100,6 @@ static int fillInCell(
|
||||
nHeader += putVarint32(&pCell[nHeader], nPayload);
|
||||
nHeader += putVarint(&pCell[nHeader], *(u64*)&pX->nKey);
|
||||
}else{
|
||||
assert( pX->nData==0 );
|
||||
assert( pX->nZero==0 );
|
||||
assert( pX->nKey<=0x7fffffff && pX->pKey!=0 );
|
||||
nSrc = nPayload = (int)pX->nKey;
|
||||
pSrc = pX->pKey;
|
||||
|
||||
@@ -90,7 +90,9 @@ int sqlite3BtreeIsInReadTrans(Btree*);
|
||||
int sqlite3BtreeIsInBackup(Btree*);
|
||||
void *sqlite3BtreeSchema(Btree *, int, void(*)(void *));
|
||||
int sqlite3BtreeSchemaLocked(Btree *pBtree);
|
||||
#ifndef SQLITE_OMIT_SHARED_CACHE
|
||||
int sqlite3BtreeLockTable(Btree *pBtree, int iTab, u8 isWriteLock);
|
||||
#endif
|
||||
int sqlite3BtreeSavepoint(Btree *, int, int);
|
||||
|
||||
const char *sqlite3BtreeGetFilename(Btree *);
|
||||
@@ -293,8 +295,10 @@ int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
|
||||
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
|
||||
struct Pager *sqlite3BtreePager(Btree*);
|
||||
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*);
|
||||
void sqlite3BtreeIncrblobCursor(BtCursor *);
|
||||
#endif
|
||||
void sqlite3BtreeClearCursor(BtCursor *);
|
||||
int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
|
||||
int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
|
||||
|
||||
+16
-23
@@ -146,7 +146,6 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
assert( !pParse->isMultiWrite
|
||||
|| sqlite3VdbeAssertMayAbort(v, pParse->mayAbort));
|
||||
if( v ){
|
||||
while( sqlite3VdbeDeletePriorOpcode(v, OP_Close) ){}
|
||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||
|
||||
#if SQLITE_USER_AUTHENTICATION
|
||||
@@ -173,14 +172,16 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
assert( sqlite3VdbeGetOp(v, 0)->opcode==OP_Init );
|
||||
sqlite3VdbeJumpHere(v, 0);
|
||||
for(iDb=0; iDb<db->nDb; iDb++){
|
||||
Schema *pSchema;
|
||||
if( DbMaskTest(pParse->cookieMask, iDb)==0 ) continue;
|
||||
sqlite3VdbeUsesBtree(v, iDb);
|
||||
pSchema = db->aDb[iDb].pSchema;
|
||||
sqlite3VdbeAddOp4Int(v,
|
||||
OP_Transaction, /* Opcode */
|
||||
iDb, /* P1 */
|
||||
DbMaskTest(pParse->writeMask,iDb), /* P2 */
|
||||
pParse->cookieValue[iDb], /* P3 */
|
||||
db->aDb[iDb].pSchema->iGeneration /* P4 */
|
||||
pSchema->schema_cookie, /* P3 */
|
||||
pSchema->iGeneration /* P4 */
|
||||
);
|
||||
if( db->init.busy==0 ) sqlite3VdbeChangeP5(v, 1);
|
||||
VdbeComment((v,
|
||||
@@ -231,16 +232,6 @@ void sqlite3FinishCoding(Parse *pParse){
|
||||
}else{
|
||||
pParse->rc = SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/* We are done with this Parse object. There is no need to de-initialize it */
|
||||
#if 0
|
||||
pParse->colNamesSet = 0;
|
||||
pParse->nTab = 0;
|
||||
pParse->nMem = 0;
|
||||
pParse->nSet = 0;
|
||||
pParse->nVar = 0;
|
||||
DbMaskZero(pParse->cookieMask);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -260,8 +251,7 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
char *zSql;
|
||||
char *zErrMsg = 0;
|
||||
sqlite3 *db = pParse->db;
|
||||
# define SAVE_SZ (sizeof(Parse) - offsetof(Parse,nVar))
|
||||
char saveBuf[SAVE_SZ];
|
||||
char saveBuf[PARSE_TAIL_SZ];
|
||||
|
||||
if( pParse->nErr ) return;
|
||||
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
|
||||
@@ -272,12 +262,12 @@ void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
|
||||
return; /* A malloc must have failed */
|
||||
}
|
||||
pParse->nested++;
|
||||
memcpy(saveBuf, &pParse->nVar, SAVE_SZ);
|
||||
memset(&pParse->nVar, 0, SAVE_SZ);
|
||||
memcpy(saveBuf, PARSE_TAIL(pParse), PARSE_TAIL_SZ);
|
||||
memset(PARSE_TAIL(pParse), 0, PARSE_TAIL_SZ);
|
||||
sqlite3RunParser(pParse, zSql, &zErrMsg);
|
||||
sqlite3DbFree(db, zErrMsg);
|
||||
sqlite3DbFree(db, zSql);
|
||||
memcpy(&pParse->nVar, saveBuf, SAVE_SZ);
|
||||
memcpy(PARSE_TAIL(pParse), saveBuf, PARSE_TAIL_SZ);
|
||||
pParse->nested--;
|
||||
}
|
||||
|
||||
@@ -1458,6 +1448,9 @@ CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char *zName){
|
||||
** set back to prior value. But schema changes are infrequent
|
||||
** and the probability of hitting the same cookie value is only
|
||||
** 1 chance in 2^32. So we're safe enough.
|
||||
**
|
||||
** IMPLEMENTATION-OF: R-34230-56049 SQLite automatically increments
|
||||
** the schema-version whenever the schema changes.
|
||||
*/
|
||||
void sqlite3ChangeCookie(Parse *pParse, int iDb){
|
||||
sqlite3 *db = pParse->db;
|
||||
@@ -2141,7 +2134,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
||||
int nErr = 0; /* Number of errors encountered */
|
||||
int n; /* Temporarily holds the number of cursors assigned */
|
||||
sqlite3 *db = pParse->db; /* Database connection for malloc errors */
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
sqlite3_xauth xAuth; /* Saved xAuth pointer */
|
||||
#endif
|
||||
|
||||
assert( pTable );
|
||||
|
||||
@@ -4039,15 +4034,13 @@ int sqlite3OpenTempDatabase(Parse *pParse){
|
||||
*/
|
||||
void sqlite3CodeVerifySchema(Parse *pParse, int iDb){
|
||||
Parse *pToplevel = sqlite3ParseToplevel(pParse);
|
||||
sqlite3 *db = pToplevel->db;
|
||||
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
assert( db->aDb[iDb].pBt!=0 || iDb==1 );
|
||||
assert( iDb>=0 && iDb<pParse->db->nDb );
|
||||
assert( pParse->db->aDb[iDb].pBt!=0 || iDb==1 );
|
||||
assert( iDb<SQLITE_MAX_ATTACHED+2 );
|
||||
assert( sqlite3SchemaMutexHeld(db, iDb, 0) );
|
||||
assert( sqlite3SchemaMutexHeld(pParse->db, iDb, 0) );
|
||||
if( DbMaskTest(pToplevel->cookieMask, iDb)==0 ){
|
||||
DbMaskSet(pToplevel->cookieMask, iDb);
|
||||
pToplevel->cookieValue[iDb] = db->aDb[iDb].pSchema->schema_cookie;
|
||||
if( !OMIT_TEMPDB && iDb==1 ){
|
||||
sqlite3OpenTempDatabase(pToplevel);
|
||||
}
|
||||
|
||||
+3
-4
@@ -212,7 +212,6 @@ void sqlite3DeleteFrom(
|
||||
){
|
||||
Vdbe *v; /* The virtual database engine */
|
||||
Table *pTab; /* The table from which records will be deleted */
|
||||
const char *zDb; /* Name of database holding pTab */
|
||||
int i; /* Loop counter */
|
||||
WhereInfo *pWInfo; /* Information about the WHERE clause */
|
||||
Index *pIdx; /* For looping over indices of the table */
|
||||
@@ -289,8 +288,8 @@ void sqlite3DeleteFrom(
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb<db->nDb );
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb);
|
||||
rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0,
|
||||
db->aDb[iDb].zDbSName);
|
||||
assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE );
|
||||
if( rcauth==SQLITE_DENY ){
|
||||
goto delete_from_cleanup;
|
||||
@@ -474,7 +473,7 @@ void sqlite3DeleteFrom(
|
||||
if( !isView ){
|
||||
int iAddrOnce = 0;
|
||||
if( eOnePass==ONEPASS_MULTI ){
|
||||
iAddrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
iAddrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
}
|
||||
testcase( IsVirtual(pTab) );
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenWrite, OPFLAG_FORDELETE,
|
||||
|
||||
+122
-155
@@ -720,7 +720,7 @@ void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
|
||||
** is allocated to hold the integer text and the dequote flag is ignored.
|
||||
*/
|
||||
Expr *sqlite3ExprAlloc(
|
||||
sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */
|
||||
sqlite3 *db, /* Handle for sqlite3DbMallocRawNN() */
|
||||
int op, /* Expression opcode */
|
||||
const Token *pToken, /* Token argument. Might be NULL */
|
||||
int dequote /* True to dequote */
|
||||
@@ -938,7 +938,7 @@ Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *pToken){
|
||||
** instance of the wildcard, the next sequential variable number is
|
||||
** assigned.
|
||||
*/
|
||||
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr, u32 n){
|
||||
sqlite3 *db = pParse->db;
|
||||
const char *z;
|
||||
|
||||
@@ -947,19 +947,19 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
z = pExpr->u.zToken;
|
||||
assert( z!=0 );
|
||||
assert( z[0]!=0 );
|
||||
assert( n==sqlite3Strlen30(z) );
|
||||
if( z[1]==0 ){
|
||||
/* Wildcard of the form "?". Assign the next variable number */
|
||||
assert( z[0]=='?' );
|
||||
pExpr->iColumn = (ynVar)(++pParse->nVar);
|
||||
}else{
|
||||
ynVar x = 0;
|
||||
u32 n = sqlite3Strlen30(z);
|
||||
ynVar x;
|
||||
if( z[0]=='?' ){
|
||||
/* Wildcard of the form "?nnn". Convert "nnn" to an integer and
|
||||
** use it as the variable number */
|
||||
i64 i;
|
||||
int bOk = 0==sqlite3Atoi64(&z[1], &i, n-1, SQLITE_UTF8);
|
||||
pExpr->iColumn = x = (ynVar)i;
|
||||
x = (ynVar)i;
|
||||
testcase( i==0 );
|
||||
testcase( i==1 );
|
||||
testcase( i==db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]-1 );
|
||||
@@ -967,7 +967,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
if( bOk==0 || i<1 || i>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
||||
sqlite3ErrorMsg(pParse, "variable number must be between ?1 and ?%d",
|
||||
db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER]);
|
||||
x = 0;
|
||||
return;
|
||||
}
|
||||
if( i>pParse->nVar ){
|
||||
pParse->nVar = (int)i;
|
||||
@@ -978,33 +978,31 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){
|
||||
** has never appeared before, reuse the same variable number
|
||||
*/
|
||||
ynVar i;
|
||||
for(i=0; i<pParse->nzVar; i++){
|
||||
for(i=x=0; i<pParse->nzVar; i++){
|
||||
if( pParse->azVar[i] && strcmp(pParse->azVar[i],z)==0 ){
|
||||
pExpr->iColumn = x = (ynVar)i+1;
|
||||
x = (ynVar)i+1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( x==0 ) x = pExpr->iColumn = (ynVar)(++pParse->nVar);
|
||||
if( x==0 ) x = (ynVar)(++pParse->nVar);
|
||||
}
|
||||
if( x>0 ){
|
||||
if( x>pParse->nzVar ){
|
||||
char **a;
|
||||
a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
|
||||
if( a==0 ){
|
||||
assert( db->mallocFailed ); /* Error reported through mallocFailed */
|
||||
return;
|
||||
}
|
||||
pParse->azVar = a;
|
||||
memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
|
||||
pParse->nzVar = x;
|
||||
}
|
||||
if( z[0]!='?' || pParse->azVar[x-1]==0 ){
|
||||
sqlite3DbFree(db, pParse->azVar[x-1]);
|
||||
pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
|
||||
pExpr->iColumn = x;
|
||||
if( x>pParse->nzVar ){
|
||||
char **a;
|
||||
a = sqlite3DbRealloc(db, pParse->azVar, x*sizeof(a[0]));
|
||||
if( a==0 ){
|
||||
assert( db->mallocFailed ); /* Error reported through mallocFailed */
|
||||
return;
|
||||
}
|
||||
pParse->azVar = a;
|
||||
memset(&a[pParse->nzVar], 0, (x-pParse->nzVar)*sizeof(a[0]));
|
||||
pParse->nzVar = x;
|
||||
}
|
||||
if( pParse->azVar[x-1]==0 ){
|
||||
pParse->azVar[x-1] = sqlite3DbStrNDup(db, z, n);
|
||||
}
|
||||
}
|
||||
if( !pParse->nErr && pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
||||
if( pParse->nVar>db->aLimit[SQLITE_LIMIT_VARIABLE_NUMBER] ){
|
||||
sqlite3ErrorMsg(pParse, "too many SQL variables");
|
||||
}
|
||||
}
|
||||
@@ -1016,18 +1014,25 @@ static SQLITE_NOINLINE void sqlite3ExprDeleteNN(sqlite3 *db, Expr *p){
|
||||
assert( p!=0 );
|
||||
/* Sanity check: Assert that the IntValue is non-negative if it exists */
|
||||
assert( !ExprHasProperty(p, EP_IntValue) || p->u.iValue>=0 );
|
||||
if( !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
#ifdef SQLITE_DEBUG
|
||||
if( ExprHasProperty(p, EP_Leaf) && !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
assert( p->pLeft==0 );
|
||||
assert( p->pRight==0 );
|
||||
assert( p->x.pSelect==0 );
|
||||
}
|
||||
#endif
|
||||
if( !ExprHasProperty(p, (EP_TokenOnly|EP_Leaf)) ){
|
||||
/* The Expr.x union is never used at the same time as Expr.pRight */
|
||||
assert( p->x.pList==0 || p->pRight==0 );
|
||||
if( p->pLeft && p->op!=TK_SELECT_COLUMN ) sqlite3ExprDeleteNN(db, p->pLeft);
|
||||
sqlite3ExprDelete(db, p->pRight);
|
||||
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
sqlite3SelectDelete(db, p->x.pSelect);
|
||||
}else{
|
||||
sqlite3ExprListDelete(db, p->x.pList);
|
||||
}
|
||||
}
|
||||
if( ExprHasProperty(p, EP_MemToken) ) sqlite3DbFree(db, p->u.zToken);
|
||||
if( !ExprHasProperty(p, EP_Static) ){
|
||||
sqlite3DbFree(db, p);
|
||||
}
|
||||
@@ -1204,7 +1209,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
memcpy(zToken, p->u.zToken, nToken);
|
||||
}
|
||||
|
||||
if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){
|
||||
if( 0==((p->flags|pNew->flags) & (EP_TokenOnly|EP_Leaf)) ){
|
||||
/* Fill in the pNew->x.pSelect or pNew->x.pList member. */
|
||||
if( ExprHasProperty(p, EP_xIsSelect) ){
|
||||
pNew->x.pSelect = sqlite3SelectDup(db, p->x.pSelect, dupFlags);
|
||||
@@ -1216,7 +1221,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
/* Fill in pNew->pLeft and pNew->pRight. */
|
||||
if( ExprHasProperty(pNew, EP_Reduced|EP_TokenOnly) ){
|
||||
zAlloc += dupedExprNodeSize(p, dupFlags);
|
||||
if( ExprHasProperty(pNew, EP_Reduced) ){
|
||||
if( !ExprHasProperty(pNew, EP_TokenOnly|EP_Leaf) ){
|
||||
pNew->pLeft = p->pLeft ?
|
||||
exprDup(db, p->pLeft, EXPRDUP_REDUCE, &zAlloc) : 0;
|
||||
pNew->pRight = p->pRight ?
|
||||
@@ -1226,7 +1231,7 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int dupFlags, u8 **pzBuffer){
|
||||
*pzBuffer = zAlloc;
|
||||
}
|
||||
}else{
|
||||
if( !ExprHasProperty(p, EP_TokenOnly) ){
|
||||
if( !ExprHasProperty(p, EP_TokenOnly|EP_Leaf) ){
|
||||
if( pNew->op==TK_SELECT_COLUMN ){
|
||||
pNew->pLeft = p->pLeft;
|
||||
}else{
|
||||
@@ -1968,15 +1973,6 @@ static Select *isCandidateForInOpt(Expr *pX){
|
||||
}
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
/*
|
||||
** Code an OP_Once instruction and allocate space for its flag. Return the
|
||||
** address of the new instruction.
|
||||
*/
|
||||
int sqlite3CodeOnce(Parse *pParse){
|
||||
Vdbe *v = sqlite3GetVdbe(pParse); /* Virtual machine being coded */
|
||||
return sqlite3VdbeAddOp1(v, OP_Once, pParse->nOnce++);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
/*
|
||||
** Generate code that checks the left-most column of index table iCur to see if
|
||||
@@ -2150,7 +2146,7 @@ int sqlite3FindInIndex(
|
||||
assert(v); /* sqlite3GetVdbe() has always been previously called */
|
||||
if( nExpr==1 && pEList->a[0].pExpr->iColumn<0 ){
|
||||
/* The "x IN (SELECT rowid FROM table)" case */
|
||||
int iAddr = sqlite3CodeOnce(pParse);
|
||||
int iAddr = sqlite3VdbeAddOp0(v, OP_Once);
|
||||
VdbeCoverage(v);
|
||||
|
||||
sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
|
||||
@@ -2233,12 +2229,12 @@ int sqlite3FindInIndex(
|
||||
assert( i==nExpr || colUsed!=(MASKBIT(nExpr)-1) );
|
||||
if( colUsed==(MASKBIT(nExpr)-1) ){
|
||||
/* If we reach this point, that means the index pIdx is usable */
|
||||
int iAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
int iAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
sqlite3VdbeAddOp4(v, OP_Explain, 0, 0, 0,
|
||||
sqlite3MPrintf(db, "USING INDEX %s FOR IN-OPERATOR",pIdx->zName),
|
||||
P4_DYNAMIC);
|
||||
#endif
|
||||
#endif
|
||||
sqlite3VdbeAddOp3(v, OP_OpenRead, iTab, pIdx->tnum, iDb);
|
||||
sqlite3VdbeSetP4KeyInfo(pParse, pIdx);
|
||||
VdbeComment((v, "%s", pIdx->zName));
|
||||
@@ -2246,12 +2242,12 @@ int sqlite3FindInIndex(
|
||||
eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0];
|
||||
|
||||
if( prRhsHasNull ){
|
||||
*prRhsHasNull = ++pParse->nMem;
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
#ifdef SQLITE_ENABLE_COLUMN_USED_MASK
|
||||
i64 mask = (1<<nExpr)-1;
|
||||
sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed,
|
||||
iTab, 0, 0, (u8*)&mask, P4_INT64);
|
||||
#endif
|
||||
#endif
|
||||
*prRhsHasNull = ++pParse->nMem;
|
||||
if( nExpr==1 ){
|
||||
sqlite3SetHasNullFlag(v, iTab, *prRhsHasNull);
|
||||
}
|
||||
@@ -2408,7 +2404,7 @@ int sqlite3CodeSubselect(
|
||||
** save the results, and reuse the same result on subsequent invocations.
|
||||
*/
|
||||
if( !ExprHasProperty(pExpr, EP_VarSelect) ){
|
||||
jmpIfDynamic = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
jmpIfDynamic = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
@@ -2596,8 +2592,8 @@ int sqlite3CodeSubselect(
|
||||
VdbeComment((v, "Init EXISTS result"));
|
||||
}
|
||||
sqlite3ExprDelete(pParse->db, pSel->pLimit);
|
||||
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
|
||||
&sqlite3IntTokens[1]);
|
||||
pSel->pLimit = sqlite3ExprAlloc(pParse->db, TK_INTEGER,
|
||||
&sqlite3IntTokens[1], 0);
|
||||
pSel->iLimit = 0;
|
||||
pSel->selFlags &= ~SF_MultiValue;
|
||||
if( sqlite3Select(pParse, pSel, &dest) ){
|
||||
@@ -2966,32 +2962,19 @@ static void codeInteger(Parse *pParse, Expr *pExpr, int negFlag, int iMem){
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SQLITE_DEBUG)
|
||||
/*
|
||||
** Verify the consistency of the column cache
|
||||
** Erase column-cache entry number i
|
||||
*/
|
||||
static int cacheIsValid(Parse *pParse){
|
||||
int i, n;
|
||||
for(i=n=0; i<SQLITE_N_COLCACHE; i++){
|
||||
if( pParse->aColCache[i].iReg>0 ) n++;
|
||||
}
|
||||
return n==pParse->nColCache;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Clear a cache entry.
|
||||
*/
|
||||
static void cacheEntryClear(Parse *pParse, struct yColCache *p){
|
||||
if( p->tempReg ){
|
||||
static void cacheEntryClear(Parse *pParse, int i){
|
||||
if( pParse->aColCache[i].tempReg ){
|
||||
if( pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
||||
pParse->aTempReg[pParse->nTempReg++] = p->iReg;
|
||||
pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
|
||||
}
|
||||
p->tempReg = 0;
|
||||
}
|
||||
p->iReg = 0;
|
||||
pParse->nColCache--;
|
||||
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
|
||||
if( i<pParse->nColCache ){
|
||||
pParse->aColCache[i] = pParse->aColCache[pParse->nColCache];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3021,46 +3004,33 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
** that the object will never already be in cache. Verify this guarantee.
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
assert( p->iReg==0 || p->iTable!=iTab || p->iColumn!=iCol );
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
assert( p->iTable!=iTab || p->iColumn!=iCol );
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Find an empty slot and replace it */
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg==0 ){
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
pParse->nColCache++;
|
||||
assert( pParse->db->mallocFailed || cacheIsValid(pParse) );
|
||||
return;
|
||||
/* If the cache is already full, delete the least recently used entry */
|
||||
if( pParse->nColCache>=SQLITE_N_COLCACHE ){
|
||||
minLru = 0x7fffffff;
|
||||
idxLru = -1;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->lru<minLru ){
|
||||
idxLru = i;
|
||||
minLru = p->lru;
|
||||
}
|
||||
}
|
||||
p = &pParse->aColCache[idxLru];
|
||||
}else{
|
||||
p = &pParse->aColCache[pParse->nColCache++];
|
||||
}
|
||||
|
||||
/* Replace the last recently used */
|
||||
minLru = 0x7fffffff;
|
||||
idxLru = -1;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->lru<minLru ){
|
||||
idxLru = i;
|
||||
minLru = p->lru;
|
||||
}
|
||||
}
|
||||
if( ALWAYS(idxLru>=0) ){
|
||||
p = &pParse->aColCache[idxLru];
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
assert( cacheIsValid(pParse) );
|
||||
return;
|
||||
}
|
||||
/* Add the new entry to the end of the cache */
|
||||
p->iLevel = pParse->iCacheLevel;
|
||||
p->iTable = iTab;
|
||||
p->iColumn = iCol;
|
||||
p->iReg = iReg;
|
||||
p->tempReg = 0;
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3068,13 +3038,14 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
|
||||
** Purge the range of registers from the column cache.
|
||||
*/
|
||||
void sqlite3ExprCacheRemove(Parse *pParse, int iReg, int nReg){
|
||||
struct yColCache *p;
|
||||
if( iReg<=0 || pParse->nColCache==0 ) return;
|
||||
p = &pParse->aColCache[SQLITE_N_COLCACHE-1];
|
||||
while(1){
|
||||
if( p->iReg >= iReg && p->iReg < iReg+nReg ) cacheEntryClear(pParse, p);
|
||||
if( p==pParse->aColCache ) break;
|
||||
p--;
|
||||
int i = 0;
|
||||
while( i<pParse->nColCache ){
|
||||
struct yColCache *p = &pParse->aColCache[i];
|
||||
if( p->iReg >= iReg && p->iReg < iReg+nReg ){
|
||||
cacheEntryClear(pParse, i);
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3098,8 +3069,7 @@ void sqlite3ExprCachePush(Parse *pParse){
|
||||
** the cache to the state it was in prior the most recent Push.
|
||||
*/
|
||||
void sqlite3ExprCachePop(Parse *pParse){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
int i = 0;
|
||||
assert( pParse->iCacheLevel>=1 );
|
||||
pParse->iCacheLevel--;
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -3107,9 +3077,11 @@ void sqlite3ExprCachePop(Parse *pParse){
|
||||
printf("POP to %d\n", pParse->iCacheLevel);
|
||||
}
|
||||
#endif
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg && p->iLevel>pParse->iCacheLevel ){
|
||||
cacheEntryClear(pParse, p);
|
||||
while( i<pParse->nColCache ){
|
||||
if( pParse->aColCache[i].iLevel>pParse->iCacheLevel ){
|
||||
cacheEntryClear(pParse, i);
|
||||
}else{
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3123,7 +3095,7 @@ void sqlite3ExprCachePop(Parse *pParse){
|
||||
static void sqlite3ExprCachePinRegister(Parse *pParse, int iReg){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
if( p->iReg==iReg ){
|
||||
p->tempReg = 0;
|
||||
}
|
||||
@@ -3201,8 +3173,8 @@ int sqlite3ExprCodeGetColumn(
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn ){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
if( p->iTable==iTable && p->iColumn==iColumn ){
|
||||
p->lru = pParse->iCacheCnt++;
|
||||
sqlite3ExprCachePinRegister(pParse, p->iReg);
|
||||
return p->iReg;
|
||||
@@ -3234,18 +3206,20 @@ void sqlite3ExprCodeGetColumnToReg(
|
||||
*/
|
||||
void sqlite3ExprCacheClear(Parse *pParse){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
|
||||
#if SQLITE_DEBUG
|
||||
if( pParse->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
printf("CLEAR\n");
|
||||
}
|
||||
#endif
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
if( p->iReg ){
|
||||
cacheEntryClear(pParse, p);
|
||||
for(i=0; i<pParse->nColCache; i++){
|
||||
if( pParse->aColCache[i].tempReg
|
||||
&& pParse->nTempReg<ArraySize(pParse->aTempReg)
|
||||
){
|
||||
pParse->aTempReg[pParse->nTempReg++] = pParse->aColCache[i].iReg;
|
||||
}
|
||||
}
|
||||
pParse->nColCache = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3277,7 +3251,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
|
||||
static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
int r = p->iReg;
|
||||
if( r>=iFrom && r<=iTo ) return 1; /*NO_TEST*/
|
||||
}
|
||||
@@ -3348,7 +3322,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
int regFree1 = 0; /* If non-zero free this temporary register */
|
||||
int regFree2 = 0; /* If non-zero free this temporary register */
|
||||
int r1, r2; /* Various register numbers */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
Expr tempX; /* Temporary expression node */
|
||||
int p5 = 0;
|
||||
|
||||
@@ -3369,12 +3342,11 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
|
||||
if( !pAggInfo->directMode ){
|
||||
assert( pCol->iMem>0 );
|
||||
inReg = pCol->iMem;
|
||||
break;
|
||||
return pCol->iMem;
|
||||
}else if( pAggInfo->useSortingIdx ){
|
||||
sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab,
|
||||
pCol->iSorterColumn, target);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
/* Otherwise, fall thru into the TK_COLUMN case */
|
||||
}
|
||||
@@ -3383,38 +3355,36 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
if( iTab<0 ){
|
||||
if( pParse->ckBase>0 ){
|
||||
/* Generating CHECK constraints or inserting into partial index */
|
||||
inReg = pExpr->iColumn + pParse->ckBase;
|
||||
break;
|
||||
return pExpr->iColumn + pParse->ckBase;
|
||||
}else{
|
||||
/* Coding an expression that is part of an index where column names
|
||||
** in the index refer to the table to which the index belongs */
|
||||
iTab = pParse->iSelfTab;
|
||||
}
|
||||
}
|
||||
inReg = sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
||||
return sqlite3ExprCodeGetColumn(pParse, pExpr->pTab,
|
||||
pExpr->iColumn, iTab, target,
|
||||
pExpr->op2);
|
||||
break;
|
||||
}
|
||||
case TK_INTEGER: {
|
||||
codeInteger(pParse, pExpr, 0, target);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
case TK_FLOAT: {
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
codeReal(v, pExpr->u.zToken, 0, target);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
#endif
|
||||
case TK_STRING: {
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
sqlite3VdbeLoadString(v, target, pExpr->u.zToken);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
case TK_NULL: {
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_BLOB_LITERAL
|
||||
case TK_BLOB: {
|
||||
@@ -3429,7 +3399,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( z[n]=='\'' );
|
||||
zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n);
|
||||
sqlite3VdbeAddOp4(v, OP_Blob, n/2, target, 0, zBlob, P4_DYNAMIC);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
#endif
|
||||
case TK_VARIABLE: {
|
||||
@@ -3442,11 +3412,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
|| strcmp(pExpr->u.zToken, pParse->azVar[pExpr->iColumn-1])==0 );
|
||||
sqlite3VdbeChangeP4(v, -1, pParse->azVar[pExpr->iColumn-1], P4_STATIC);
|
||||
}
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
case TK_REGISTER: {
|
||||
inReg = pExpr->iTable;
|
||||
break;
|
||||
return pExpr->iTable;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_CAST
|
||||
case TK_CAST: {
|
||||
@@ -3460,7 +3429,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3AffinityType(pExpr->u.zToken, 0));
|
||||
testcase( usedAsColumnCache(pParse, inReg, inReg) );
|
||||
sqlite3ExprCacheAffinityChange(pParse, inReg, 1);
|
||||
break;
|
||||
return inReg;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_CAST */
|
||||
case TK_IS:
|
||||
@@ -3528,10 +3497,12 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( pLeft );
|
||||
if( pLeft->op==TK_INTEGER ){
|
||||
codeInteger(pParse, pLeft, 1, target);
|
||||
return target;
|
||||
#ifndef SQLITE_OMIT_FLOATING_POINT
|
||||
}else if( pLeft->op==TK_FLOAT ){
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
codeReal(v, pLeft->u.zToken, 1, target);
|
||||
return target;
|
||||
#endif
|
||||
}else{
|
||||
tempX.op = TK_INTEGER;
|
||||
@@ -3542,7 +3513,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
|
||||
testcase( regFree2==0 );
|
||||
}
|
||||
inReg = target;
|
||||
break;
|
||||
}
|
||||
case TK_BITNOT:
|
||||
@@ -3551,7 +3521,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( TK_NOT==OP_Not ); testcase( op==TK_NOT );
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1);
|
||||
testcase( regFree1==0 );
|
||||
inReg = target;
|
||||
sqlite3VdbeAddOp2(v, op, r1, inReg);
|
||||
break;
|
||||
}
|
||||
@@ -3576,7 +3545,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
assert( !ExprHasProperty(pExpr, EP_IntValue) );
|
||||
sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken);
|
||||
}else{
|
||||
inReg = pInfo->aFunc[pExpr->iAgg].iMem;
|
||||
return pInfo->aFunc[pExpr->iAgg].iMem;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3587,6 +3556,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
const char *zId; /* The function name */
|
||||
u32 constMask = 0; /* Mask of function arguments that are constant */
|
||||
int i; /* Loop counter */
|
||||
sqlite3 *db = pParse->db; /* The database connection */
|
||||
u8 enc = ENC(db); /* The text encoding used by this database */
|
||||
CollSeq *pColl = 0; /* A collating sequence */
|
||||
|
||||
@@ -3635,8 +3605,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
*/
|
||||
if( pDef->funcFlags & SQLITE_FUNC_UNLIKELY ){
|
||||
assert( nFarg>=1 );
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
|
||||
break;
|
||||
return sqlite3ExprCodeTarget(pParse, pFarg->a[0].pExpr, target);
|
||||
}
|
||||
|
||||
for(i=0; i<nFarg; i++){
|
||||
@@ -3711,7 +3680,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
if( nFarg && constMask==0 ){
|
||||
sqlite3ReleaseTempRange(pParse, r1, nFarg);
|
||||
}
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
case TK_EXISTS:
|
||||
@@ -3722,7 +3691,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
if( op==TK_SELECT && (nCol = pExpr->x.pSelect->pEList->nExpr)!=1 ){
|
||||
sqlite3SubselectError(pParse, nCol, 1);
|
||||
}else{
|
||||
inReg = sqlite3CodeSubselect(pParse, pExpr, 0, 0);
|
||||
return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3730,8 +3699,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
if( pExpr->pLeft->iTable==0 ){
|
||||
pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
|
||||
}
|
||||
inReg = pExpr->pLeft->iTable + pExpr->iColumn;
|
||||
break;
|
||||
return pExpr->pLeft->iTable + pExpr->iColumn;
|
||||
}
|
||||
case TK_IN: {
|
||||
int destIfFalse = sqlite3VdbeMakeLabel(v);
|
||||
@@ -3742,7 +3710,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
sqlite3VdbeResolveLabel(v, destIfFalse);
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, target, 0);
|
||||
sqlite3VdbeResolveLabel(v, destIfNull);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_SUBQUERY */
|
||||
|
||||
@@ -3760,13 +3728,12 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
*/
|
||||
case TK_BETWEEN: {
|
||||
exprCodeBetween(pParse, pExpr, target, 0, 0);
|
||||
break;
|
||||
return target;
|
||||
}
|
||||
case TK_SPAN:
|
||||
case TK_COLLATE:
|
||||
case TK_UPLUS: {
|
||||
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||
break;
|
||||
return sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||
}
|
||||
|
||||
case TK_TRIGGER: {
|
||||
@@ -3908,7 +3875,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
}else{
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, target);
|
||||
}
|
||||
assert( db->mallocFailed || pParse->nErr>0
|
||||
assert( pParse->db->mallocFailed || pParse->nErr>0
|
||||
|| pParse->iCacheLevel==iCacheLevel );
|
||||
sqlite3VdbeResolveLabel(v, endLabel);
|
||||
break;
|
||||
@@ -4980,7 +4947,7 @@ void sqlite3ReleaseTempReg(Parse *pParse, int iReg){
|
||||
if( iReg && pParse->nTempReg<ArraySize(pParse->aTempReg) ){
|
||||
int i;
|
||||
struct yColCache *p;
|
||||
for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
|
||||
for(i=0, p=pParse->aColCache; i<pParse->nColCache; i++, p++){
|
||||
if( p->iReg==iReg ){
|
||||
p->tempReg = 1;
|
||||
return;
|
||||
|
||||
+2
-2
@@ -1242,10 +1242,10 @@ static Trigger *fkActionTrigger(
|
||||
if( pDflt ){
|
||||
pNew = sqlite3ExprDup(db, pDflt, 0);
|
||||
}else{
|
||||
pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
|
||||
pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
|
||||
}
|
||||
}else{
|
||||
pNew = sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
|
||||
pNew = sqlite3ExprAlloc(db, TK_NULL, 0, 0);
|
||||
}
|
||||
pList = sqlite3ExprListAppend(pParse, pList, pNew);
|
||||
sqlite3ExprListSetName(pParse, pList, &tFromCol, 0);
|
||||
|
||||
+6
-8
@@ -79,16 +79,13 @@ const unsigned char sqlite3UpperToLower[] = {
|
||||
**
|
||||
** (x & ~(map[x]&0x20))
|
||||
**
|
||||
** Standard function tolower() is implemented using the sqlite3UpperToLower[]
|
||||
** The equivalent of tolower() is implemented using the sqlite3UpperToLower[]
|
||||
** array. tolower() is used more often than toupper() by SQLite.
|
||||
**
|
||||
** Bit 0x40 is set if the character non-alphanumeric and can be used in an
|
||||
** Bit 0x40 is set if the character is non-alphanumeric and can be used in an
|
||||
** SQLite identifier. Identifiers are alphanumerics, "_", "$", and any
|
||||
** non-ASCII UTF character. Hence the test for whether or not a character is
|
||||
** part of an identifier is 0x46.
|
||||
**
|
||||
** SQLite's versions are identical to the standard versions assuming a
|
||||
** locale of "C". They are implemented as macros in sqliteInt.h.
|
||||
*/
|
||||
#ifdef SQLITE_ASCII
|
||||
const unsigned char sqlite3CtypeMap[256] = {
|
||||
@@ -161,7 +158,7 @@ const unsigned char sqlite3CtypeMap[256] = {
|
||||
#endif
|
||||
|
||||
/* Statement journals spill to disk when their size exceeds the following
|
||||
** threashold (in bytes). 0 means that statement journals are created and
|
||||
** threshold (in bytes). 0 means that statement journals are created and
|
||||
** written to disk immediately (the default behavior for SQLite versions
|
||||
** before 3.12.0). -1 means always keep the entire statement journal in
|
||||
** memory. (The statement journal is also always held entirely in memory
|
||||
@@ -225,7 +222,8 @@ SQLITE_WSD struct Sqlite3Config sqlite3Config = {
|
||||
#ifndef SQLITE_OMIT_BUILTIN_TEST
|
||||
0, /* xTestCallback */
|
||||
#endif
|
||||
0 /* bLocaltimeFault */
|
||||
0, /* bLocaltimeFault */
|
||||
0x7ffffffe /* iOnceResetThreshold */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -248,7 +246,7 @@ const Token sqlite3IntTokens[] = {
|
||||
** The value of the "pending" byte must be 0x40000000 (1 byte past the
|
||||
** 1-gibabyte boundary) in a compatible database. SQLite never uses
|
||||
** the database page that contains the pending byte. It never attempts
|
||||
** to read or write that page. The pending byte page is set assign
|
||||
** to read or write that page. The pending byte page is set aside
|
||||
** for use by the VFS layers as space for managing file locks.
|
||||
**
|
||||
** During testing, it is often desirable to move the pending byte to
|
||||
|
||||
+5
-1
@@ -56,7 +56,11 @@ static unsigned int strHash(const char *z){
|
||||
unsigned int h = 0;
|
||||
unsigned char c;
|
||||
while( (c = (unsigned char)*z++)!=0 ){ /*OPTIMIZATION-IF-TRUE*/
|
||||
h = (h<<3) ^ h ^ sqlite3UpperToLower[c];
|
||||
/* Knuth multiplicative hashing. (Sorting & Searching, p. 510).
|
||||
** 0x9e3779b1 is 2654435761 which is the closest prime number to
|
||||
** (2**32)*golden_ratio, where golden_ratio = (sqrt(5) - 1)/2. */
|
||||
h += sqlite3UpperToLower[c];
|
||||
h *= 0x9e3779b1;
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
+3
-5
@@ -485,7 +485,6 @@ void sqlite3Insert(
|
||||
sqlite3 *db; /* The main database structure */
|
||||
Table *pTab; /* The table to insert into. aka TABLE */
|
||||
char *zTab; /* Name of the table into which we are inserting */
|
||||
const char *zDb; /* Name of the database holding this table */
|
||||
int i, j, idx; /* Loop counters */
|
||||
Vdbe *v; /* Generate code into this virtual machine */
|
||||
Index *pIdx; /* For looping over indices of the table */
|
||||
@@ -500,7 +499,6 @@ void sqlite3Insert(
|
||||
int addrCont = 0; /* Top of insert loop. Label "C" in templates 3 and 4 */
|
||||
SelectDest dest; /* Destination for SELECT on rhs of INSERT */
|
||||
int iDb; /* Index of database holding TABLE */
|
||||
Db *pDb; /* The database containing table being inserted into */
|
||||
u8 useTempTable = 0; /* Store SELECT results in intermediate table */
|
||||
u8 appendFlag = 0; /* True if the insert is likely to be an append */
|
||||
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
|
||||
@@ -550,9 +548,8 @@ void sqlite3Insert(
|
||||
}
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb<db->nDb );
|
||||
pDb = &db->aDb[iDb];
|
||||
zDb = pDb->zDbSName;
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0,
|
||||
db->aDb[iDb].zDbSName) ){
|
||||
goto insert_cleanup;
|
||||
}
|
||||
withoutRowid = !HasRowid(pTab);
|
||||
@@ -2180,6 +2177,7 @@ static int xferOptimization(
|
||||
sqlite3ReleaseTempReg(pParse, regRowid);
|
||||
sqlite3ReleaseTempReg(pParse, regData);
|
||||
if( emptyDestTest ){
|
||||
sqlite3AutoincrementEnd(pParse);
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, SQLITE_OK, 0);
|
||||
sqlite3VdbeJumpHere(v, emptyDestTest);
|
||||
sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
|
||||
|
||||
+7
-13
@@ -620,18 +620,7 @@ int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#endif /* SQLITE_OMIT_LOAD_EXTENSION */
|
||||
|
||||
/*
|
||||
** The auto-extension code added regardless of whether or not extension
|
||||
** loading is supported. We need a dummy sqlite3Apis pointer for that
|
||||
** code if regular extension loading is not available. This is that
|
||||
** dummy pointer.
|
||||
*/
|
||||
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
||||
static const sqlite3_api_routines sqlite3Apis = { 0 };
|
||||
#endif
|
||||
|
||||
#endif /* !defined(SQLITE_OMIT_LOAD_EXTENSION) */
|
||||
|
||||
/*
|
||||
** The following object holds the list of automatically loaded
|
||||
@@ -775,6 +764,11 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){
|
||||
char *zErrmsg;
|
||||
#if SQLITE_THREADSAFE
|
||||
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
|
||||
#endif
|
||||
#ifdef SQLITE_OMIT_LOAD_EXTENSION
|
||||
const sqlite3_api_routines *pThunk = 0;
|
||||
#else
|
||||
const sqlite3_api_routines *pThunk = &sqlite3Apis;
|
||||
#endif
|
||||
sqlite3_mutex_enter(mutex);
|
||||
if( i>=wsdAutoext.nExt ){
|
||||
@@ -785,7 +779,7 @@ void sqlite3AutoLoadExtensions(sqlite3 *db){
|
||||
}
|
||||
sqlite3_mutex_leave(mutex);
|
||||
zErrmsg = 0;
|
||||
if( xInit && (rc = xInit(db, &zErrmsg, &sqlite3Apis))!=0 ){
|
||||
if( xInit && (rc = xInit(db, &zErrmsg, pThunk))!=0 ){
|
||||
sqlite3ErrorWithMsg(db, rc,
|
||||
"automatic extension loading failed: %s", zErrmsg);
|
||||
go = 0;
|
||||
|
||||
@@ -3784,6 +3784,15 @@ int sqlite3_test_control(int op, ...){
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the threshold at which OP_Once counters reset back to zero.
|
||||
** By default this is 0x7ffffffe (over 2 billion), but that value is
|
||||
** too big to test in a reasonable amount of time, so this control is
|
||||
** provided to set a small and easily reachable reset value.
|
||||
*/
|
||||
case SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD: {
|
||||
sqlite3GlobalConfig.iOnceResetThreshold = va_arg(ap, int);
|
||||
break;
|
||||
}
|
||||
|
||||
/* sqlite3_test_control(SQLITE_TESTCTRL_VDBE_COVERAGE, xCallback, ptr);
|
||||
**
|
||||
|
||||
+47
-33
@@ -80,15 +80,6 @@ struct LimitVal {
|
||||
Expr *pOffset; /* The OFFSET expression. NULL if there is none */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of this structure is used to store the LIKE,
|
||||
** GLOB, NOT LIKE, and NOT GLOB operators.
|
||||
*/
|
||||
struct LikeOp {
|
||||
Token eOperator; /* "like" or "glob" or "regexp" */
|
||||
int bNot; /* True if the NOT keyword is present */
|
||||
};
|
||||
|
||||
/*
|
||||
** An instance of the following structure describes the event of a
|
||||
** TRIGGER. "a" is the event type, one of TK_UPDATE, TK_INSERT,
|
||||
@@ -100,11 +91,6 @@ struct LikeOp {
|
||||
*/
|
||||
struct TrigEvent { int a; IdList * b; };
|
||||
|
||||
/*
|
||||
** An instance of this structure holds the ATTACH key and the key type.
|
||||
*/
|
||||
struct AttachKey { int type; Token key; };
|
||||
|
||||
/*
|
||||
** Disable lookaside memory allocation for objects that might be
|
||||
** shared across database connections.
|
||||
@@ -556,8 +542,8 @@ selcollist(A) ::= sclp(A) STAR. {
|
||||
Expr *p = sqlite3Expr(pParse->db, TK_ASTERISK, 0);
|
||||
A = sqlite3ExprListAppend(pParse, A, p);
|
||||
}
|
||||
selcollist(A) ::= sclp(A) nm(X) DOT STAR(Y). {
|
||||
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, &Y);
|
||||
selcollist(A) ::= sclp(A) nm(X) DOT STAR. {
|
||||
Expr *pRight = sqlite3PExpr(pParse, TK_ASTERISK, 0, 0, 0);
|
||||
Expr *pLeft = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||
Expr *pDot = sqlite3PExpr(pParse, TK_DOT, pLeft, pRight, 0);
|
||||
A = sqlite3ExprListAppend(pParse,A, pDot);
|
||||
@@ -851,7 +837,24 @@ idlist(A) ::= nm(Y).
|
||||
** that created the expression.
|
||||
*/
|
||||
static void spanExpr(ExprSpan *pOut, Parse *pParse, int op, Token t){
|
||||
pOut->pExpr = sqlite3PExpr(pParse, op, 0, 0, &t);
|
||||
Expr *p = sqlite3DbMallocRawNN(pParse->db, sizeof(Expr)+t.n+1);
|
||||
if( p ){
|
||||
memset(p, 0, sizeof(Expr));
|
||||
p->op = (u8)op;
|
||||
p->flags = EP_Leaf;
|
||||
p->iAgg = -1;
|
||||
p->u.zToken = (char*)&p[1];
|
||||
memcpy(p->u.zToken, t.z, t.n);
|
||||
p->u.zToken[t.n] = 0;
|
||||
if( sqlite3Isquote(p->u.zToken[0]) ){
|
||||
if( p->u.zToken[0]=='"' ) p->flags |= EP_DblQuoted;
|
||||
sqlite3Dequote(p->u.zToken);
|
||||
}
|
||||
#if SQLITE_MAX_EXPR_DEPTH>0
|
||||
p->nHeight = 1;
|
||||
#endif
|
||||
}
|
||||
pOut->pExpr = p;
|
||||
pOut->zStart = t.z;
|
||||
pOut->zEnd = &t.z[t.n];
|
||||
}
|
||||
@@ -864,25 +867,32 @@ term(A) ::= NULL(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
|
||||
expr(A) ::= id(X). {spanExpr(&A,pParse,TK_ID,X); /*A-overwrites-X*/}
|
||||
expr(A) ::= JOIN_KW(X). {spanExpr(&A,pParse,TK_ID,X); /*A-overwrites-X*/}
|
||||
expr(A) ::= nm(X) DOT nm(Y). {
|
||||
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
|
||||
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
|
||||
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
|
||||
spanSet(&A,&X,&Y); /*A-overwrites-X*/
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp2, 0);
|
||||
}
|
||||
expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). {
|
||||
Expr *temp1 = sqlite3PExpr(pParse, TK_ID, 0, 0, &X);
|
||||
Expr *temp2 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Y);
|
||||
Expr *temp3 = sqlite3PExpr(pParse, TK_ID, 0, 0, &Z);
|
||||
Expr *temp1 = sqlite3ExprAlloc(pParse->db, TK_ID, &X, 1);
|
||||
Expr *temp2 = sqlite3ExprAlloc(pParse->db, TK_ID, &Y, 1);
|
||||
Expr *temp3 = sqlite3ExprAlloc(pParse->db, TK_ID, &Z, 1);
|
||||
Expr *temp4 = sqlite3PExpr(pParse, TK_DOT, temp2, temp3, 0);
|
||||
spanSet(&A,&X,&Z); /*A-overwrites-X*/
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_DOT, temp1, temp4, 0);
|
||||
}
|
||||
term(A) ::= INTEGER|FLOAT|BLOB(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
|
||||
term(A) ::= STRING(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
|
||||
term(A) ::= FLOAT|BLOB(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
|
||||
term(A) ::= STRING(X). {spanExpr(&A,pParse,@X,X);/*A-overwrites-X*/}
|
||||
term(A) ::= INTEGER(X). {
|
||||
A.pExpr = sqlite3ExprAlloc(pParse->db, TK_INTEGER, &X, 1);
|
||||
A.zStart = X.z;
|
||||
A.zEnd = X.z + X.n;
|
||||
if( A.pExpr ) A.pExpr->flags |= EP_Leaf;
|
||||
}
|
||||
expr(A) ::= VARIABLE(X). {
|
||||
if( !(X.z[0]=='#' && sqlite3Isdigit(X.z[1])) ){
|
||||
u32 n = X.n;
|
||||
spanExpr(&A, pParse, TK_VARIABLE, X);
|
||||
sqlite3ExprAssignVarNumber(pParse, A.pExpr);
|
||||
sqlite3ExprAssignVarNumber(pParse, A.pExpr, n);
|
||||
}else{
|
||||
/* When doing a nested parse, one can include terms in an expression
|
||||
** that look like this: #1 #2 ... These terms refer to registers
|
||||
@@ -894,7 +904,7 @@ expr(A) ::= VARIABLE(X). {
|
||||
sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", &t);
|
||||
A.pExpr = 0;
|
||||
}else{
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, &t);
|
||||
A.pExpr = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, 0);
|
||||
if( A.pExpr ) sqlite3GetInt32(&t.z[1], &A.pExpr->iTable);
|
||||
}
|
||||
}
|
||||
@@ -975,25 +985,29 @@ expr(A) ::= expr(A) PLUS|MINUS(OP) expr(Y).
|
||||
expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y).
|
||||
{spanBinaryExpr(pParse,@OP,&A,&Y);}
|
||||
expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);}
|
||||
%type likeop {struct LikeOp}
|
||||
likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;/*A-overwrites-X*/}
|
||||
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;}
|
||||
%type likeop {Token}
|
||||
likeop(A) ::= LIKE_KW|MATCH(X). {A=X;/*A-overwrites-X*/}
|
||||
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A=X; A.n|=0x80000000; /*A-overwrite-X*/}
|
||||
expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] {
|
||||
ExprList *pList;
|
||||
int bNot = OP.n & 0x80000000;
|
||||
OP.n &= 0x7fffffff;
|
||||
pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
|
||||
pList = sqlite3ExprListAppend(pParse,pList, A.pExpr);
|
||||
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
|
||||
exprNot(pParse, OP.bNot, &A);
|
||||
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP);
|
||||
exprNot(pParse, bNot, &A);
|
||||
A.zEnd = Y.zEnd;
|
||||
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
|
||||
}
|
||||
expr(A) ::= expr(A) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] {
|
||||
ExprList *pList;
|
||||
int bNot = OP.n & 0x80000000;
|
||||
OP.n &= 0x7fffffff;
|
||||
pList = sqlite3ExprListAppend(pParse,0, Y.pExpr);
|
||||
pList = sqlite3ExprListAppend(pParse,pList, A.pExpr);
|
||||
pList = sqlite3ExprListAppend(pParse,pList, E.pExpr);
|
||||
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator);
|
||||
exprNot(pParse, OP.bNot, &A);
|
||||
A.pExpr = sqlite3ExprFunction(pParse, pList, &OP);
|
||||
exprNot(pParse, bNot, &A);
|
||||
A.zEnd = E.zEnd;
|
||||
if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc;
|
||||
}
|
||||
|
||||
+1
-1
@@ -461,7 +461,7 @@ static SQLITE_NOINLINE PgHdr *pcacheFetchFinishWithInit(
|
||||
assert( pPage!=0 );
|
||||
pPgHdr = (PgHdr*)pPage->pExtra;
|
||||
assert( pPgHdr->pPage==0 );
|
||||
memset(pPgHdr, 0, sizeof(PgHdr));
|
||||
memset(&pPgHdr->pDirty, 0, sizeof(PgHdr) - offsetof(PgHdr,pDirty));
|
||||
pPgHdr->pPage = pPage;
|
||||
pPgHdr->pData = pPage->pBuf;
|
||||
pPgHdr->pExtra = (void *)&pPgHdr[1];
|
||||
|
||||
+1
-1
@@ -279,7 +279,7 @@ static int pcache1InitBulk(PCache1 *pCache){
|
||||
szBulk = -1024 * (i64)pcache1.nInitPage;
|
||||
}
|
||||
if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
|
||||
szBulk = pCache->szAlloc*pCache->nMax;
|
||||
szBulk = pCache->szAlloc*(i64)pCache->nMax;
|
||||
}
|
||||
zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
|
||||
sqlite3EndBenignMalloc();
|
||||
|
||||
+30
-36
@@ -518,18 +518,14 @@ static int sqlite3Prepare(
|
||||
sqlite3_stmt **ppStmt, /* OUT: A pointer to the prepared statement */
|
||||
const char **pzTail /* OUT: End of parsed string */
|
||||
){
|
||||
Parse *pParse; /* Parsing context */
|
||||
char *zErrMsg = 0; /* Error message */
|
||||
int rc = SQLITE_OK; /* Result code */
|
||||
int i; /* Loop counter */
|
||||
Parse sParse; /* Parsing context */
|
||||
|
||||
/* Allocate the parsing context */
|
||||
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
|
||||
if( pParse==0 ){
|
||||
rc = SQLITE_NOMEM_BKPT;
|
||||
goto end_prepare;
|
||||
}
|
||||
pParse->pReprepare = pReprepare;
|
||||
memset(&sParse, 0, PARSE_HDR_SZ);
|
||||
memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ);
|
||||
sParse.pReprepare = pReprepare;
|
||||
assert( ppStmt && *ppStmt==0 );
|
||||
/* assert( !db->mallocFailed ); // not true with SQLITE_USE_ALLOCA */
|
||||
assert( sqlite3_mutex_held(db->mutex) );
|
||||
@@ -573,8 +569,7 @@ static int sqlite3Prepare(
|
||||
|
||||
sqlite3VtabUnlockList(db);
|
||||
|
||||
pParse->db = db;
|
||||
pParse->nQueryLoop = 0; /* Logarithmic, so 0 really means 1 */
|
||||
sParse.db = db;
|
||||
if( nBytes>=0 && (nBytes==0 || zSql[nBytes-1]!=0) ){
|
||||
char *zSqlCopy;
|
||||
int mxLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
|
||||
@@ -587,61 +582,61 @@ static int sqlite3Prepare(
|
||||
}
|
||||
zSqlCopy = sqlite3DbStrNDup(db, zSql, nBytes);
|
||||
if( zSqlCopy ){
|
||||
sqlite3RunParser(pParse, zSqlCopy, &zErrMsg);
|
||||
pParse->zTail = &zSql[pParse->zTail-zSqlCopy];
|
||||
sqlite3RunParser(&sParse, zSqlCopy, &zErrMsg);
|
||||
sParse.zTail = &zSql[sParse.zTail-zSqlCopy];
|
||||
sqlite3DbFree(db, zSqlCopy);
|
||||
}else{
|
||||
pParse->zTail = &zSql[nBytes];
|
||||
sParse.zTail = &zSql[nBytes];
|
||||
}
|
||||
}else{
|
||||
sqlite3RunParser(pParse, zSql, &zErrMsg);
|
||||
sqlite3RunParser(&sParse, zSql, &zErrMsg);
|
||||
}
|
||||
assert( 0==pParse->nQueryLoop );
|
||||
assert( 0==sParse.nQueryLoop );
|
||||
|
||||
if( pParse->rc==SQLITE_DONE ) pParse->rc = SQLITE_OK;
|
||||
if( pParse->checkSchema ){
|
||||
schemaIsValid(pParse);
|
||||
if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
|
||||
if( sParse.checkSchema ){
|
||||
schemaIsValid(&sParse);
|
||||
}
|
||||
if( db->mallocFailed ){
|
||||
pParse->rc = SQLITE_NOMEM_BKPT;
|
||||
sParse.rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
if( pzTail ){
|
||||
*pzTail = pParse->zTail;
|
||||
*pzTail = sParse.zTail;
|
||||
}
|
||||
rc = pParse->rc;
|
||||
rc = sParse.rc;
|
||||
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
if( rc==SQLITE_OK && pParse->pVdbe && pParse->explain ){
|
||||
if( rc==SQLITE_OK && sParse.pVdbe && sParse.explain ){
|
||||
static const char * const azColName[] = {
|
||||
"addr", "opcode", "p1", "p2", "p3", "p4", "p5", "comment",
|
||||
"selectid", "order", "from", "detail"
|
||||
};
|
||||
int iFirst, mx;
|
||||
if( pParse->explain==2 ){
|
||||
sqlite3VdbeSetNumCols(pParse->pVdbe, 4);
|
||||
if( sParse.explain==2 ){
|
||||
sqlite3VdbeSetNumCols(sParse.pVdbe, 4);
|
||||
iFirst = 8;
|
||||
mx = 12;
|
||||
}else{
|
||||
sqlite3VdbeSetNumCols(pParse->pVdbe, 8);
|
||||
sqlite3VdbeSetNumCols(sParse.pVdbe, 8);
|
||||
iFirst = 0;
|
||||
mx = 8;
|
||||
}
|
||||
for(i=iFirst; i<mx; i++){
|
||||
sqlite3VdbeSetColName(pParse->pVdbe, i-iFirst, COLNAME_NAME,
|
||||
sqlite3VdbeSetColName(sParse.pVdbe, i-iFirst, COLNAME_NAME,
|
||||
azColName[i], SQLITE_STATIC);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if( db->init.busy==0 ){
|
||||
Vdbe *pVdbe = pParse->pVdbe;
|
||||
sqlite3VdbeSetSql(pVdbe, zSql, (int)(pParse->zTail-zSql), saveSqlFlag);
|
||||
Vdbe *pVdbe = sParse.pVdbe;
|
||||
sqlite3VdbeSetSql(pVdbe, zSql, (int)(sParse.zTail-zSql), saveSqlFlag);
|
||||
}
|
||||
if( pParse->pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
|
||||
sqlite3VdbeFinalize(pParse->pVdbe);
|
||||
if( sParse.pVdbe && (rc!=SQLITE_OK || db->mallocFailed) ){
|
||||
sqlite3VdbeFinalize(sParse.pVdbe);
|
||||
assert(!(*ppStmt));
|
||||
}else{
|
||||
*ppStmt = (sqlite3_stmt*)pParse->pVdbe;
|
||||
*ppStmt = (sqlite3_stmt*)sParse.pVdbe;
|
||||
}
|
||||
|
||||
if( zErrMsg ){
|
||||
@@ -652,16 +647,15 @@ static int sqlite3Prepare(
|
||||
}
|
||||
|
||||
/* Delete any TriggerPrg structures allocated while parsing this statement. */
|
||||
while( pParse->pTriggerPrg ){
|
||||
TriggerPrg *pT = pParse->pTriggerPrg;
|
||||
pParse->pTriggerPrg = pT->pNext;
|
||||
while( sParse.pTriggerPrg ){
|
||||
TriggerPrg *pT = sParse.pTriggerPrg;
|
||||
sParse.pTriggerPrg = pT->pNext;
|
||||
sqlite3DbFree(db, pT);
|
||||
}
|
||||
|
||||
end_prepare:
|
||||
|
||||
sqlite3ParserReset(pParse);
|
||||
sqlite3StackFree(db, pParse);
|
||||
sqlite3ParserReset(&sParse);
|
||||
rc = sqlite3ApiExit(db, rc);
|
||||
assert( (rc&db->errMask)==rc );
|
||||
return rc;
|
||||
|
||||
+12
-12
@@ -623,7 +623,6 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
|
||||
/* if( pSrcList==0 ) break; */
|
||||
notValid(pParse, pNC, "the \".\" operator", NC_IdxExpr);
|
||||
/*notValid(pParse, pNC, "the \".\" operator", NC_PartIdx|NC_IsCheck, 1);*/
|
||||
pRight = pExpr->pRight;
|
||||
if( pRight->op==TK_ID ){
|
||||
zDb = 0;
|
||||
@@ -646,14 +645,12 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
int no_such_func = 0; /* True if no such function exists */
|
||||
int wrong_num_args = 0; /* True if wrong number of arguments */
|
||||
int is_agg = 0; /* True if is an aggregate function */
|
||||
int auth; /* Authorization to use the function */
|
||||
int nId; /* Number of characters in function name */
|
||||
const char *zId; /* The function name. */
|
||||
FuncDef *pDef; /* Information about the function */
|
||||
u8 enc = ENC(pParse->db); /* The database encoding */
|
||||
|
||||
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
||||
notValid(pParse, pNC, "functions", NC_PartIdx);
|
||||
zId = pExpr->u.zToken;
|
||||
nId = sqlite3Strlen30(zId);
|
||||
pDef = sqlite3FindFunction(pParse->db, zId, n, enc, 0);
|
||||
@@ -690,15 +687,17 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0, pDef->zName, 0);
|
||||
if( auth!=SQLITE_OK ){
|
||||
if( auth==SQLITE_DENY ){
|
||||
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
|
||||
pDef->zName);
|
||||
pNC->nErr++;
|
||||
{
|
||||
int auth = sqlite3AuthCheck(pParse, SQLITE_FUNCTION, 0,pDef->zName,0);
|
||||
if( auth!=SQLITE_OK ){
|
||||
if( auth==SQLITE_DENY ){
|
||||
sqlite3ErrorMsg(pParse, "not authorized to use function: %s",
|
||||
pDef->zName);
|
||||
pNC->nErr++;
|
||||
}
|
||||
pExpr->op = TK_NULL;
|
||||
return WRC_Prune;
|
||||
}
|
||||
pExpr->op = TK_NULL;
|
||||
return WRC_Prune;
|
||||
}
|
||||
#endif
|
||||
if( pDef->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG) ){
|
||||
@@ -711,7 +710,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
|
||||
/* Date/time functions that use 'now', and other functions like
|
||||
** sqlite_version() that might change over time cannot be used
|
||||
** in an index. */
|
||||
notValid(pParse, pNC, "non-deterministic functions", NC_IdxExpr);
|
||||
notValid(pParse, pNC, "non-deterministic functions",
|
||||
NC_IdxExpr|NC_PartIdx);
|
||||
}
|
||||
}
|
||||
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
|
||||
|
||||
+7
-6
@@ -1005,7 +1005,7 @@ static void selectInnerLoop(
|
||||
*/
|
||||
KeyInfo *sqlite3KeyInfoAlloc(sqlite3 *db, int N, int X){
|
||||
int nExtra = (N+X)*(sizeof(CollSeq*)+1);
|
||||
KeyInfo *p = sqlite3DbMallocRaw(db, sizeof(KeyInfo) + nExtra);
|
||||
KeyInfo *p = sqlite3DbMallocRawNN(db, sizeof(KeyInfo) + nExtra);
|
||||
if( p ){
|
||||
p->aSortOrder = (u8*)&p->aColl[N+X];
|
||||
p->nField = (u16)N;
|
||||
@@ -1232,7 +1232,7 @@ static void generateSortTail(
|
||||
int regSortOut = ++pParse->nMem;
|
||||
iSortTab = pParse->nTab++;
|
||||
if( pSort->labelBkOut ){
|
||||
addrOnce = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
}
|
||||
sqlite3VdbeAddOp3(v, OP_OpenPseudo, iSortTab, regSortOut, nKey+1+nSortData);
|
||||
if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce);
|
||||
@@ -3695,12 +3695,13 @@ static int flattenSubquery(
|
||||
assert( pParent->pHaving==0 );
|
||||
pParent->pHaving = pParent->pWhere;
|
||||
pParent->pWhere = pWhere;
|
||||
pParent->pHaving = sqlite3ExprAnd(db, pParent->pHaving,
|
||||
sqlite3ExprDup(db, pSub->pHaving, 0));
|
||||
pParent->pHaving = sqlite3ExprAnd(db,
|
||||
sqlite3ExprDup(db, pSub->pHaving, 0), pParent->pHaving
|
||||
);
|
||||
assert( pParent->pGroupBy==0 );
|
||||
pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
|
||||
}else{
|
||||
pParent->pWhere = sqlite3ExprAnd(db, pParent->pWhere, pWhere);
|
||||
pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
|
||||
}
|
||||
substSelect(db, pParent, iParent, pSub->pEList, 0);
|
||||
|
||||
@@ -5027,7 +5028,7 @@ int sqlite3Select(
|
||||
/* If the subquery is not correlated and if we are not inside of
|
||||
** a trigger, then we only need to compute the value of the subquery
|
||||
** once. */
|
||||
onceAddr = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
onceAddr = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
VdbeComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
}else{
|
||||
VdbeNoopComment((v, "materialize \"%s\"", pItem->pTab->zName));
|
||||
|
||||
+246
-36
@@ -143,6 +143,7 @@
|
||||
extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR);
|
||||
extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int);
|
||||
extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int);
|
||||
extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText);
|
||||
#endif
|
||||
|
||||
/* On Windows, we normally run with output mode of TEXT so that \n characters
|
||||
@@ -626,8 +627,10 @@ struct ShellState {
|
||||
int normalMode; /* Output mode before ".explain on" */
|
||||
int writableSchema; /* True if PRAGMA writable_schema=ON */
|
||||
int showHeader; /* True to show column names in List or Column mode */
|
||||
int nCheck; /* Number of ".check" commands run */
|
||||
unsigned shellFlgs; /* Various flags */
|
||||
char *zDestTable; /* Name of destination table when MODE_Insert */
|
||||
char zTestcase[30]; /* Name of current test case */
|
||||
char colSeparator[20]; /* Column separator character for several modes */
|
||||
char rowSeparator[20]; /* Row separator character for MODE_Ascii */
|
||||
int colWidth[100]; /* Requested width of each column when in column mode*/
|
||||
@@ -894,6 +897,7 @@ static void interrupt_handler(int NotUsed){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
/*
|
||||
** When the ".auth ON" is set, the following authorizer callback is
|
||||
** invoked. It always returns SQLITE_OK.
|
||||
@@ -926,7 +930,7 @@ static int shellAuth(
|
||||
az[1] = zA2;
|
||||
az[2] = zA3;
|
||||
az[3] = zA4;
|
||||
raw_printf(p->out, "authorizer: %s", azAction[op]);
|
||||
utf8_printf(p->out, "authorizer: %s", azAction[op]);
|
||||
for(i=0; i<4; i++){
|
||||
raw_printf(p->out, " ");
|
||||
if( az[i] ){
|
||||
@@ -938,7 +942,8 @@ static int shellAuth(
|
||||
raw_printf(p->out, "\n");
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
** This is the callback routine that the shell
|
||||
@@ -1442,7 +1447,7 @@ static void displayLinuxIoStats(FILE *out){
|
||||
for(i=0; i<ArraySize(aTrans); i++){
|
||||
int n = (int)strlen(aTrans[i].zPattern);
|
||||
if( strncmp(aTrans[i].zPattern, z, n)==0 ){
|
||||
raw_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
|
||||
utf8_printf(out, "%-36s %s", aTrans[i].zDesc, &z[n]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2131,11 +2136,14 @@ static int run_schema_dump_query(
|
||||
** Text of a help message
|
||||
*/
|
||||
static char zHelp[] =
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
".auth ON|OFF Show authorizer callbacks\n"
|
||||
#endif
|
||||
".backup ?DB? FILE Backup DB (default \"main\") to FILE\n"
|
||||
".bail on|off Stop after hitting an error. Default OFF\n"
|
||||
".binary on|off Turn binary output on or off. Default OFF\n"
|
||||
".changes on|off Show number of rows changed by SQL\n"
|
||||
".check GLOB Fail if output since .testcase does not match\n"
|
||||
".clone NEWDB Clone data into NEWDB from the existing database\n"
|
||||
".databases List names and files of attached databases\n"
|
||||
".dbinfo ?DB? Show status information about the database\n"
|
||||
@@ -2173,7 +2181,8 @@ static char zHelp[] =
|
||||
" tcl TCL list elements\n"
|
||||
".nullvalue STRING Use STRING in place of NULL values\n"
|
||||
".once FILENAME Output for the next SQL command only to FILENAME\n"
|
||||
".open ?FILENAME? Close existing database and reopen FILENAME\n"
|
||||
".open ?--new? ?FILE? Close existing database and reopen FILE\n"
|
||||
" The --new starts with an empty file\n"
|
||||
".output ?FILENAME? Send output to FILENAME or stdout\n"
|
||||
".print STRING... Print literal STRING\n"
|
||||
".prompt MAIN CONTINUE Replace the standard prompts\n"
|
||||
@@ -2196,6 +2205,7 @@ static char zHelp[] =
|
||||
".tables ?TABLE? List names of tables\n"
|
||||
" If TABLE specified, only list tables matching\n"
|
||||
" LIKE pattern TABLE.\n"
|
||||
".testcase NAME Begin redirecting output to 'testcase-out.txt'\n"
|
||||
".timeout MS Try opening locked tables for MS milliseconds\n"
|
||||
".timer on|off Turn SQL timer on or off\n"
|
||||
".trace FILE|off Output each SQL statement as it is run\n"
|
||||
@@ -2232,6 +2242,35 @@ void session_help(ShellState *p){
|
||||
|
||||
/* Forward reference */
|
||||
static int process_input(ShellState *p, FILE *in);
|
||||
|
||||
|
||||
/*
|
||||
** Read the content of a file into memory obtained from sqlite3_malloc64().
|
||||
** The caller is responsible for freeing the memory.
|
||||
**
|
||||
** NULL is returned if any error is encountered.
|
||||
*/
|
||||
static char *readFile(const char *zName){
|
||||
FILE *in = fopen(zName, "rb");
|
||||
long nIn;
|
||||
size_t nRead;
|
||||
char *pBuf;
|
||||
if( in==0 ) return 0;
|
||||
fseek(in, 0, SEEK_END);
|
||||
nIn = ftell(in);
|
||||
rewind(in);
|
||||
pBuf = sqlite3_malloc64( nIn+1 );
|
||||
if( pBuf==0 ) return 0;
|
||||
nRead = fread(pBuf, nIn, 1, in);
|
||||
fclose(in);
|
||||
if( nRead!=1 ){
|
||||
sqlite3_free(pBuf);
|
||||
return 0;
|
||||
}
|
||||
pBuf[nIn] = 0;
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the "readfile(X)" SQL function. The entire content
|
||||
** of the file named X is read and returned as a BLOB. NULL is returned
|
||||
@@ -2243,25 +2282,13 @@ static void readfileFunc(
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const char *zName;
|
||||
FILE *in;
|
||||
long nIn;
|
||||
void *pBuf;
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
zName = (const char*)sqlite3_value_text(argv[0]);
|
||||
if( zName==0 ) return;
|
||||
in = fopen(zName, "rb");
|
||||
if( in==0 ) return;
|
||||
fseek(in, 0, SEEK_END);
|
||||
nIn = ftell(in);
|
||||
rewind(in);
|
||||
pBuf = sqlite3_malloc64( nIn );
|
||||
if( pBuf && 1==fread(pBuf, nIn, 1, in) ){
|
||||
sqlite3_result_blob(context, pBuf, nIn, sqlite3_free);
|
||||
}else{
|
||||
sqlite3_free(pBuf);
|
||||
}
|
||||
fclose(in);
|
||||
pBuf = readFile(zName);
|
||||
if( pBuf ) sqlite3_result_blob(context, pBuf, -1, sqlite3_free);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3063,6 +3090,104 @@ static int shellNomemError(void){
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare the pattern in zGlob[] against the text in z[]. Return TRUE
|
||||
** if they match and FALSE (0) if they do not match.
|
||||
**
|
||||
** Globbing rules:
|
||||
**
|
||||
** '*' Matches any sequence of zero or more characters.
|
||||
**
|
||||
** '?' Matches exactly one character.
|
||||
**
|
||||
** [...] Matches one character from the enclosed list of
|
||||
** characters.
|
||||
**
|
||||
** [^...] Matches one character not in the enclosed list.
|
||||
**
|
||||
** '#' Matches any sequence of one or more digits with an
|
||||
** optional + or - sign in front
|
||||
**
|
||||
** ' ' Any span of whitespace matches any other span of
|
||||
** whitespace.
|
||||
**
|
||||
** Extra whitespace at the end of z[] is ignored.
|
||||
*/
|
||||
static int testcase_glob(const char *zGlob, const char *z){
|
||||
int c, c2;
|
||||
int invert;
|
||||
int seen;
|
||||
|
||||
while( (c = (*(zGlob++)))!=0 ){
|
||||
if( IsSpace(c) ){
|
||||
if( !IsSpace(*z) ) return 0;
|
||||
while( IsSpace(*zGlob) ) zGlob++;
|
||||
while( IsSpace(*z) ) z++;
|
||||
}else if( c=='*' ){
|
||||
while( (c=(*(zGlob++))) == '*' || c=='?' ){
|
||||
if( c=='?' && (*(z++))==0 ) return 0;
|
||||
}
|
||||
if( c==0 ){
|
||||
return 1;
|
||||
}else if( c=='[' ){
|
||||
while( *z && testcase_glob(zGlob-1,z)==0 ){
|
||||
z++;
|
||||
}
|
||||
return (*z)!=0;
|
||||
}
|
||||
while( (c2 = (*(z++)))!=0 ){
|
||||
while( c2!=c ){
|
||||
c2 = *(z++);
|
||||
if( c2==0 ) return 0;
|
||||
}
|
||||
if( testcase_glob(zGlob,z) ) return 1;
|
||||
}
|
||||
return 0;
|
||||
}else if( c=='?' ){
|
||||
if( (*(z++))==0 ) return 0;
|
||||
}else if( c=='[' ){
|
||||
int prior_c = 0;
|
||||
seen = 0;
|
||||
invert = 0;
|
||||
c = *(z++);
|
||||
if( c==0 ) return 0;
|
||||
c2 = *(zGlob++);
|
||||
if( c2=='^' ){
|
||||
invert = 1;
|
||||
c2 = *(zGlob++);
|
||||
}
|
||||
if( c2==']' ){
|
||||
if( c==']' ) seen = 1;
|
||||
c2 = *(zGlob++);
|
||||
}
|
||||
while( c2 && c2!=']' ){
|
||||
if( c2=='-' && zGlob[0]!=']' && zGlob[0]!=0 && prior_c>0 ){
|
||||
c2 = *(zGlob++);
|
||||
if( c>=prior_c && c<=c2 ) seen = 1;
|
||||
prior_c = 0;
|
||||
}else{
|
||||
if( c==c2 ){
|
||||
seen = 1;
|
||||
}
|
||||
prior_c = c2;
|
||||
}
|
||||
c2 = *(zGlob++);
|
||||
}
|
||||
if( c2==0 || (seen ^ invert)==0 ) return 0;
|
||||
}else if( c=='#' ){
|
||||
if( (z[0]=='-' || z[0]=='+') && IsDigit(z[1]) ) z++;
|
||||
if( !IsDigit(z[0]) ) return 0;
|
||||
z++;
|
||||
while( IsDigit(z[0]) ){ z++; }
|
||||
}else{
|
||||
if( c!=(*(z++)) ) return 0;
|
||||
}
|
||||
}
|
||||
while( IsSpace(*z) ){ z++; }
|
||||
return *z==0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Compare the string as a command-line option with either one or two
|
||||
** initial "-" characters.
|
||||
@@ -3074,6 +3199,21 @@ static int optionMatch(const char *zStr, const char *zOpt){
|
||||
return strcmp(zStr, zOpt)==0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete a file.
|
||||
*/
|
||||
int shellDeleteFile(const char *zFilename){
|
||||
int rc;
|
||||
#ifdef _WIN32
|
||||
wchar_t *z = sqlite3_win32_utf8_to_unicode(zFilename);
|
||||
rc = _wunlink(z);
|
||||
sqlite3_free(z);
|
||||
#else
|
||||
rc = unlink(zFilename);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** If an input line begins with "." then invoke this routine to
|
||||
** process that line.
|
||||
@@ -3117,6 +3257,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
n = strlen30(azArg[0]);
|
||||
c = azArg[0][0];
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( c=='a' && strncmp(azArg[0], "auth", n)==0 ){
|
||||
if( nArg!=2 ){
|
||||
raw_printf(stderr, "Usage: .auth ON|OFF\n");
|
||||
@@ -3130,6 +3271,7 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_set_authorizer(p->db, 0, 0);
|
||||
}
|
||||
}else
|
||||
#endif
|
||||
|
||||
if( (c=='b' && n>=3 && strncmp(azArg[0], "backup", n)==0)
|
||||
|| (c=='s' && n>=3 && strncmp(azArg[0], "save", n)==0)
|
||||
@@ -3225,6 +3367,31 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}
|
||||
}else
|
||||
|
||||
/* Cancel output redirection, if it is currently set (by .testcase)
|
||||
** Then read the content of the testcase-out.txt file and compare against
|
||||
** azArg[1]. If there are differences, report an error and exit.
|
||||
*/
|
||||
if( c=='c' && n>=3 && strncmp(azArg[0], "check", n)==0 ){
|
||||
char *zRes = 0;
|
||||
output_reset(p);
|
||||
if( nArg!=2 ){
|
||||
raw_printf(stderr, "Usage: .check GLOB-PATTERN\n");
|
||||
rc = 2;
|
||||
}else if( (zRes = readFile("testcase-out.txt"))==0 ){
|
||||
raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n");
|
||||
rc = 2;
|
||||
}else if( testcase_glob(azArg[1],zRes)==0 ){
|
||||
utf8_printf(stderr,
|
||||
"testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n",
|
||||
p->zTestcase, azArg[1], zRes);
|
||||
rc = 2;
|
||||
}else{
|
||||
utf8_printf(stdout, "testcase-%s ok\n", p->zTestcase);
|
||||
p->nCheck++;
|
||||
}
|
||||
sqlite3_free(zRes);
|
||||
}else
|
||||
|
||||
if( c=='c' && strncmp(azArg[0], "clone", n)==0 ){
|
||||
if( nArg==2 ){
|
||||
tryToClone(p, azArg[1]);
|
||||
@@ -3833,22 +4000,43 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
}else
|
||||
|
||||
if( c=='o' && strncmp(azArg[0], "open", n)==0 && n>=2 ){
|
||||
sqlite3 *savedDb = p->db;
|
||||
const char *zSavedFilename = p->zDbFilename;
|
||||
char *zNewFilename = 0;
|
||||
char *zNewFilename; /* Name of the database file to open */
|
||||
int iName = 1; /* Index in azArg[] of the filename */
|
||||
int newFlag = 0; /* True to delete file before opening */
|
||||
/* Close the existing database */
|
||||
session_close_all(p);
|
||||
sqlite3_close(p->db);
|
||||
p->db = 0;
|
||||
if( nArg>=2 ) zNewFilename = sqlite3_mprintf("%s", azArg[1]);
|
||||
p->zDbFilename = zNewFilename;
|
||||
open_db(p, 1);
|
||||
if( p->db!=0 ){
|
||||
session_close_all(p);
|
||||
sqlite3_close(savedDb);
|
||||
sqlite3_free(p->zFreeOnClose);
|
||||
p->zFreeOnClose = zNewFilename;
|
||||
}else{
|
||||
sqlite3_free(zNewFilename);
|
||||
p->db = savedDb;
|
||||
p->zDbFilename = zSavedFilename;
|
||||
sqlite3_free(p->zFreeOnClose);
|
||||
p->zFreeOnClose = 0;
|
||||
/* Check for command-line arguments */
|
||||
for(iName=1; iName<nArg && azArg[iName][0]=='-'; iName++){
|
||||
const char *z = azArg[iName];
|
||||
if( optionMatch(z,"new") ){
|
||||
newFlag = 1;
|
||||
}else if( z[0]=='-' ){
|
||||
utf8_printf(stderr, "unknown option: %s\n", z);
|
||||
rc = 1;
|
||||
goto meta_command_exit;
|
||||
}
|
||||
}
|
||||
/* If a filename is specified, try to open it first */
|
||||
zNewFilename = nArg>iName ? sqlite3_mprintf("%s", azArg[iName]) : 0;
|
||||
if( zNewFilename ){
|
||||
if( newFlag ) shellDeleteFile(zNewFilename);
|
||||
p->zDbFilename = zNewFilename;
|
||||
open_db(p, 1);
|
||||
if( p->db==0 ){
|
||||
utf8_printf(stderr, "Error: cannot open '%s'\n", zNewFilename);
|
||||
sqlite3_free(zNewFilename);
|
||||
}else{
|
||||
p->zFreeOnClose = zNewFilename;
|
||||
}
|
||||
}
|
||||
if( p->db==0 ){
|
||||
/* As a fall-back open a TEMP database */
|
||||
p->zDbFilename = 0;
|
||||
open_db(p, 0);
|
||||
}
|
||||
}else
|
||||
|
||||
@@ -4378,6 +4566,8 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
raw_printf(p->out, "%d ", p->colWidth[i]);
|
||||
}
|
||||
raw_printf(p->out, "\n");
|
||||
utf8_printf(p->out, "%12.12s: %s\n", "filename",
|
||||
p->zDbFilename ? p->zDbFilename : "");
|
||||
}else
|
||||
|
||||
if( c=='s' && strncmp(azArg[0], "stats", n)==0 ){
|
||||
@@ -4495,6 +4685,20 @@ static int do_meta_command(char *zLine, ShellState *p){
|
||||
sqlite3_free(azResult);
|
||||
}else
|
||||
|
||||
/* Begin redirecting output to the file "testcase-out.txt" */
|
||||
if( c=='t' && strcmp(azArg[0],"testcase")==0 ){
|
||||
output_reset(p);
|
||||
p->out = output_file_open("testcase-out.txt");
|
||||
if( p->out==0 ){
|
||||
utf8_printf(stderr, "Error: cannot open 'testcase-out.txt'\n");
|
||||
}
|
||||
if( nArg>=2 ){
|
||||
sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "%s", azArg[1]);
|
||||
}else{
|
||||
sqlite3_snprintf(sizeof(p->zTestcase), p->zTestcase, "?");
|
||||
}
|
||||
}else
|
||||
|
||||
if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 && nArg>=2 ){
|
||||
static const struct {
|
||||
const char *zCtrlName; /* Name of a test-control option */
|
||||
@@ -5005,8 +5209,13 @@ static int process_input(ShellState *p, FILE *in){
|
||||
** Return a pathname which is the user's home directory. A
|
||||
** 0 return indicates an error of some kind.
|
||||
*/
|
||||
static char *find_home_dir(void){
|
||||
static char *find_home_dir(int clearFlag){
|
||||
static char *home_dir = NULL;
|
||||
if( clearFlag ){
|
||||
free(home_dir);
|
||||
home_dir = 0;
|
||||
return 0;
|
||||
}
|
||||
if( home_dir ) return home_dir;
|
||||
|
||||
#if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \
|
||||
@@ -5081,7 +5290,7 @@ static void process_sqliterc(
|
||||
FILE *in = NULL;
|
||||
|
||||
if (sqliterc == NULL) {
|
||||
home_dir = find_home_dir();
|
||||
home_dir = find_home_dir(0);
|
||||
if( home_dir==0 ){
|
||||
raw_printf(stderr, "-- warning: cannot find home directory;"
|
||||
" cannot read ~/.sqliterc\n");
|
||||
@@ -5569,7 +5778,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
printf(".\nUse \".open FILENAME\" to reopen on a "
|
||||
"persistent database.\n");
|
||||
}
|
||||
zHome = find_home_dir();
|
||||
zHome = find_home_dir(0);
|
||||
if( zHome ){
|
||||
nHistory = strlen30(zHome) + 20;
|
||||
if( (zHistory = malloc(nHistory))!=0 ){
|
||||
@@ -5593,6 +5802,7 @@ int SQLITE_CDECL wmain(int argc, wchar_t **wargv){
|
||||
sqlite3_close(data.db);
|
||||
}
|
||||
sqlite3_free(data.zFreeOnClose);
|
||||
find_home_dir(1);
|
||||
#if !SQLITE_SHELL_IS_UTF8
|
||||
for(i=0; i<argc; i++) sqlite3_free(argv[i]);
|
||||
sqlite3_free(argv);
|
||||
|
||||
+16
-8
@@ -108,7 +108,8 @@ extern "C" {
|
||||
** be held constant and Z will be incremented or else Y will be incremented
|
||||
** and Z will be reset to zero.
|
||||
**
|
||||
** Since version 3.6.18, SQLite source code has been stored in the
|
||||
** Since [version 3.6.18] ([dateof:3.6.18]),
|
||||
** SQLite source code has been stored in the
|
||||
** <a href="http://www.fossil-scm.org/">Fossil configuration management
|
||||
** system</a>. ^The SQLITE_SOURCE_ID macro evaluates to
|
||||
** a string which identifies a particular check-in of SQLite
|
||||
@@ -452,7 +453,8 @@ int sqlite3_exec(
|
||||
** [result codes]. However, experience has shown that many of
|
||||
** these result codes are too coarse-grained. They do not provide as
|
||||
** much information about problems as programmers might like. In an effort to
|
||||
** address this, newer versions of SQLite (version 3.3.8 and later) include
|
||||
** address this, newer versions of SQLite (version 3.3.8 [dateof:3.3.8]
|
||||
** and later) include
|
||||
** support for additional result codes that provide more detailed information
|
||||
** about errors. These [extended result codes] are enabled or disabled
|
||||
** on a per database connection basis using the
|
||||
@@ -4051,7 +4053,8 @@ const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
|
||||
** other than [SQLITE_ROW] before any subsequent invocation of
|
||||
** sqlite3_step(). Failure to reset the prepared statement using
|
||||
** [sqlite3_reset()] would result in an [SQLITE_MISUSE] return from
|
||||
** sqlite3_step(). But after version 3.6.23.1, sqlite3_step() began
|
||||
** sqlite3_step(). But after [version 3.6.23.1] ([dateof:3.6.23.1],
|
||||
** sqlite3_step() began
|
||||
** calling [sqlite3_reset()] automatically in this circumstance rather
|
||||
** than returning [SQLITE_MISUSE]. This is not considered a compatibility
|
||||
** break because any application that ever receives an SQLITE_MISUSE error
|
||||
@@ -5414,7 +5417,8 @@ void *sqlite3_update_hook(
|
||||
** and disabled if the argument is false.)^
|
||||
**
|
||||
** ^Cache sharing is enabled and disabled for an entire process.
|
||||
** This is a change as of SQLite version 3.5.0. In prior versions of SQLite,
|
||||
** This is a change as of SQLite [version 3.5.0] ([dateof:3.5.0]).
|
||||
** In prior versions of SQLite,
|
||||
** sharing was enabled or disabled for each thread separately.
|
||||
**
|
||||
** ^(The cache sharing mode set by this interface effects all subsequent
|
||||
@@ -5508,7 +5512,8 @@ int sqlite3_db_release_memory(sqlite3*);
|
||||
** from the heap.
|
||||
** </ul>)^
|
||||
**
|
||||
** Beginning with SQLite version 3.7.3, the soft heap limit is enforced
|
||||
** Beginning with SQLite [version 3.7.3] ([dateof:3.7.3]),
|
||||
** the soft heap limit is enforced
|
||||
** regardless of whether or not the [SQLITE_ENABLE_MEMORY_MANAGEMENT]
|
||||
** compile-time option is invoked. With [SQLITE_ENABLE_MEMORY_MANAGEMENT],
|
||||
** the soft heap limit is enforced on every memory allocation. Without
|
||||
@@ -5902,13 +5907,15 @@ struct sqlite3_module {
|
||||
** the xUpdate method are automatically rolled back by SQLite.
|
||||
**
|
||||
** IMPORTANT: The estimatedRows field was added to the sqlite3_index_info
|
||||
** structure for SQLite version 3.8.2. If a virtual table extension is
|
||||
** structure for SQLite [version 3.8.2] ([dateof:3.8.2]).
|
||||
** If a virtual table extension is
|
||||
** used with an SQLite version earlier than 3.8.2, the results of attempting
|
||||
** to read or write the estimatedRows field are undefined (but are likely
|
||||
** to included crashing the application). The estimatedRows field should
|
||||
** therefore only be used if [sqlite3_libversion_number()] returns a
|
||||
** value greater than or equal to 3008002. Similarly, the idxFlags field
|
||||
** was added for version 3.9.0. It may therefore only be used if
|
||||
** was added for [version 3.9.0] ([dateof:3.9.0]).
|
||||
** It may therefore only be used if
|
||||
** sqlite3_libversion_number() returns a value greater than or equal to
|
||||
** 3009000.
|
||||
*/
|
||||
@@ -6606,7 +6613,7 @@ int sqlite3_mutex_notheld(sqlite3_mutex*);
|
||||
#define SQLITE_MUTEX_STATIC_MEM 3 /* sqlite3_malloc() */
|
||||
#define SQLITE_MUTEX_STATIC_MEM2 4 /* NOT USED */
|
||||
#define SQLITE_MUTEX_STATIC_OPEN 4 /* sqlite3BtreeOpen() */
|
||||
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_random() */
|
||||
#define SQLITE_MUTEX_STATIC_PRNG 5 /* sqlite3_randomness() */
|
||||
#define SQLITE_MUTEX_STATIC_LRU 6 /* lru page list */
|
||||
#define SQLITE_MUTEX_STATIC_LRU2 7 /* NOT USED */
|
||||
#define SQLITE_MUTEX_STATIC_PMEM 7 /* sqlite3PageMalloc() */
|
||||
@@ -6710,6 +6717,7 @@ int sqlite3_test_control(int op, ...);
|
||||
#define SQLITE_TESTCTRL_SCRATCHMALLOC 17
|
||||
#define SQLITE_TESTCTRL_LOCALTIME_FAULT 18
|
||||
#define SQLITE_TESTCTRL_EXPLAIN_STMT 19 /* NOT USED */
|
||||
#define SQLITE_TESTCTRL_ONCE_RESET_THRESHOLD 19
|
||||
#define SQLITE_TESTCTRL_NEVER_CORRUPT 20
|
||||
#define SQLITE_TESTCTRL_VDBE_COVERAGE 21
|
||||
#define SQLITE_TESTCTRL_BYTEORDER 22
|
||||
|
||||
+30
-20
@@ -2338,6 +2338,7 @@ struct Expr {
|
||||
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
|
||||
#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
|
||||
#define EP_Alias 0x400000 /* Is an alias for a result set column */
|
||||
#define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */
|
||||
|
||||
/*
|
||||
** Combinations of two or more EP_* flags
|
||||
@@ -2889,36 +2890,23 @@ struct Parse {
|
||||
u8 okConstFactor; /* OK to factor out constants */
|
||||
u8 disableLookaside; /* Number of times lookaside has been disabled */
|
||||
u8 nColCache; /* Number of entries in aColCache[] */
|
||||
int aTempReg[8]; /* Holding area for temporary registers */
|
||||
int nRangeReg; /* Size of the temporary register block */
|
||||
int iRangeReg; /* First register in temporary register block */
|
||||
int nErr; /* Number of errors seen */
|
||||
int nTab; /* Number of previously allocated VDBE cursors */
|
||||
int nMem; /* Number of memory cells used so far */
|
||||
int nSet; /* Number of sets used so far */
|
||||
int nOnce; /* Number of OP_Once instructions so far */
|
||||
int nOpAlloc; /* Number of slots allocated for Vdbe.aOp[] */
|
||||
int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */
|
||||
int iFixedOp; /* Never back out opcodes iFixedOp-1 or earlier */
|
||||
int ckBase; /* Base register of data during check constraints */
|
||||
int iSelfTab; /* Table of an index whose exprs are being coded */
|
||||
int iCacheLevel; /* ColCache valid when aColCache[].iLevel<=iCacheLevel */
|
||||
int iCacheCnt; /* Counter used to generate aColCache[].lru values */
|
||||
int nLabel; /* Number of labels used */
|
||||
int *aLabel; /* Space to hold the labels */
|
||||
struct yColCache {
|
||||
int iTable; /* Table cursor number */
|
||||
i16 iColumn; /* Table column number */
|
||||
u8 tempReg; /* iReg is a temp register that needs to be freed */
|
||||
int iLevel; /* Nesting level */
|
||||
int iReg; /* Reg with value of this column. 0 means none. */
|
||||
int lru; /* Least recently used entry has the smallest value */
|
||||
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
|
||||
ExprList *pConstExpr;/* Constant expressions */
|
||||
Token constraintName;/* Name of the constraint currently being parsed */
|
||||
yDbMask writeMask; /* Start a write transaction on these databases */
|
||||
yDbMask cookieMask; /* Bitmask of schema verified databases */
|
||||
int cookieValue[SQLITE_MAX_ATTACHED+2]; /* Values of cookies to verify */
|
||||
int regRowid; /* Register holding rowid of CREATE TABLE entry */
|
||||
int regRoot; /* Register holding root page number for new objects */
|
||||
int nMaxArg; /* Max args passed to user function by sub-program */
|
||||
@@ -2931,8 +2919,6 @@ struct Parse {
|
||||
TableLock *aTableLock; /* Required table locks for shared-cache mode */
|
||||
#endif
|
||||
AutoincInfo *pAinc; /* Information about AUTOINCREMENT counters */
|
||||
|
||||
/* Information used while coding trigger programs. */
|
||||
Parse *pToplevel; /* Parse structure for main program (or NULL) */
|
||||
Table *pTriggerTab; /* Table triggers are being coded for */
|
||||
int addrCrTab; /* Address of OP_CreateTable opcode on CREATE TABLE */
|
||||
@@ -2943,6 +2929,25 @@ struct Parse {
|
||||
u8 eOrconf; /* Default ON CONFLICT policy for trigger steps */
|
||||
u8 disableTriggers; /* True to disable triggers */
|
||||
|
||||
/**************************************************************************
|
||||
** Fields above must be initialized to zero. The fields that follow,
|
||||
** down to the beginning of the recursive section, do not need to be
|
||||
** initialized as they will be set before being used. The boundary is
|
||||
** determined by offsetof(Parse,aColCache).
|
||||
**************************************************************************/
|
||||
|
||||
struct yColCache {
|
||||
int iTable; /* Table cursor number */
|
||||
i16 iColumn; /* Table column number */
|
||||
u8 tempReg; /* iReg is a temp register that needs to be freed */
|
||||
int iLevel; /* Nesting level */
|
||||
int iReg; /* Reg with value of this column. 0 means none. */
|
||||
int lru; /* Least recently used entry has the smallest value */
|
||||
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
|
||||
int aTempReg[8]; /* Holding area for temporary registers */
|
||||
Token sNameToken; /* Token with unqualified schema object name */
|
||||
Token sLastToken; /* The last token parsed */
|
||||
|
||||
/************************************************************************
|
||||
** Above is constant between recursions. Below is reset before and after
|
||||
** each recursion. The boundary between these two regions is determined
|
||||
@@ -2958,7 +2963,6 @@ struct Parse {
|
||||
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
|
||||
int nVtabLock; /* Number of virtual tables to lock */
|
||||
#endif
|
||||
int nAlias; /* Number of aliased result set columns */
|
||||
int nHeight; /* Expression tree height of current sub-select */
|
||||
#ifndef SQLITE_OMIT_EXPLAIN
|
||||
int iSelectId; /* ID of current select for EXPLAIN output */
|
||||
@@ -2970,8 +2974,6 @@ struct Parse {
|
||||
Table *pNewTable; /* A table being constructed by CREATE TABLE */
|
||||
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
|
||||
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
|
||||
Token sNameToken; /* Token with unqualified schema object name */
|
||||
Token sLastToken; /* The last token parsed */
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
Token sArg; /* Complete text of a module argument */
|
||||
Table **apVtabLock; /* Pointer to virtual tables needing locking */
|
||||
@@ -2982,6 +2984,14 @@ struct Parse {
|
||||
With *pWithToFree; /* Free this WITH object at the end of the parse */
|
||||
};
|
||||
|
||||
/*
|
||||
** Sizes and pointers of various parts of the Parse object.
|
||||
*/
|
||||
#define PARSE_HDR_SZ offsetof(Parse,aColCache) /* Recursive part w/o aColCache*/
|
||||
#define PARSE_RECURSE_SZ offsetof(Parse,nVar) /* Recursive part */
|
||||
#define PARSE_TAIL_SZ (sizeof(Parse)-PARSE_RECURSE_SZ) /* Non-recursive part */
|
||||
#define PARSE_TAIL(X) (((char*)(X))+PARSE_RECURSE_SZ) /* Pointer to tail */
|
||||
|
||||
/*
|
||||
** Return true if currently inside an sqlite3_declare_vtab() call.
|
||||
*/
|
||||
@@ -3230,6 +3240,7 @@ struct Sqlite3Config {
|
||||
int (*xTestCallback)(int); /* Invoked by sqlite3FaultSim() */
|
||||
#endif
|
||||
int bLocaltimeFault; /* True to fail localtime() calls */
|
||||
int iOnceResetThreshold; /* When to reset OP_Once counters */
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -3544,7 +3555,7 @@ Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
|
||||
void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
|
||||
Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
|
||||
Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
|
||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
|
||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*, u32);
|
||||
void sqlite3ExprDelete(sqlite3*, Expr*);
|
||||
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
||||
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
||||
@@ -3583,7 +3594,6 @@ void sqlite3EndTable(Parse*,Token*,Token*,u8,Select*);
|
||||
int sqlite3ParseUri(const char*,const char*,unsigned int*,
|
||||
sqlite3_vfs**,char**,char **);
|
||||
Btree *sqlite3DbNameToBtree(sqlite3*,const char*);
|
||||
int sqlite3CodeOnce(Parse *);
|
||||
|
||||
#ifdef SQLITE_OMIT_BUILTIN_TEST
|
||||
# define sqlite3FaultSim(X) SQLITE_OK
|
||||
|
||||
+8
-5
@@ -590,7 +590,8 @@ static int DbProgressHandler(void *cd){
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
||||
!defined(SQLITE_OMIT_DEPRECATED)
|
||||
/*
|
||||
** This routine is called by the SQLite trace handler whenever a new
|
||||
** block of SQL is executed. The TCL script in pDb->zTrace is executed.
|
||||
@@ -684,7 +685,8 @@ static int DbTraceV2Handler(
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
||||
!defined(SQLITE_OMIT_DEPRECATED)
|
||||
/*
|
||||
** This routine is called by the SQLite profile handler after a statement
|
||||
** SQL has executed. The TCL script in pDb->zProfile is evaluated.
|
||||
@@ -2747,7 +2749,8 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
}else{
|
||||
pDb->zProfile = 0;
|
||||
}
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT)
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
||||
!defined(SQLITE_OMIT_DEPRECATED)
|
||||
if( pDb->zProfile ){
|
||||
pDb->interp = interp;
|
||||
sqlite3_profile(pDb->db, DbProfileHandler, pDb);
|
||||
@@ -2934,8 +2937,8 @@ static int SQLITE_TCLAPI DbObjCmd(
|
||||
}else{
|
||||
pDb->zTrace = 0;
|
||||
}
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) \
|
||||
&& !defined(SQLITE_OMIT_DEPRECATED)
|
||||
#if !defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_OMIT_FLOATING_POINT) && \
|
||||
!defined(SQLITE_OMIT_DEPRECATED)
|
||||
if( pDb->zTrace ){
|
||||
pDb->interp = interp;
|
||||
sqlite3_trace(pDb->db, DbTraceHandler, pDb);
|
||||
|
||||
+24
@@ -2388,6 +2388,29 @@ static int SQLITE_TCLAPI test_snapshot_cmp(
|
||||
}
|
||||
#endif /* SQLITE_ENABLE_SNAPSHOT */
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_delete_database FILENAME
|
||||
*/
|
||||
int sqlite3_delete_database(const char*); /* in test_delete.c */
|
||||
static int SQLITE_TCLAPI test_delete_database(
|
||||
void * clientData,
|
||||
Tcl_Interp *interp,
|
||||
int objc,
|
||||
Tcl_Obj *CONST objv[]
|
||||
){
|
||||
int rc;
|
||||
const char *zFile;
|
||||
if( objc!=2 ){
|
||||
Tcl_WrongNumArgs(interp, 1, objv, "FILE");
|
||||
return TCL_ERROR;
|
||||
}
|
||||
zFile = (const char*)Tcl_GetString(objv[1]);
|
||||
rc = sqlite3_delete_database(zFile);
|
||||
|
||||
Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** Usage: sqlite3_next_stmt DB STMT
|
||||
**
|
||||
@@ -7483,6 +7506,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
||||
{ "sqlite3_snapshot_free", test_snapshot_free, 0 },
|
||||
{ "sqlite3_snapshot_cmp", test_snapshot_cmp, 0 },
|
||||
#endif
|
||||
{ "sqlite3_delete_database", test_delete_database, 0 },
|
||||
};
|
||||
static int bitmask_size = sizeof(Bitmask)*8;
|
||||
static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
|
||||
|
||||
+11
-6
@@ -253,7 +253,6 @@ static int SQLITE_TCLAPI btree_close_cursor(
|
||||
const char **argv /* Text of each argument */
|
||||
){
|
||||
BtCursor *pCur;
|
||||
Btree *pBt;
|
||||
int rc;
|
||||
|
||||
if( argc!=2 ){
|
||||
@@ -262,12 +261,18 @@ static int SQLITE_TCLAPI btree_close_cursor(
|
||||
return TCL_ERROR;
|
||||
}
|
||||
pCur = sqlite3TestTextToPtr(argv[1]);
|
||||
pBt = pCur->pBtree;
|
||||
sqlite3_mutex_enter(pBt->db->mutex);
|
||||
sqlite3BtreeEnter(pBt);
|
||||
#if SQLITE_THREADSAFE>0
|
||||
{
|
||||
Btree *pBt = pCur->pBtree;
|
||||
sqlite3_mutex_enter(pBt->db->mutex);
|
||||
sqlite3BtreeEnter(pBt);
|
||||
rc = sqlite3BtreeCloseCursor(pCur);
|
||||
sqlite3BtreeLeave(pBt);
|
||||
sqlite3_mutex_leave(pBt->db->mutex);
|
||||
}
|
||||
#else
|
||||
rc = sqlite3BtreeCloseCursor(pCur);
|
||||
sqlite3BtreeLeave(pBt);
|
||||
sqlite3_mutex_leave(pBt->db->mutex);
|
||||
#endif
|
||||
ckfree((char *)pCur);
|
||||
if( rc ){
|
||||
Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
** 2016 September 10
|
||||
**
|
||||
** The author disclaims copyright to this source code. In place of
|
||||
** a legal notice, here is a blessing:
|
||||
**
|
||||
** May you do good and not evil.
|
||||
** May you find forgiveness for yourself and forgive others.
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** This file contains test code to delete an SQLite database and all
|
||||
** of its associated files. Associated files include:
|
||||
**
|
||||
** * The journal file.
|
||||
** * The wal file.
|
||||
** * The SQLITE_ENABLE_8_3_NAMES version of the db, journal or wal files.
|
||||
** * Files created by the test_multiplex.c module to extend any of the
|
||||
** above.
|
||||
*/
|
||||
|
||||
#if SQLITE_OS_WIN
|
||||
# include <io.h>
|
||||
# define F_OK 0
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include "sqlite3.h"
|
||||
|
||||
/* The following #defines are copied from test_multiplex.c */
|
||||
#ifndef MX_CHUNK_NUMBER
|
||||
# define MX_CHUNK_NUMBER 299
|
||||
#endif
|
||||
#ifndef SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET
|
||||
# define SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET 400
|
||||
#endif
|
||||
#ifndef SQLITE_MULTIPLEX_WAL_8_3_OFFSET
|
||||
# define SQLITE_MULTIPLEX_WAL_8_3_OFFSET 700
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This routine is a copy of (most of) the code from SQLite function
|
||||
** sqlite3FileSuffix3(). It modifies the filename in buffer z in the
|
||||
** same way as SQLite does when in 8.3 filenames mode.
|
||||
*/
|
||||
static void sqlite3Delete83Name(char *z){
|
||||
int i, sz;
|
||||
sz = strlen(z);
|
||||
for(i=sz-1; i>0 && z[i]!='/' && z[i]!='.'; i--){}
|
||||
if( z[i]=='.' && (sz>i+4) ) memmove(&z[i+1], &z[sz-3], 4);
|
||||
}
|
||||
|
||||
/*
|
||||
** zFile is a filename. Assuming no error occurs, if this file exists,
|
||||
** set *pbExists to true and unlink it. Or, if the file does not exist,
|
||||
** set *pbExists to false before returning.
|
||||
**
|
||||
** If an error occurs, the value of errno is returned. Or, if no error
|
||||
** occurs, zero is returned.
|
||||
*/
|
||||
static int sqlite3DeleteUnlinkIfExists(const char *zFile, int *pbExists){
|
||||
int rc;
|
||||
rc = access(zFile, F_OK);
|
||||
if( rc ){
|
||||
if( errno==ENOENT ){
|
||||
if( pbExists ) *pbExists = 0;
|
||||
return 0;
|
||||
}
|
||||
return errno;
|
||||
}
|
||||
if( pbExists ) *pbExists = 1;
|
||||
rc = unlink(zFile);
|
||||
if( rc ) return errno;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Delete the database file identified by the string argument passed to this
|
||||
** function. The string must contain a filename, not an SQLite URI.
|
||||
*/
|
||||
int sqlite3_delete_database(
|
||||
const char *zFile /* File to delete */
|
||||
){
|
||||
char *zBuf; /* Buffer to sprintf() filenames to */
|
||||
int nBuf; /* Size of buffer in bytes */
|
||||
int rc = 0; /* System error code */
|
||||
int i; /* Iterate through azFmt[] and aMFile[] */
|
||||
|
||||
const char *azFmt[] = { "%s", "%s-journal", "%s-wal", "%s-shm" };
|
||||
|
||||
struct MFile {
|
||||
const char *zFmt;
|
||||
int iOffset;
|
||||
int b83;
|
||||
} aMFile[] = {
|
||||
{ "%s%03d", 0, 0 },
|
||||
{ "%s-journal%03d", 0, 0 },
|
||||
{ "%s-wal%03d", 0, 0 },
|
||||
{ "%s%03d", 0, 1 },
|
||||
{ "%s-journal%03d", SQLITE_MULTIPLEX_JOURNAL_8_3_OFFSET, 1 },
|
||||
{ "%s-wal%03d", SQLITE_MULTIPLEX_WAL_8_3_OFFSET, 1 },
|
||||
};
|
||||
|
||||
/* Allocate a buffer large enough for any of the files that need to be
|
||||
** deleted. */
|
||||
nBuf = strlen(zFile) + 100;
|
||||
zBuf = (char*)sqlite3_malloc(nBuf);
|
||||
if( zBuf==0 ) return SQLITE_NOMEM;
|
||||
|
||||
/* Delete both the regular and 8.3 filenames versions of the database,
|
||||
** journal, wal and shm files. */
|
||||
for(i=0; rc==0 && i<sizeof(azFmt)/sizeof(azFmt[0]); i++){
|
||||
sqlite3_snprintf(nBuf, zBuf, azFmt[i], zFile);
|
||||
rc = sqlite3DeleteUnlinkIfExists(zBuf, 0);
|
||||
if( rc==0 && i!=0 ){
|
||||
sqlite3Delete83Name(zBuf);
|
||||
rc = sqlite3DeleteUnlinkIfExists(zBuf, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Delete any multiplexor files */
|
||||
for(i=0; rc==0 && i<sizeof(aMFile)/sizeof(aMFile[0]); i++){
|
||||
struct MFile *p = &aMFile[i];
|
||||
int iChunk;
|
||||
for(iChunk=1; iChunk<=MX_CHUNK_NUMBER; iChunk++){
|
||||
int bExists;
|
||||
sqlite3_snprintf(nBuf, zBuf, p->zFmt, zFile, iChunk+p->iOffset);
|
||||
if( p->b83 ) sqlite3Delete83Name(zBuf);
|
||||
rc = sqlite3DeleteUnlinkIfExists(zBuf, &bExists);
|
||||
if( bExists==0 || rc!=0 ) break;
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3_free(zBuf);
|
||||
return (rc ? SQLITE_ERROR : SQLITE_OK);
|
||||
}
|
||||
+1
-3
@@ -96,7 +96,6 @@ void sqlite3BeginTrigger(
|
||||
int iDb; /* The database to store the trigger in */
|
||||
Token *pName; /* The unqualified db name */
|
||||
DbFixer sFix; /* State vector for the DB fixer */
|
||||
int iTabDb; /* Index of the database holding pTab */
|
||||
|
||||
assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
|
||||
assert( pName2!=0 );
|
||||
@@ -209,10 +208,10 @@ void sqlite3BeginTrigger(
|
||||
" trigger on table: %S", pTableName, 0);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
int code = SQLITE_CREATE_TRIGGER;
|
||||
const char *zDb = db->aDb[iTabDb].zDbSName;
|
||||
const char *zDbTrig = isTemp ? db->aDb[1].zDbSName : zDb;
|
||||
@@ -880,7 +879,6 @@ static TriggerPrg *codeRowTrigger(
|
||||
}
|
||||
pProgram->nMem = pSubParse->nMem;
|
||||
pProgram->nCsr = pSubParse->nTab;
|
||||
pProgram->nOnce = pSubParse->nOnce;
|
||||
pProgram->token = (void *)pTrigger;
|
||||
pPrg->aColmask[0] = pSubParse->oldmask;
|
||||
pPrg->aColmask[1] = pSubParse->newmask;
|
||||
|
||||
+11
-26
@@ -1305,36 +1305,21 @@ int sqlite3SubInt64(i64 *pA, i64 iB){
|
||||
return sqlite3AddInt64(pA, -iB);
|
||||
}
|
||||
}
|
||||
#define TWOPOWER32 (((i64)1)<<32)
|
||||
#define TWOPOWER31 (((i64)1)<<31)
|
||||
int sqlite3MulInt64(i64 *pA, i64 iB){
|
||||
i64 iA = *pA;
|
||||
i64 iA1, iA0, iB1, iB0, r;
|
||||
|
||||
iA1 = iA/TWOPOWER32;
|
||||
iA0 = iA % TWOPOWER32;
|
||||
iB1 = iB/TWOPOWER32;
|
||||
iB0 = iB % TWOPOWER32;
|
||||
if( iA1==0 ){
|
||||
if( iB1==0 ){
|
||||
*pA *= iB;
|
||||
return 0;
|
||||
if( iB>0 ){
|
||||
if( iA>LARGEST_INT64/iB ) return 1;
|
||||
if( iA<SMALLEST_INT64/iB ) return 1;
|
||||
}else if( iB<0 ){
|
||||
if( iA>0 ){
|
||||
if( iB<SMALLEST_INT64/iA ) return 1;
|
||||
}else if( iA<0 ){
|
||||
if( iB==SMALLEST_INT64 ) return 1;
|
||||
if( iA==SMALLEST_INT64 ) return 1;
|
||||
if( -iA>LARGEST_INT64/-iB ) return 1;
|
||||
}
|
||||
r = iA0*iB1;
|
||||
}else if( iB1==0 ){
|
||||
r = iA1*iB0;
|
||||
}else{
|
||||
/* If both iA1 and iB1 are non-zero, overflow will result */
|
||||
return 1;
|
||||
}
|
||||
testcase( r==(-TWOPOWER31)-1 );
|
||||
testcase( r==(-TWOPOWER31) );
|
||||
testcase( r==TWOPOWER31 );
|
||||
testcase( r==TWOPOWER31-1 );
|
||||
if( r<(-TWOPOWER31) || r>=TWOPOWER31 ) return 1;
|
||||
r *= TWOPOWER32;
|
||||
if( sqlite3AddInt64(&r, iA0*iB0) ) return 1;
|
||||
*pA = r;
|
||||
*pA = iA*iB;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
+57
-56
@@ -1136,11 +1136,13 @@ case OP_Null: { /* out2 */
|
||||
cnt = pOp->p3-pOp->p2;
|
||||
assert( pOp->p3<=(p->nMem+1 - p->nCursor) );
|
||||
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
|
||||
pOut->n = 0;
|
||||
while( cnt>0 ){
|
||||
pOut++;
|
||||
memAboutToChange(p, pOut);
|
||||
sqlite3VdbeMemSetNull(pOut);
|
||||
pOut->flags = nullFlag;
|
||||
pOut->n = 0;
|
||||
cnt--;
|
||||
}
|
||||
break;
|
||||
@@ -2035,12 +2037,21 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
if( (flags1 | flags3)&MEM_Str ){
|
||||
if( (flags1 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
applyNumericAffinity(pIn1,0);
|
||||
testcase( flags3!=pIn3->flags ); /* Possible if pIn1==pIn3 */
|
||||
flags3 = pIn3->flags;
|
||||
}
|
||||
if( (flags3 & (MEM_Int|MEM_Real|MEM_Str))==MEM_Str ){
|
||||
applyNumericAffinity(pIn3,0);
|
||||
}
|
||||
}
|
||||
/* Handle the common case of integer comparison here, as an
|
||||
** optimization, to avoid a call to sqlite3MemCompare() */
|
||||
if( (pIn1->flags & pIn3->flags & MEM_Int)!=0 ){
|
||||
if( pIn3->u.i > pIn1->u.i ){ res = +1; goto compare_op; }
|
||||
if( pIn3->u.i < pIn1->u.i ){ res = -1; goto compare_op; }
|
||||
res = 0;
|
||||
goto compare_op;
|
||||
}
|
||||
}else if( affinity==SQLITE_AFF_TEXT ){
|
||||
if( (flags1 & MEM_Str)==0 && (flags1 & (MEM_Int|MEM_Real))!=0 ){
|
||||
testcase( pIn1->flags & MEM_Int );
|
||||
@@ -2048,7 +2059,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
sqlite3VdbeMemStringify(pIn1, encoding, 1);
|
||||
testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
|
||||
flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
|
||||
flags3 = pIn3->flags;
|
||||
assert( pIn1!=pIn3 );
|
||||
}
|
||||
if( (flags3 & MEM_Str)==0 && (flags3 & (MEM_Int|MEM_Real))!=0 ){
|
||||
testcase( pIn3->flags & MEM_Int );
|
||||
@@ -2059,16 +2070,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
}
|
||||
}
|
||||
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
|
||||
if( flags1 & MEM_Zero ){
|
||||
sqlite3VdbeMemExpandBlob(pIn1);
|
||||
flags1 &= ~MEM_Zero;
|
||||
}
|
||||
if( flags3 & MEM_Zero ){
|
||||
sqlite3VdbeMemExpandBlob(pIn3);
|
||||
flags3 &= ~MEM_Zero;
|
||||
}
|
||||
res = sqlite3MemCompare(pIn3, pIn1, pOp->p4.pColl);
|
||||
}
|
||||
compare_op:
|
||||
switch( pOp->opcode ){
|
||||
case OP_Eq: res2 = res==0; break;
|
||||
case OP_Ne: res2 = res; break;
|
||||
@@ -2119,11 +2123,11 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
|
||||
|
||||
/* Opcode: ElseNotEq * P2 * * *
|
||||
**
|
||||
** This opcode must immediately follow an Lt or Gt comparison operator.
|
||||
** If the operands in that previous comparison had been used with an Eq
|
||||
** operator and if the result of that Eq would be NULL or false (0), then
|
||||
** then jump to P2. If the result of comparing the two previous operands
|
||||
** using Eq would have been true (1), then fall through.
|
||||
** This opcode must immediately follow an OP_Lt or OP_Gt comparison operator.
|
||||
** If result of an OP_Eq comparison on the same two operands
|
||||
** would have be NULL or false (0), then then jump to P2.
|
||||
** If the result of an OP_Eq comparison on the two previous operands
|
||||
** would have been true (1), then fall through.
|
||||
*/
|
||||
case OP_ElseNotEq: { /* same as TK_ESCAPE, jump */
|
||||
assert( pOp>aOp );
|
||||
@@ -2330,22 +2334,18 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */
|
||||
|
||||
/* Opcode: Once P1 P2 * * *
|
||||
**
|
||||
** Check the "once" flag number P1. If it is set, jump to instruction P2.
|
||||
** Otherwise, set the flag and fall through to the next instruction.
|
||||
** In other words, this opcode causes all following opcodes up through P2
|
||||
** (but not including P2) to run just once and to be skipped on subsequent
|
||||
** times through the loop.
|
||||
**
|
||||
** All "once" flags are initially cleared whenever a prepared statement
|
||||
** first begins to run.
|
||||
** If the P1 value is equal to the P1 value on the OP_Init opcode at
|
||||
** instruction 0, then jump to P2. If the two P1 values differ, then
|
||||
** set the P1 value on this opcode to equal the P1 value on the OP_Init
|
||||
** and fall through.
|
||||
*/
|
||||
case OP_Once: { /* jump */
|
||||
assert( pOp->p1<p->nOnceFlag );
|
||||
VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
|
||||
if( p->aOnceFlag[pOp->p1] ){
|
||||
assert( p->aOp[0].opcode==OP_Init );
|
||||
VdbeBranchTaken(p->aOp[0].p1==pOp->p1, 2);
|
||||
if( p->aOp[0].p1==pOp->p1 ){
|
||||
goto jump_to_p2;
|
||||
}else{
|
||||
p->aOnceFlag[pOp->p1] = 1;
|
||||
pOp->p1 = p->aOp[0].p1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3178,12 +3178,12 @@ case OP_Transaction: {
|
||||
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
|
||||
testcase( rc==SQLITE_BUSY_SNAPSHOT );
|
||||
testcase( rc==SQLITE_BUSY_RECOVERY );
|
||||
if( (rc&0xff)==SQLITE_BUSY ){
|
||||
p->pc = (int)(pOp - aOp);
|
||||
p->rc = rc;
|
||||
goto vdbe_return;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
if( (rc&0xff)==SQLITE_BUSY ){
|
||||
p->pc = (int)(pOp - aOp);
|
||||
p->rc = rc;
|
||||
goto vdbe_return;
|
||||
}
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
|
||||
@@ -3210,10 +3210,9 @@ case OP_Transaction: {
|
||||
}
|
||||
|
||||
/* Gather the schema version number for checking:
|
||||
** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite
|
||||
** each time a query is executed to ensure that the internal cache of the
|
||||
** schema used when compiling the SQL query matches the schema of the
|
||||
** database against which the compiled query is actually executed.
|
||||
** IMPLEMENTATION-OF: R-03189-51135 As each SQL statement runs, the schema
|
||||
** version is checked to ensure that the schema has not changed since the
|
||||
** SQL statement was prepared.
|
||||
*/
|
||||
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
|
||||
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
|
||||
@@ -3874,7 +3873,6 @@ case OP_SeekGT: { /* jump, in3 */
|
||||
#ifdef SQLITE_DEBUG
|
||||
{ int i; for(i=0; i<r.nField; i++) assert( memIsValid(&r.aMem[i]) ); }
|
||||
#endif
|
||||
ExpandBlob(r.aMem);
|
||||
r.eqSeen = 0;
|
||||
rc = sqlite3BtreeMovetoUnpacked(pC->uc.pCursor, &r, 0, 0, &res);
|
||||
if( rc!=SQLITE_OK ){
|
||||
@@ -4015,13 +4013,13 @@ case OP_Found: { /* jump, in3 */
|
||||
r.pKeyInfo = pC->pKeyInfo;
|
||||
r.nField = (u16)pOp->p4.i;
|
||||
r.aMem = pIn3;
|
||||
#ifdef SQLITE_DEBUG
|
||||
for(ii=0; ii<r.nField; ii++){
|
||||
assert( memIsValid(&r.aMem[ii]) );
|
||||
ExpandBlob(&r.aMem[ii]);
|
||||
#ifdef SQLITE_DEBUG
|
||||
assert( (r.aMem[ii].flags & MEM_Zero)==0 || r.aMem[ii].n==0 );
|
||||
if( ii ) REGISTER_TRACE(pOp->p3+ii, &r.aMem[ii]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
pIdxKey = &r;
|
||||
}else{
|
||||
pIdxKey = sqlite3VdbeAllocUnpackedRecord(
|
||||
@@ -4029,7 +4027,7 @@ case OP_Found: { /* jump, in3 */
|
||||
);
|
||||
if( pIdxKey==0 ) goto no_mem;
|
||||
assert( pIn3->flags & MEM_Blob );
|
||||
ExpandBlob(pIn3);
|
||||
(void)ExpandBlob(pIn3);
|
||||
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
|
||||
}
|
||||
pIdxKey->default_rc = 0;
|
||||
@@ -4470,7 +4468,7 @@ case OP_InsertInt: {
|
||||
** P1 must not be pseudo-table. It has to be a real table with
|
||||
** multiple rows.
|
||||
**
|
||||
** If P4 is not NULL then it points to a Table struture. In this case either
|
||||
** If P4 is not NULL then it points to a Table object. In this case either
|
||||
** the update or pre-update hook, or both, may be invoked. The P1 cursor must
|
||||
** have been positioned using OP_NotFound prior to invoking this opcode in
|
||||
** this case. Specifically, if one is configured, the pre-update hook is
|
||||
@@ -5061,9 +5059,6 @@ case OP_IdxInsert: { /* in2 */
|
||||
}else{
|
||||
x.nKey = pIn2->n;
|
||||
x.pKey = pIn2->z;
|
||||
x.nData = 0;
|
||||
x.nZero = 0;
|
||||
x.pData = 0;
|
||||
rc = sqlite3BtreeInsert(pC->uc.pCursor, &x, pOp->p3,
|
||||
((pOp->p5 & OPFLAG_USESEEKRESULT) ? pC->seekResult : 0)
|
||||
);
|
||||
@@ -5788,8 +5783,7 @@ case OP_Program: { /* jump */
|
||||
if( pProgram->nCsr==0 ) nMem++;
|
||||
nByte = ROUND8(sizeof(VdbeFrame))
|
||||
+ nMem * sizeof(Mem)
|
||||
+ pProgram->nCsr * sizeof(VdbeCursor *)
|
||||
+ pProgram->nOnce * sizeof(u8);
|
||||
+ pProgram->nCsr * sizeof(VdbeCursor *);
|
||||
pFrame = sqlite3DbMallocZero(db, nByte);
|
||||
if( !pFrame ){
|
||||
goto no_mem;
|
||||
@@ -5809,8 +5803,6 @@ case OP_Program: { /* jump */
|
||||
pFrame->aOp = p->aOp;
|
||||
pFrame->nOp = p->nOp;
|
||||
pFrame->token = pProgram->token;
|
||||
pFrame->aOnceFlag = p->aOnceFlag;
|
||||
pFrame->nOnceFlag = p->nOnceFlag;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
pFrame->anExec = p->anExec;
|
||||
#endif
|
||||
@@ -5844,13 +5836,10 @@ case OP_Program: { /* jump */
|
||||
p->apCsr = (VdbeCursor **)&aMem[p->nMem];
|
||||
p->aOp = aOp = pProgram->aOp;
|
||||
p->nOp = pProgram->nOp;
|
||||
p->aOnceFlag = (u8 *)&p->apCsr[p->nCursor];
|
||||
p->nOnceFlag = pProgram->nOnce;
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
p->anExec = 0;
|
||||
#endif
|
||||
pOp = &aOp[-1];
|
||||
memset(p->aOnceFlag, 0, p->nOnceFlag);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -6817,7 +6806,7 @@ case OP_MaxPgcnt: { /* out2 */
|
||||
#endif
|
||||
|
||||
|
||||
/* Opcode: Init * P2 * P4 *
|
||||
/* Opcode: Init P1 P2 * P4 *
|
||||
** Synopsis: Start at P2
|
||||
**
|
||||
** Programs contain a single instance of this opcode as the very first
|
||||
@@ -6828,9 +6817,13 @@ case OP_MaxPgcnt: { /* out2 */
|
||||
** Or if P4 is blank, use the string returned by sqlite3_sql().
|
||||
**
|
||||
** If P2 is not zero, jump to instruction P2.
|
||||
**
|
||||
** Increment the value of P1 so that OP_Once opcodes will jump the
|
||||
** first time they are evaluated for this run.
|
||||
*/
|
||||
case OP_Init: { /* jump */
|
||||
char *zTrace;
|
||||
int i;
|
||||
|
||||
/* If the P4 argument is not NULL, then it must be an SQL comment string.
|
||||
** The "--" string is broken up to prevent false-positives with srcck1.c.
|
||||
@@ -6842,6 +6835,7 @@ case OP_Init: { /* jump */
|
||||
** sqlite3_expanded_sql(P) otherwise.
|
||||
*/
|
||||
assert( pOp->p4.z==0 || strncmp(pOp->p4.z, "-" "- ", 3)==0 );
|
||||
assert( pOp==p->aOp ); /* Always instruction 0 */
|
||||
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
if( (db->mTrace & (SQLITE_TRACE_STMT|SQLITE_TRACE_LEGACY))!=0
|
||||
@@ -6863,10 +6857,10 @@ case OP_Init: { /* jump */
|
||||
#ifdef SQLITE_USE_FCNTL_TRACE
|
||||
zTrace = (pOp->p4.z ? pOp->p4.z : p->zSql);
|
||||
if( zTrace ){
|
||||
int i;
|
||||
for(i=0; i<db->nDb; i++){
|
||||
if( DbMaskTest(p->btreeMask, i)==0 ) continue;
|
||||
sqlite3_file_control(db, db->aDb[i].zDbSName, SQLITE_FCNTL_TRACE, zTrace);
|
||||
int j;
|
||||
for(j=0; j<db->nDb; j++){
|
||||
if( DbMaskTest(p->btreeMask, j)==0 ) continue;
|
||||
sqlite3_file_control(db, db->aDb[j].zDbSName, SQLITE_FCNTL_TRACE, zTrace);
|
||||
}
|
||||
}
|
||||
#endif /* SQLITE_USE_FCNTL_TRACE */
|
||||
@@ -6879,6 +6873,13 @@ case OP_Init: { /* jump */
|
||||
#endif /* SQLITE_DEBUG */
|
||||
#endif /* SQLITE_OMIT_TRACE */
|
||||
assert( pOp->p2>0 );
|
||||
if( pOp->p1>=sqlite3GlobalConfig.iOnceResetThreshold ){
|
||||
for(i=1; i<p->nOp; i++){
|
||||
if( p->aOp[i].opcode==OP_Once ) p->aOp[i].p1 = 0;
|
||||
}
|
||||
pOp->p1 = 0;
|
||||
}
|
||||
pOp->p1++;
|
||||
goto jump_to_p2;
|
||||
}
|
||||
|
||||
|
||||
@@ -88,7 +88,6 @@ struct SubProgram {
|
||||
int nOp; /* Elements in aOp[] */
|
||||
int nMem; /* Number of memory cells required */
|
||||
int nCsr; /* Number of cursors required */
|
||||
int nOnce; /* Number of OP_Once instructions */
|
||||
void *token; /* id that may be used to recursive triggers */
|
||||
SubProgram *pNext; /* Next sub-program already visited */
|
||||
};
|
||||
|
||||
+36
-49
@@ -52,9 +52,6 @@ typedef unsigned Bool;
|
||||
/* Opaque type used by code in vdbesort.c */
|
||||
typedef struct VdbeSorter VdbeSorter;
|
||||
|
||||
/* Opaque type used by the explainer */
|
||||
typedef struct Explain Explain;
|
||||
|
||||
/* Elements of the linked list at Vdbe.pAuxData */
|
||||
typedef struct AuxData AuxData;
|
||||
|
||||
@@ -129,6 +126,12 @@ struct VdbeCursor {
|
||||
** aType[] and nField+1 array slots for aOffset[] */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
** A value for VdbeCursor.cacheStatus that means the cache is always invalid.
|
||||
*/
|
||||
#define CACHE_STALE 0
|
||||
|
||||
/*
|
||||
** When a sub-program is executed (OP_Program), a structure of this type
|
||||
** is allocated to store the current value of the program counter, as
|
||||
@@ -157,7 +160,6 @@ struct VdbeFrame {
|
||||
Op *aOp; /* Program instructions for parent frame */
|
||||
i64 *anExec; /* Event counters from parent frame */
|
||||
Mem *aMem; /* Array of memory cells for parent frame */
|
||||
u8 *aOnceFlag; /* Array of OP_Once flags for parent frame */
|
||||
VdbeCursor **apCsr; /* Array of Vdbe cursors for parent frame */
|
||||
void *token; /* Copy of SubProgram.token */
|
||||
i64 lastRowid; /* Last insert rowid (sqlite3.lastRowid) */
|
||||
@@ -166,7 +168,6 @@ struct VdbeFrame {
|
||||
int pc; /* Program Counter in parent (calling) frame */
|
||||
int nOp; /* Size of aOp array */
|
||||
int nMem; /* Number of entries in aMem */
|
||||
int nOnceFlag; /* Number of entries in aOnceFlag */
|
||||
int nChildMem; /* Number of memory cells for child frame */
|
||||
int nChildCsr; /* Number of cursors for child frame */
|
||||
int nChange; /* Statement changes (Vdbe.nChange) */
|
||||
@@ -175,11 +176,6 @@ struct VdbeFrame {
|
||||
|
||||
#define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
|
||||
|
||||
/*
|
||||
** A value for VdbeCursor.cacheValid that means the cache is always invalid.
|
||||
*/
|
||||
#define CACHE_STALE 0
|
||||
|
||||
/*
|
||||
** Internally, the vdbe manipulates nearly all SQL values as Mem
|
||||
** structures. Each Mem struct may cache multiple representations (string,
|
||||
@@ -320,18 +316,6 @@ struct sqlite3_context {
|
||||
sqlite3_value *argv[1]; /* Argument set */
|
||||
};
|
||||
|
||||
/*
|
||||
** An Explain object accumulates indented output which is helpful
|
||||
** in describing recursive data structures.
|
||||
*/
|
||||
struct Explain {
|
||||
Vdbe *pVdbe; /* Attach the explanation to this Vdbe */
|
||||
StrAccum str; /* The string being accumulated */
|
||||
int nIndent; /* Number of elements in aIndent */
|
||||
u16 aIndent[100]; /* Levels of indentation */
|
||||
char zBase[100]; /* Initial space */
|
||||
};
|
||||
|
||||
/* A bitfield type for use inside of structures. Always follow with :N where
|
||||
** N is the number of bits.
|
||||
*/
|
||||
@@ -356,34 +340,47 @@ struct ScanStatus {
|
||||
*/
|
||||
struct Vdbe {
|
||||
sqlite3 *db; /* The database connection that owns this statement */
|
||||
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
|
||||
Parse *pParse; /* Parsing context used to create this Vdbe */
|
||||
ynVar nVar; /* Number of entries in aVar[] */
|
||||
ynVar nzVar; /* Number of entries in azVar[] */
|
||||
u32 magic; /* Magic number for sanity checking */
|
||||
int nMem; /* Number of memory locations currently allocated */
|
||||
int nCursor; /* Number of slots in apCsr[] */
|
||||
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
||||
int pc; /* The program counter */
|
||||
int rc; /* Value to return */
|
||||
int nChange; /* Number of db changes made since last reset */
|
||||
int iStatement; /* Statement number (or 0 if has not opened stmt) */
|
||||
i64 iCurrentTime; /* Value of julianday('now') for this statement */
|
||||
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
|
||||
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
|
||||
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
|
||||
|
||||
/* When allocating a new Vdbe object, all of the fields below should be
|
||||
** initialized to zero or NULL */
|
||||
|
||||
Op *aOp; /* Space to hold the virtual machine's program */
|
||||
Mem *aMem; /* The memory locations */
|
||||
Mem **apArg; /* Arguments to currently executing user function */
|
||||
Mem *aColName; /* Column names to return */
|
||||
Mem *pResultSet; /* Pointer to an array of results */
|
||||
Parse *pParse; /* Parsing context used to create this Vdbe */
|
||||
int nMem; /* Number of memory locations currently allocated */
|
||||
int nOp; /* Number of instructions in the program */
|
||||
int nCursor; /* Number of slots in apCsr[] */
|
||||
u32 magic; /* Magic number for sanity checking */
|
||||
char *zErrMsg; /* Error message written here */
|
||||
Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
|
||||
VdbeCursor **apCsr; /* One element of this array for each open cursor */
|
||||
Mem *aVar; /* Values for the OP_Variable opcode. */
|
||||
char **azVar; /* Name of variables */
|
||||
ynVar nVar; /* Number of entries in aVar[] */
|
||||
ynVar nzVar; /* Number of entries in azVar[] */
|
||||
u32 cacheCtr; /* VdbeCursor row cache generation counter */
|
||||
int pc; /* The program counter */
|
||||
int rc; /* Value to return */
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
i64 startTime; /* Time when query started - used for profiling */
|
||||
#endif
|
||||
int nOp; /* Number of instructions in the program */
|
||||
#ifdef SQLITE_DEBUG
|
||||
int rcApp; /* errcode set by sqlite3_result_error_code() */
|
||||
#endif
|
||||
u16 nResColumn; /* Number of columns in one row of the result set */
|
||||
u8 errorAction; /* Recovery action to do in case of an error */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
bft expired:1; /* True if the VM needs to be recompiled */
|
||||
bft doingRerun:1; /* True if rerunning after an auto-reprepare */
|
||||
u8 minWriteFileFormat; /* Minimum file format for writable database files */
|
||||
bft explain:2; /* True if EXPLAIN present on SQL command */
|
||||
bft changeCntOn:1; /* True to update the change-counter */
|
||||
bft runOnlyOnce:1; /* Automatically expire on reset */
|
||||
@@ -391,18 +388,9 @@ struct Vdbe {
|
||||
bft readOnly:1; /* True for statements that do not write */
|
||||
bft bIsReader:1; /* True for statements that read */
|
||||
bft isPrepareV2:1; /* True if prepared with prepare_v2() */
|
||||
int nChange; /* Number of db changes made since last reset */
|
||||
yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */
|
||||
yDbMask lockMask; /* Subset of btreeMask that requires a lock */
|
||||
int iStatement; /* Statement number (or 0 if has not opened stmt) */
|
||||
u32 aCounter[5]; /* Counters used by sqlite3_stmt_status() */
|
||||
#ifndef SQLITE_OMIT_TRACE
|
||||
i64 startTime; /* Time when query started - used for profiling */
|
||||
#endif
|
||||
i64 iCurrentTime; /* Value of julianday('now') for this statement */
|
||||
i64 nFkConstraint; /* Number of imm. FK constraints this VM */
|
||||
i64 nStmtDefCons; /* Number of def. constraints when stmt started */
|
||||
i64 nStmtDefImmCons; /* Number of def. imm constraints when stmt started */
|
||||
char *zSql; /* Text of the SQL statement that generated this */
|
||||
void *pFree; /* Free this when deleting the vdbe */
|
||||
VdbeFrame *pFrame; /* Parent frame */
|
||||
@@ -410,8 +398,6 @@ struct Vdbe {
|
||||
int nFrame; /* Number of frames in pFrame list */
|
||||
u32 expmask; /* Binding to these vars invalidates VM */
|
||||
SubProgram *pProgram; /* Linked list of all sub-programs used by VM */
|
||||
int nOnceFlag; /* Size of array aOnceFlag[] */
|
||||
u8 *aOnceFlag; /* Flags for OP_Once */
|
||||
AuxData *pAuxData; /* Linked list of auxdata allocations */
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
i64 *anExec; /* Number of times each op has been executed */
|
||||
@@ -423,10 +409,11 @@ struct Vdbe {
|
||||
/*
|
||||
** The following are allowed values for Vdbe.magic
|
||||
*/
|
||||
#define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */
|
||||
#define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */
|
||||
#define VDBE_MAGIC_HALT 0x519c2973 /* VDBE has completed execution */
|
||||
#define VDBE_MAGIC_DEAD 0xb606c3c8 /* The VDBE has been deallocated */
|
||||
#define VDBE_MAGIC_INIT 0x16bceaa5 /* Building a VDBE program */
|
||||
#define VDBE_MAGIC_RUN 0x2df20da3 /* VDBE is ready to execute */
|
||||
#define VDBE_MAGIC_HALT 0x319c2973 /* VDBE has completed execution */
|
||||
#define VDBE_MAGIC_RESET 0x48fa9f76 /* Reset and ready to run again */
|
||||
#define VDBE_MAGIC_DEAD 0x5606c3c8 /* The VDBE has been deallocated */
|
||||
|
||||
/*
|
||||
** Structure used to store the context required by the
|
||||
|
||||
+10
-9
@@ -169,7 +169,7 @@ int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
|
||||
const void *sqlite3_value_blob(sqlite3_value *pVal){
|
||||
Mem *p = (Mem*)pVal;
|
||||
if( p->flags & (MEM_Blob|MEM_Str) ){
|
||||
if( sqlite3VdbeMemExpandBlob(p)!=SQLITE_OK ){
|
||||
if( ExpandBlob(p)!=SQLITE_OK ){
|
||||
assert( p->flags==MEM_Null && p->z==0 );
|
||||
return 0;
|
||||
}
|
||||
@@ -952,14 +952,13 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
|
||||
Mem *pOut;
|
||||
|
||||
pVm = (Vdbe *)pStmt;
|
||||
if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
|
||||
sqlite3_mutex_enter(pVm->db->mutex);
|
||||
if( pVm==0 ) return (Mem*)columnNullValue();
|
||||
assert( pVm->db );
|
||||
sqlite3_mutex_enter(pVm->db->mutex);
|
||||
if( pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
|
||||
pOut = &pVm->pResultSet[i];
|
||||
}else{
|
||||
if( pVm && ALWAYS(pVm->db) ){
|
||||
sqlite3_mutex_enter(pVm->db->mutex);
|
||||
sqlite3Error(pVm->db, SQLITE_RANGE);
|
||||
}
|
||||
sqlite3Error(pVm->db, SQLITE_RANGE);
|
||||
pOut = (Mem*)columnNullValue();
|
||||
}
|
||||
return pOut;
|
||||
@@ -992,6 +991,8 @@ static void columnMallocFailure(sqlite3_stmt *pStmt)
|
||||
*/
|
||||
Vdbe *p = (Vdbe *)pStmt;
|
||||
if( p ){
|
||||
assert( p->db!=0 );
|
||||
assert( sqlite3_mutex_held(p->db->mutex) );
|
||||
p->rc = sqlite3ApiExit(p->db, p->rc);
|
||||
sqlite3_mutex_leave(p->db->mutex);
|
||||
}
|
||||
@@ -1568,7 +1569,7 @@ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
|
||||
*/
|
||||
int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
|
||||
Vdbe *v = (Vdbe*)pStmt;
|
||||
return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
|
||||
return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1775,7 +1776,7 @@ int sqlite3_preupdate_new(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
||||
UnpackedRecord *pUnpack = p->pNewUnpacked;
|
||||
if( !pUnpack ){
|
||||
Mem *pData = &p->v->aMem[p->iNewReg];
|
||||
rc = sqlite3VdbeMemExpandBlob(pData);
|
||||
rc = ExpandBlob(pData);
|
||||
if( rc!=SQLITE_OK ) goto preupdate_new_out;
|
||||
pUnpack = vdbeUnpackRecord(&p->keyinfo, pData->n, pData->z);
|
||||
if( !pUnpack ){
|
||||
|
||||
+94
-50
@@ -21,8 +21,9 @@
|
||||
Vdbe *sqlite3VdbeCreate(Parse *pParse){
|
||||
sqlite3 *db = pParse->db;
|
||||
Vdbe *p;
|
||||
p = sqlite3DbMallocZero(db, sizeof(Vdbe) );
|
||||
p = sqlite3DbMallocRawNN(db, sizeof(Vdbe) );
|
||||
if( p==0 ) return 0;
|
||||
memset(&p->aOp, 0, sizeof(Vdbe)-offsetof(Vdbe,aOp));
|
||||
p->db = db;
|
||||
if( db->pVdbe ){
|
||||
db->pVdbe->pPrev = p;
|
||||
@@ -184,9 +185,8 @@ int sqlite3VdbeAddOp3(Vdbe *p, int op, int p1, int p2, int p3){
|
||||
if( p->db->flags & SQLITE_VdbeAddopTrace ){
|
||||
int jj, kk;
|
||||
Parse *pParse = p->pParse;
|
||||
for(jj=kk=0; jj<SQLITE_N_COLCACHE; jj++){
|
||||
for(jj=kk=0; jj<pParse->nColCache; jj++){
|
||||
struct yColCache *x = pParse->aColCache + jj;
|
||||
if( x->iLevel>pParse->iCacheLevel || x->iReg==0 ) continue;
|
||||
printf(" r[%d]={%d:%d}", x->iReg, x->iTable, x->iColumn);
|
||||
kk++;
|
||||
}
|
||||
@@ -374,7 +374,6 @@ void sqlite3VdbeResolveLabel(Vdbe *v, int x){
|
||||
if( p->aLabel ){
|
||||
p->aLabel[j] = v->nOp;
|
||||
}
|
||||
p->iFixedOp = v->nOp - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -765,7 +764,8 @@ void sqlite3VdbeChangeP3(Vdbe *p, u32 addr, int val){
|
||||
sqlite3VdbeGetOp(p,addr)->p3 = val;
|
||||
}
|
||||
void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
|
||||
if( !p->db->mallocFailed ) p->aOp[p->nOp-1].p5 = p5;
|
||||
assert( p->nOp>0 || p->db->mallocFailed );
|
||||
if( p->nOp>0 ) p->aOp[p->nOp-1].p5 = p5;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -773,7 +773,6 @@ void sqlite3VdbeChangeP5(Vdbe *p, u8 p5){
|
||||
** the address of the next instruction to be coded.
|
||||
*/
|
||||
void sqlite3VdbeJumpHere(Vdbe *p, int addr){
|
||||
p->pParse->iFixedOp = p->nOp - 1;
|
||||
sqlite3VdbeChangeP2(p, addr, p->nOp);
|
||||
}
|
||||
|
||||
@@ -896,7 +895,7 @@ int sqlite3VdbeChangeToNoop(Vdbe *p, int addr){
|
||||
** then remove it. Return true if and only if an opcode was removed.
|
||||
*/
|
||||
int sqlite3VdbeDeletePriorOpcode(Vdbe *p, u8 op){
|
||||
if( (p->nOp-1)>(p->pParse->iFixedOp) && p->aOp[p->nOp-1].opcode==op ){
|
||||
if( p->nOp>0 && p->aOp[p->nOp-1].opcode==op ){
|
||||
return sqlite3VdbeChangeToNoop(p, p->nOp-1);
|
||||
}else{
|
||||
return 0;
|
||||
@@ -1459,6 +1458,21 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Initialize an array of N Mem element.
|
||||
*/
|
||||
static void initMemArray(Mem *p, int N, sqlite3 *db, u16 flags){
|
||||
while( (N--)>0 ){
|
||||
p->db = db;
|
||||
p->flags = flags;
|
||||
p->szMalloc = 0;
|
||||
#ifdef SQLITE_DEBUG
|
||||
p->pScopyFrom = 0;
|
||||
#endif
|
||||
p++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Release an array of N Mem elements
|
||||
*/
|
||||
@@ -1670,6 +1684,7 @@ int sqlite3VdbeList(
|
||||
pMem->flags = MEM_Str|MEM_Term;
|
||||
zP4 = displayP4(pOp, pMem->z, pMem->szMalloc);
|
||||
if( zP4!=pMem->z ){
|
||||
pMem->n = 0;
|
||||
sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0);
|
||||
}else{
|
||||
assert( pMem->z!=0 );
|
||||
@@ -1812,7 +1827,7 @@ void sqlite3VdbeRewind(Vdbe *p){
|
||||
int i;
|
||||
#endif
|
||||
assert( p!=0 );
|
||||
assert( p->magic==VDBE_MAGIC_INIT );
|
||||
assert( p->magic==VDBE_MAGIC_INIT || p->magic==VDBE_MAGIC_RESET );
|
||||
|
||||
/* There should be at least one opcode.
|
||||
*/
|
||||
@@ -1869,7 +1884,6 @@ void sqlite3VdbeMakeReady(
|
||||
int nMem; /* Number of VM memory registers */
|
||||
int nCursor; /* Number of cursors required */
|
||||
int nArg; /* Number of arguments in subprograms */
|
||||
int nOnce; /* Number of OP_Once instructions */
|
||||
int n; /* Loop counter */
|
||||
struct ReusableSpace x; /* Reusable bulk memory */
|
||||
|
||||
@@ -1884,8 +1898,6 @@ void sqlite3VdbeMakeReady(
|
||||
nMem = pParse->nMem;
|
||||
nCursor = pParse->nTab;
|
||||
nArg = pParse->nMaxArg;
|
||||
nOnce = pParse->nOnce;
|
||||
if( nOnce==0 ) nOnce = 1; /* Ensure at least one byte in p->aOnceFlag[] */
|
||||
|
||||
/* Each cursor uses a memory cell. The first cursor (cursor 0) can
|
||||
** use aMem[0] which is not otherwise used by the VDBE program. Allocate
|
||||
@@ -1904,10 +1916,7 @@ void sqlite3VdbeMakeReady(
|
||||
assert( EIGHT_BYTE_ALIGNMENT(x.pSpace) );
|
||||
x.nFree = ROUNDDOWN8(pParse->szOpAlloc - n); /* Bytes of unused memory */
|
||||
assert( x.nFree>=0 );
|
||||
if( x.nFree>0 ){
|
||||
memset(x.pSpace, 0, x.nFree);
|
||||
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
|
||||
}
|
||||
assert( EIGHT_BYTE_ALIGNMENT(&x.pSpace[x.nFree]) );
|
||||
|
||||
resolveP2Values(p, &nArg);
|
||||
p->usesStmtJournal = (u8)(pParse->isMultiWrite && pParse->mayAbort);
|
||||
@@ -1932,36 +1941,34 @@ void sqlite3VdbeMakeReady(
|
||||
p->aVar = allocSpace(&x, p->aVar, nVar*sizeof(Mem));
|
||||
p->apArg = allocSpace(&x, p->apArg, nArg*sizeof(Mem*));
|
||||
p->apCsr = allocSpace(&x, p->apCsr, nCursor*sizeof(VdbeCursor*));
|
||||
p->aOnceFlag = allocSpace(&x, p->aOnceFlag, nOnce);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
p->anExec = allocSpace(&x, p->anExec, p->nOp*sizeof(i64));
|
||||
#endif
|
||||
if( x.nNeeded==0 ) break;
|
||||
x.pSpace = p->pFree = sqlite3DbMallocZero(db, x.nNeeded);
|
||||
x.pSpace = p->pFree = sqlite3DbMallocRawNN(db, x.nNeeded);
|
||||
x.nFree = x.nNeeded;
|
||||
}while( !db->mallocFailed );
|
||||
|
||||
p->nCursor = nCursor;
|
||||
p->nOnceFlag = nOnce;
|
||||
if( p->aVar ){
|
||||
p->nVar = (ynVar)nVar;
|
||||
for(n=0; n<nVar; n++){
|
||||
p->aVar[n].flags = MEM_Null;
|
||||
p->aVar[n].db = db;
|
||||
}
|
||||
}
|
||||
p->nzVar = pParse->nzVar;
|
||||
p->azVar = pParse->azVar;
|
||||
pParse->nzVar = 0;
|
||||
pParse->azVar = 0;
|
||||
if( p->aMem ){
|
||||
p->nMem = nMem;
|
||||
for(n=0; n<nMem; n++){
|
||||
p->aMem[n].flags = MEM_Undefined;
|
||||
p->aMem[n].db = db;
|
||||
}
|
||||
}
|
||||
p->explain = pParse->explain;
|
||||
if( db->mallocFailed ){
|
||||
p->nVar = 0;
|
||||
p->nCursor = 0;
|
||||
p->nMem = 0;
|
||||
}else{
|
||||
p->nCursor = nCursor;
|
||||
p->nVar = (ynVar)nVar;
|
||||
initMemArray(p->aVar, nVar, db, MEM_Null);
|
||||
p->nMem = nMem;
|
||||
initMemArray(p->aMem, nMem, db, MEM_Undefined);
|
||||
memset(p->apCsr, 0, nCursor*sizeof(VdbeCursor*));
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
memset(p->anExec, 0, p->nOp*sizeof(i64));
|
||||
#endif
|
||||
}
|
||||
sqlite3VdbeRewind(p);
|
||||
}
|
||||
|
||||
@@ -2030,8 +2037,6 @@ int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
v->anExec = pFrame->anExec;
|
||||
#endif
|
||||
v->aOnceFlag = pFrame->aOnceFlag;
|
||||
v->nOnceFlag = pFrame->nOnceFlag;
|
||||
v->aOp = pFrame->aOp;
|
||||
v->nOp = pFrame->nOp;
|
||||
v->aMem = pFrame->aMem;
|
||||
@@ -2115,13 +2120,9 @@ void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
|
||||
sqlite3DbFree(db, p->aColName);
|
||||
n = nResColumn*COLNAME_N;
|
||||
p->nResColumn = (u16)nResColumn;
|
||||
p->aColName = pColName = (Mem*)sqlite3DbMallocZero(db, sizeof(Mem)*n );
|
||||
p->aColName = pColName = (Mem*)sqlite3DbMallocRawNN(db, sizeof(Mem)*n );
|
||||
if( p->aColName==0 ) return;
|
||||
while( n-- > 0 ){
|
||||
pColName->flags = MEM_Null;
|
||||
pColName->db = p->db;
|
||||
pColName++;
|
||||
}
|
||||
initMemArray(p->aColName, n, p->db, MEM_Null);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2572,7 +2573,6 @@ int sqlite3VdbeHalt(Vdbe *p){
|
||||
if( db->mallocFailed ){
|
||||
p->rc = SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
if( p->aOnceFlag ) memset(p->aOnceFlag, 0, p->nOnceFlag);
|
||||
closeAllCursors(p);
|
||||
if( p->magic!=VDBE_MAGIC_RUN ){
|
||||
return SQLITE_OK;
|
||||
@@ -2884,7 +2884,7 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
}
|
||||
#endif
|
||||
p->iCurrentTime = 0;
|
||||
p->magic = VDBE_MAGIC_INIT;
|
||||
p->magic = VDBE_MAGIC_RESET;
|
||||
return p->rc & db->errMask;
|
||||
}
|
||||
|
||||
@@ -2948,19 +2948,21 @@ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){
|
||||
SubProgram *pSub, *pNext;
|
||||
int i;
|
||||
assert( p->db==0 || p->db==db );
|
||||
releaseMemArray(p->aVar, p->nVar);
|
||||
releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
|
||||
for(pSub=p->pProgram; pSub; pSub=pNext){
|
||||
pNext = pSub->pNext;
|
||||
vdbeFreeOpArray(db, pSub->aOp, pSub->nOp);
|
||||
sqlite3DbFree(db, pSub);
|
||||
}
|
||||
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
|
||||
sqlite3DbFree(db, p->azVar);
|
||||
if( p->magic!=VDBE_MAGIC_INIT ){
|
||||
releaseMemArray(p->aVar, p->nVar);
|
||||
for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]);
|
||||
sqlite3DbFree(db, p->azVar);
|
||||
sqlite3DbFree(db, p->pFree);
|
||||
}
|
||||
vdbeFreeOpArray(db, p->aOp, p->nOp);
|
||||
sqlite3DbFree(db, p->aColName);
|
||||
sqlite3DbFree(db, p->zSql);
|
||||
sqlite3DbFree(db, p->pFree);
|
||||
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
||||
for(i=0; i<p->nScan; i++){
|
||||
sqlite3DbFree(db, p->aScan[i].zName);
|
||||
@@ -3716,15 +3718,49 @@ static int vdbeCompareMemString(
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** The input pBlob is guaranteed to be a Blob that is not marked
|
||||
** with MEM_Zero. Return true if it could be a zero-blob.
|
||||
*/
|
||||
static int isAllZero(const char *z, int n){
|
||||
int i;
|
||||
for(i=0; i<n; i++){
|
||||
if( z[i] ) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
** Compare two blobs. Return negative, zero, or positive if the first
|
||||
** is less than, equal to, or greater than the second, respectively.
|
||||
** If one blob is a prefix of the other, then the shorter is the lessor.
|
||||
*/
|
||||
static SQLITE_NOINLINE int sqlite3BlobCompare(const Mem *pB1, const Mem *pB2){
|
||||
int c = memcmp(pB1->z, pB2->z, pB1->n>pB2->n ? pB2->n : pB1->n);
|
||||
int c;
|
||||
int n1 = pB1->n;
|
||||
int n2 = pB2->n;
|
||||
|
||||
/* It is possible to have a Blob value that has some non-zero content
|
||||
** followed by zero content. But that only comes up for Blobs formed
|
||||
** by the OP_MakeRecord opcode, and such Blobs never get passed into
|
||||
** sqlite3MemCompare(). */
|
||||
assert( (pB1->flags & MEM_Zero)==0 || n1==0 );
|
||||
assert( (pB2->flags & MEM_Zero)==0 || n2==0 );
|
||||
|
||||
if( (pB1->flags|pB2->flags) & MEM_Zero ){
|
||||
if( pB1->flags & pB2->flags & MEM_Zero ){
|
||||
return pB1->u.nZero - pB2->u.nZero;
|
||||
}else if( pB1->flags & MEM_Zero ){
|
||||
if( !isAllZero(pB2->z, pB2->n) ) return -1;
|
||||
return pB1->u.nZero - n2;
|
||||
}else{
|
||||
if( !isAllZero(pB1->z, pB1->n) ) return +1;
|
||||
return n1 - pB2->u.nZero;
|
||||
}
|
||||
}
|
||||
c = memcmp(pB1->z, pB2->z, n1>n2 ? n2 : n1);
|
||||
if( c ) return c;
|
||||
return pB1->n - pB2->n;
|
||||
return n1 - n2;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -4030,6 +4066,7 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
|
||||
/* RHS is a blob */
|
||||
else if( pRhs->flags & MEM_Blob ){
|
||||
assert( (pRhs->flags & MEM_Zero)==0 || pRhs->n==0 );
|
||||
getVarint32(&aKey1[idx1], serial_type);
|
||||
testcase( serial_type==12 );
|
||||
if( serial_type<12 || (serial_type & 0x01) ){
|
||||
@@ -4041,6 +4078,12 @@ int sqlite3VdbeRecordCompareWithSkip(
|
||||
if( (d1+nStr) > (unsigned)nKey1 ){
|
||||
pPKey2->errCode = (u8)SQLITE_CORRUPT_BKPT;
|
||||
return 0; /* Corruption */
|
||||
}else if( pRhs->flags & MEM_Zero ){
|
||||
if( !isAllZero((const char*)&aKey1[d1],nStr) ){
|
||||
rc = 1;
|
||||
}else{
|
||||
rc = nStr - pRhs->u.nZero;
|
||||
}
|
||||
}else{
|
||||
int nCmp = MIN(nStr, pRhs->n);
|
||||
rc = memcmp(&aKey1[d1], pRhs->z, nCmp);
|
||||
@@ -4111,7 +4154,7 @@ static int vdbeRecordCompareInt(
|
||||
int res;
|
||||
u32 y;
|
||||
u64 x;
|
||||
i64 v = pPKey2->aMem[0].u.i;
|
||||
i64 v;
|
||||
i64 lhs;
|
||||
|
||||
vdbeAssertFieldCountWithinLimits(nKey1, pKey1, pPKey2->pKeyInfo);
|
||||
@@ -4170,6 +4213,7 @@ static int vdbeRecordCompareInt(
|
||||
return sqlite3VdbeRecordCompare(nKey1, pKey1, pPKey2);
|
||||
}
|
||||
|
||||
v = pPKey2->aMem[0].u.i;
|
||||
if( v>lhs ){
|
||||
res = pPKey2->r1;
|
||||
}else if( v<lhs ){
|
||||
|
||||
+30
-36
@@ -189,18 +189,18 @@ int sqlite3VdbeMemClearAndResize(Mem *pMem, int szNew){
|
||||
** Return SQLITE_OK on success or SQLITE_NOMEM if malloc fails.
|
||||
*/
|
||||
int sqlite3VdbeMemMakeWriteable(Mem *pMem){
|
||||
int f;
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
assert( (pMem->flags&MEM_RowSet)==0 );
|
||||
ExpandBlob(pMem);
|
||||
f = pMem->flags;
|
||||
if( (f&(MEM_Str|MEM_Blob)) && (pMem->szMalloc==0 || pMem->z!=pMem->zMalloc) ){
|
||||
if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
if( (pMem->flags & (MEM_Str|MEM_Blob))!=0 ){
|
||||
if( ExpandBlob(pMem) ) return SQLITE_NOMEM;
|
||||
if( pMem->szMalloc==0 || pMem->z!=pMem->zMalloc ){
|
||||
if( sqlite3VdbeMemGrow(pMem, pMem->n + 2, 1) ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
pMem->z[pMem->n] = 0;
|
||||
pMem->z[pMem->n+1] = 0;
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
pMem->z[pMem->n] = 0;
|
||||
pMem->z[pMem->n+1] = 0;
|
||||
pMem->flags |= MEM_Term;
|
||||
}
|
||||
pMem->flags &= ~MEM_Ephem;
|
||||
#ifdef SQLITE_DEBUG
|
||||
@@ -216,25 +216,24 @@ int sqlite3VdbeMemMakeWriteable(Mem *pMem){
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_INCRBLOB
|
||||
int sqlite3VdbeMemExpandBlob(Mem *pMem){
|
||||
if( pMem->flags & MEM_Zero ){
|
||||
int nByte;
|
||||
assert( pMem->flags&MEM_Blob );
|
||||
assert( (pMem->flags&MEM_RowSet)==0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
int nByte;
|
||||
assert( pMem->flags & MEM_Zero );
|
||||
assert( pMem->flags&MEM_Blob );
|
||||
assert( (pMem->flags&MEM_RowSet)==0 );
|
||||
assert( pMem->db==0 || sqlite3_mutex_held(pMem->db->mutex) );
|
||||
|
||||
/* Set nByte to the number of bytes required to store the expanded blob. */
|
||||
nByte = pMem->n + pMem->u.nZero;
|
||||
if( nByte<=0 ){
|
||||
nByte = 1;
|
||||
}
|
||||
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
|
||||
pMem->n += pMem->u.nZero;
|
||||
pMem->flags &= ~(MEM_Zero|MEM_Term);
|
||||
/* Set nByte to the number of bytes required to store the expanded blob. */
|
||||
nByte = pMem->n + pMem->u.nZero;
|
||||
if( nByte<=0 ){
|
||||
nByte = 1;
|
||||
}
|
||||
if( sqlite3VdbeMemGrow(pMem, nByte, 1) ){
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
memset(&pMem->z[pMem->n], 0, pMem->u.nZero);
|
||||
pMem->n += pMem->u.nZero;
|
||||
pMem->flags &= ~(MEM_Zero|MEM_Term);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#endif
|
||||
@@ -294,6 +293,7 @@ int sqlite3VdbeMemStringify(Mem *pMem, u8 enc, u8 bForce){
|
||||
|
||||
|
||||
if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){
|
||||
pMem->enc = 0;
|
||||
return SQLITE_NOMEM_BKPT;
|
||||
}
|
||||
|
||||
@@ -575,7 +575,7 @@ int sqlite3VdbeMemNumerify(Mem *pMem){
|
||||
}
|
||||
}
|
||||
assert( (pMem->flags & (MEM_Int|MEM_Real|MEM_Null))!=0 );
|
||||
pMem->flags &= ~(MEM_Str|MEM_Blob);
|
||||
pMem->flags &= ~(MEM_Str|MEM_Blob|MEM_Zero);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
@@ -593,7 +593,7 @@ void sqlite3VdbeMemCast(Mem *pMem, u8 aff, u8 encoding){
|
||||
if( (pMem->flags & MEM_Blob)==0 ){
|
||||
sqlite3ValueApplyAffinity(pMem, SQLITE_AFF_TEXT, encoding);
|
||||
assert( pMem->flags & MEM_Str || pMem->db->mallocFailed );
|
||||
MemSetTypeFlag(pMem, MEM_Blob);
|
||||
if( pMem->flags & MEM_Str ) MemSetTypeFlag(pMem, MEM_Blob);
|
||||
}else{
|
||||
pMem->flags &= ~(MEM_TypeMask&~MEM_Blob);
|
||||
}
|
||||
@@ -1018,9 +1018,6 @@ static SQLITE_NOINLINE const void *valueToText(sqlite3_value* pVal, u8 enc){
|
||||
assert( (pVal->flags & (MEM_Null))==0 );
|
||||
if( pVal->flags & (MEM_Blob|MEM_Str) ){
|
||||
pVal->flags |= MEM_Str;
|
||||
if( pVal->flags & MEM_Zero ){
|
||||
sqlite3VdbeMemExpandBlob(pVal);
|
||||
}
|
||||
if( pVal->enc != (enc & ~SQLITE_UTF16_ALIGNED) ){
|
||||
sqlite3VdbeChangeEncoding(pVal, enc & ~SQLITE_UTF16_ALIGNED);
|
||||
}
|
||||
@@ -1273,10 +1270,7 @@ static int valueFromExpr(
|
||||
const char *zNeg = "";
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( !pExpr ){
|
||||
*ppVal = 0;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
assert( pExpr!=0 );
|
||||
while( (op = pExpr->op)==TK_UPLUS || op==TK_SPAN ) pExpr = pExpr->pLeft;
|
||||
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
|
||||
|
||||
@@ -1400,7 +1394,7 @@ int sqlite3ValueFromExpr(
|
||||
u8 affinity, /* Affinity to use */
|
||||
sqlite3_value **ppVal /* Write the new value here */
|
||||
){
|
||||
return valueFromExpr(db, pExpr, enc, affinity, ppVal, 0);
|
||||
return pExpr ? valueFromExpr(db, pExpr, enc, affinity, ppVal, 0) : 0;
|
||||
}
|
||||
|
||||
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
|
||||
|
||||
+4
-2
@@ -41,12 +41,14 @@ static SQLITE_NOINLINE int walkExpr(Walker *pWalker, Expr *pExpr){
|
||||
testcase( ExprHasProperty(pExpr, EP_TokenOnly) );
|
||||
testcase( ExprHasProperty(pExpr, EP_Reduced) );
|
||||
rc = pWalker->xExprCallback(pWalker, pExpr);
|
||||
if( rc || ExprHasProperty(pExpr,EP_TokenOnly) ) return rc & WRC_Abort;
|
||||
if( rc || ExprHasProperty(pExpr,(EP_TokenOnly|EP_Leaf)) ){
|
||||
return rc & WRC_Abort;
|
||||
}
|
||||
if( pExpr->pLeft && walkExpr(pWalker, pExpr->pLeft) ) return WRC_Abort;
|
||||
if( pExpr->pRight && walkExpr(pWalker, pExpr->pRight) ) return WRC_Abort;
|
||||
if( ExprHasProperty(pExpr, EP_xIsSelect) ){
|
||||
if( sqlite3WalkSelect(pWalker, pExpr->x.pSelect) ) return WRC_Abort;
|
||||
}else{
|
||||
}else if( pExpr->x.pList ){
|
||||
if( sqlite3WalkExprList(pWalker, pExpr->x.pList) ) return WRC_Abort;
|
||||
}
|
||||
return WRC_Continue;
|
||||
|
||||
+27
-13
@@ -651,7 +651,7 @@ static void constructAutomaticIndex(
|
||||
** transient index on 2nd and subsequent iterations of the loop. */
|
||||
v = pParse->pVdbe;
|
||||
assert( v!=0 );
|
||||
addrInit = sqlite3CodeOnce(pParse); VdbeCoverage(v);
|
||||
addrInit = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v);
|
||||
|
||||
/* Count the number of columns that will be added to the index
|
||||
** and used to match WHERE clause constraints */
|
||||
@@ -2223,7 +2223,7 @@ static void whereLoopOutputAdjust(
|
||||
** then this function would be invoked with nEq=1. The value returned in
|
||||
** this case is 3.
|
||||
*/
|
||||
int whereRangeVectorLen(
|
||||
static int whereRangeVectorLen(
|
||||
Parse *pParse, /* Parsing context */
|
||||
int iCur, /* Cursor open on pIdx */
|
||||
Index *pIdx, /* The index to be used for a inequality constraint */
|
||||
@@ -2322,6 +2322,8 @@ static int whereLoopAddBtreeIndex(
|
||||
|
||||
pNew = pBuilder->pNew;
|
||||
if( db->mallocFailed ) return SQLITE_NOMEM_BKPT;
|
||||
WHERETRACE(0x800, ("BEGIN addBtreeIdx(%s), nEq=%d\n",
|
||||
pProbe->zName, pNew->u.btree.nEq));
|
||||
|
||||
assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 );
|
||||
assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 );
|
||||
@@ -2408,7 +2410,7 @@ static int whereLoopAddBtreeIndex(
|
||||
** for each such term. The following loop checks that pTerm is the
|
||||
** first such term in use, and sets nIn back to 0 if it is not. */
|
||||
for(i=0; i<pNew->nLTerm-1; i++){
|
||||
if( pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
|
||||
if( pNew->aLTerm[i] && pNew->aLTerm[i]->pExpr==pExpr ) nIn = 0;
|
||||
}
|
||||
}else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
|
||||
/* "x IN (value, value, ...)" */
|
||||
@@ -2600,6 +2602,8 @@ static int whereLoopAddBtreeIndex(
|
||||
pNew->wsFlags = saved_wsFlags;
|
||||
}
|
||||
|
||||
WHERETRACE(0x800, ("END addBtreeIdx(%s), nEq=%d, rc=%d\n",
|
||||
pProbe->zName, saved_nEq, rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -3665,7 +3669,7 @@ static i8 wherePathSatisfiesOrderBy(
|
||||
}
|
||||
}
|
||||
if( isMatch ){
|
||||
if( iColumn<0 ){
|
||||
if( iColumn==XN_ROWID ){
|
||||
testcase( distinctColumns==0 );
|
||||
distinctColumns = 1;
|
||||
}
|
||||
@@ -4120,13 +4124,20 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
|
||||
pWInfo->revMask = pFrom->revLoop;
|
||||
if( pWInfo->nOBSat<=0 ){
|
||||
pWInfo->nOBSat = 0;
|
||||
if( nLoop>0 && (pFrom->aLoop[nLoop-1]->wsFlags & WHERE_ONEROW)==0 ){
|
||||
Bitmask m = 0;
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
|
||||
if( nLoop>0 ){
|
||||
u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags;
|
||||
if( (wsFlags & WHERE_ONEROW)==0
|
||||
&& (wsFlags&(WHERE_IPK|WHERE_COLUMN_IN))!=(WHERE_IPK|WHERE_COLUMN_IN)
|
||||
){
|
||||
Bitmask m = 0;
|
||||
int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
|
||||
WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
|
||||
if( rc==pWInfo->pOrderBy->nExpr ){
|
||||
pWInfo->bOrderedInnerLoop = 1;
|
||||
pWInfo->revMask = m;
|
||||
testcase( wsFlags & WHERE_IPK );
|
||||
testcase( wsFlags & WHERE_COLUMN_IN );
|
||||
if( rc==pWInfo->pOrderBy->nExpr ){
|
||||
pWInfo->bOrderedInnerLoop = 1;
|
||||
pWInfo->revMask = m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4403,22 +4414,25 @@ WhereInfo *sqlite3WhereBegin(
|
||||
** some architectures. Hence the ROUND8() below.
|
||||
*/
|
||||
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
|
||||
pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
|
||||
pWInfo = sqlite3DbMallocRawNN(db, nByteWInfo + sizeof(WhereLoop));
|
||||
if( db->mallocFailed ){
|
||||
sqlite3DbFree(db, pWInfo);
|
||||
pWInfo = 0;
|
||||
goto whereBeginError;
|
||||
}
|
||||
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
|
||||
pWInfo->nLevel = nTabList;
|
||||
pWInfo->pParse = pParse;
|
||||
pWInfo->pTabList = pTabList;
|
||||
pWInfo->pOrderBy = pOrderBy;
|
||||
pWInfo->pDistinctSet = pDistinctSet;
|
||||
pWInfo->aiCurOnePass[0] = pWInfo->aiCurOnePass[1] = -1;
|
||||
pWInfo->nLevel = nTabList;
|
||||
pWInfo->iBreak = pWInfo->iContinue = sqlite3VdbeMakeLabel(v);
|
||||
pWInfo->wctrlFlags = wctrlFlags;
|
||||
pWInfo->iLimit = iAuxArg;
|
||||
pWInfo->savedNQueryLoop = pParse->nQueryLoop;
|
||||
memset(&pWInfo->nOBSat, 0,
|
||||
offsetof(WhereInfo,sWC) - offsetof(WhereInfo,nOBSat));
|
||||
memset(&pWInfo->a[0], 0, sizeof(WhereLoop)+nTabList*sizeof(WhereLevel));
|
||||
assert( pWInfo->eOnePass==ONEPASS_OFF ); /* ONEPASS defaults to OFF */
|
||||
pMaskSet = &pWInfo->sMaskSet;
|
||||
sWLB.pWInfo = pWInfo;
|
||||
|
||||
+15
-15
@@ -246,6 +246,12 @@ struct WherePath {
|
||||
*/
|
||||
struct WhereTerm {
|
||||
Expr *pExpr; /* Pointer to the subexpression that is this term */
|
||||
WhereClause *pWC; /* The clause this term is part of */
|
||||
LogEst truthProb; /* Probability of truth for this expression */
|
||||
u16 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
|
||||
int iParent; /* Disable pWC->a[iParent] when this term disabled */
|
||||
int leftCursor; /* Cursor number of X in "X <op> <expr>" */
|
||||
int iField; /* Field in (?,?,?) IN (SELECT...) vector */
|
||||
@@ -254,12 +260,6 @@ struct WhereTerm {
|
||||
WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */
|
||||
WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */
|
||||
} u;
|
||||
LogEst truthProb; /* Probability of truth for this expression */
|
||||
u16 eOperator; /* A WO_xx value describing <op> */
|
||||
u16 wtFlags; /* TERM_xxx bit flags. See below */
|
||||
u8 nChild; /* Number of children that must disable us */
|
||||
u8 eMatchOp; /* Op for vtab MATCH/LIKE/GLOB/REGEXP terms */
|
||||
WhereClause *pWC; /* The clause this term is part of */
|
||||
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
|
||||
Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */
|
||||
};
|
||||
@@ -412,25 +412,25 @@ struct WhereInfo {
|
||||
SrcList *pTabList; /* List of tables in the join */
|
||||
ExprList *pOrderBy; /* The ORDER BY clause or NULL */
|
||||
ExprList *pDistinctSet; /* DISTINCT over all these values */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
LogEst iLimit; /* LIMIT if wctrlFlags has WHERE_USE_LIMIT */
|
||||
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
int iBreak; /* Jump here to break out of the loop */
|
||||
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
|
||||
u16 wctrlFlags; /* Flags originally passed to sqlite3WhereBegin() */
|
||||
u8 nLevel; /* Number of nested loop */
|
||||
i8 nOBSat; /* Number of ORDER BY terms satisfied by indices */
|
||||
u8 sorted; /* True if really sorted (not just grouped) */
|
||||
u8 eOnePass; /* ONEPASS_OFF, or _SINGLE, or _MULTI */
|
||||
u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */
|
||||
u8 eDistinct; /* One of the WHERE_DISTINCT_* values */
|
||||
u8 nLevel; /* Number of nested loop */
|
||||
u8 bOrderedInnerLoop; /* True if only the inner-most loop is ordered */
|
||||
int iTop; /* The very beginning of the WHERE loop */
|
||||
int iContinue; /* Jump here to continue with next record */
|
||||
int iBreak; /* Jump here to break out of the loop */
|
||||
int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */
|
||||
int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */
|
||||
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
|
||||
WhereLoop *pLoops; /* List of all WhereLoop objects */
|
||||
Bitmask revMask; /* Mask of ORDER BY terms that need reversing */
|
||||
LogEst nRowOut; /* Estimated number of output rows */
|
||||
WhereClause sWC; /* Decomposition of the WHERE clause */
|
||||
WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */
|
||||
WhereLevel a[1]; /* Information about each nest loop in WHERE */
|
||||
};
|
||||
|
||||
|
||||
+14
-20
@@ -361,7 +361,6 @@ static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
|
||||
** * the affinity change in zAff is guaranteed not to change the value.
|
||||
*/
|
||||
static void updateRangeAffinityStr(
|
||||
Parse *pParse, /* Parse context */
|
||||
Expr *pRight, /* RHS of comparison */
|
||||
int n, /* Number of vector elements in comparison */
|
||||
char *zAff /* Affinity string to modify */
|
||||
@@ -525,14 +524,13 @@ static int codeEqualityTerm(
|
||||
int iMap = 0; /* Index in aiMap[] */
|
||||
pIn += i;
|
||||
for(i=iEq;i<pLoop->nLTerm; i++){
|
||||
int iOut = iReg;
|
||||
if( pLoop->aLTerm[i]->pExpr==pX ){
|
||||
int iOut = iReg + i - iEq;
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
assert( nEq==1 && i==iEq );
|
||||
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iReg);
|
||||
testcase( nEq>1 ); /* Happens with a UNIQUE index on ROWID */
|
||||
pIn->addrInTop = sqlite3VdbeAddOp2(v, OP_Rowid, iTab, iOut);
|
||||
}else{
|
||||
int iCol = aiMap ? aiMap[iMap++] : 0;
|
||||
iOut = iReg + i - iEq;
|
||||
pIn->addrInTop = sqlite3VdbeAddOp3(v,OP_Column,iTab, iCol, iOut);
|
||||
}
|
||||
sqlite3VdbeAddOp1(v, OP_IsNull, iOut); VdbeCoverage(v);
|
||||
@@ -1448,11 +1446,11 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
pLevel->iLikeRepCntr |= bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC);
|
||||
}
|
||||
#endif
|
||||
if( pRangeStart==0
|
||||
&& (j = pIdx->aiColumn[nEq])>=0
|
||||
&& pIdx->pTable->aCol[j].notNull==0
|
||||
){
|
||||
bSeekPastNull = 1;
|
||||
if( pRangeStart==0 ){
|
||||
j = pIdx->aiColumn[nEq];
|
||||
if( (j>=0 && pIdx->pTable->aCol[j].notNull==0) || j==XN_EXPR ){
|
||||
bSeekPastNull = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 );
|
||||
@@ -1502,7 +1500,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( zStartAff ){
|
||||
updateRangeAffinityStr(pParse, pRight, nBtm, &zStartAff[nEq]);
|
||||
updateRangeAffinityStr(pRight, nBtm, &zStartAff[nEq]);
|
||||
}
|
||||
nConstraint += nBtm;
|
||||
testcase( pRangeStart->wtFlags & TERM_VIRTUAL );
|
||||
@@ -1552,7 +1550,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
if( zEndAff ){
|
||||
updateRangeAffinityStr(pParse, pRight, nTop, zEndAff);
|
||||
updateRangeAffinityStr(pRight, nTop, zEndAff);
|
||||
codeApplyAffinity(pParse, regBase+nEq, nTop, zEndAff);
|
||||
}else{
|
||||
assert( pParse->db->mallocFailed );
|
||||
@@ -1988,7 +1986,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
** the implied "t1.a=123" constraint.
|
||||
*/
|
||||
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
|
||||
Expr *pE, *pEAlt;
|
||||
Expr *pE, sEAlt;
|
||||
WhereTerm *pAlt;
|
||||
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
|
||||
if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
|
||||
@@ -2006,13 +2004,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
|
||||
testcase( pAlt->eOperator & WO_IS );
|
||||
testcase( pAlt->eOperator & WO_IN );
|
||||
VdbeModuleComment((v, "begin transitive constraint"));
|
||||
pEAlt = sqlite3StackAllocRaw(db, sizeof(*pEAlt));
|
||||
if( pEAlt ){
|
||||
*pEAlt = *pAlt->pExpr;
|
||||
pEAlt->pLeft = pE->pLeft;
|
||||
sqlite3ExprIfFalse(pParse, pEAlt, addrCont, SQLITE_JUMPIFNULL);
|
||||
sqlite3StackFree(db, pEAlt);
|
||||
}
|
||||
sEAlt = *pAlt->pExpr;
|
||||
sEAlt.pLeft = pE->pLeft;
|
||||
sqlite3ExprIfFalse(pParse, &sEAlt, addrCont, SQLITE_JUMPIFNULL);
|
||||
}
|
||||
|
||||
/* For a LEFT OUTER JOIN, generate code that will record the fact that
|
||||
|
||||
+4
-3
@@ -77,7 +77,6 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
|
||||
sqlite3DbFree(db, pOld);
|
||||
}
|
||||
pWC->nSlot = sqlite3DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]);
|
||||
memset(&pWC->a[pWC->nTerm], 0, sizeof(pWC->a[0])*(pWC->nSlot-pWC->nTerm));
|
||||
}
|
||||
pTerm = &pWC->a[idx = pWC->nTerm++];
|
||||
if( p && ExprHasProperty(p, EP_Unlikely) ){
|
||||
@@ -89,6 +88,8 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
|
||||
pTerm->wtFlags = wtFlags;
|
||||
pTerm->pWC = pWC;
|
||||
pTerm->iParent = -1;
|
||||
memset(&pTerm->eOperator, 0,
|
||||
sizeof(WhereTerm) - offsetof(WhereTerm,eOperator));
|
||||
return idx;
|
||||
}
|
||||
|
||||
@@ -1247,7 +1248,7 @@ static void exprAnalyze(
|
||||
|
||||
pNewExpr = sqlite3PExpr(pParse, TK_GT,
|
||||
sqlite3ExprDup(db, pLeft, 0),
|
||||
sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0);
|
||||
sqlite3ExprAlloc(db, TK_NULL, 0, 0), 0);
|
||||
|
||||
idxNew = whereClauseInsert(pWC, pNewExpr,
|
||||
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
|
||||
@@ -1425,7 +1426,7 @@ void sqlite3WhereTabFuncArgs(
|
||||
pTab->zName, j);
|
||||
return;
|
||||
}
|
||||
pColRef = sqlite3PExpr(pParse, TK_COLUMN, 0, 0, 0);
|
||||
pColRef = sqlite3ExprAlloc(pParse->db, TK_COLUMN, 0, 0);
|
||||
if( pColRef==0 ) return;
|
||||
pColRef->iTable = pItem->iCursor;
|
||||
pColRef->iColumn = k++;
|
||||
|
||||
@@ -663,6 +663,18 @@ ifcapable trigger {
|
||||
} {1 124 2 10123}
|
||||
}
|
||||
|
||||
# 2016-10-03 ticket https://www.sqlite.org/src/tktview/7b3328086a5c1
|
||||
# Make sure autoincrement plays nicely with the xfer optimization
|
||||
#
|
||||
do_execsql_test autoinc-10.1 {
|
||||
DELETE FROM sqlite_sequence;
|
||||
CREATE TABLE t10a(a INTEGER PRIMARY KEY AUTOINCREMENT, b UNIQUE);
|
||||
INSERT INTO t10a VALUES(888,9999);
|
||||
CREATE TABLE t10b(x INTEGER PRIMARY KEY AUTOINCREMENT, y UNIQUE);
|
||||
INSERT INTO t10b SELECT * FROM t10a;
|
||||
SELECT * FROM sqlite_sequence;
|
||||
} {t10a 888 t10b 888}
|
||||
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -95,6 +95,7 @@ do_execsql_test 3.0 {
|
||||
|
||||
do_faultsim_test 3 -faults oom* -prep {
|
||||
catch { db close }
|
||||
catch { db2 close }
|
||||
|
||||
forcedelete test2.db
|
||||
sqlite3 db2 test2.db
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
# 2016 September 10
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the code in test_delete.c (the
|
||||
# sqlite3_delete_database() API).
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix delete_db
|
||||
|
||||
proc delete_all {} {
|
||||
foreach f [glob -nocomplain test2*] { file delete $f }
|
||||
foreach f [glob -nocomplain test3*] { file delete $f }
|
||||
}
|
||||
|
||||
proc copydb {} {
|
||||
foreach f [glob -nocomplain test3*] { file delete $f }
|
||||
foreach f [glob -nocomplain test2*] {
|
||||
set p [string range $f 5 end]
|
||||
file copy "test2$p" "test3$p"
|
||||
}
|
||||
}
|
||||
|
||||
proc files {} {
|
||||
lsort [glob -nocomplain test3*]
|
||||
}
|
||||
|
||||
db close
|
||||
delete_all
|
||||
sqlite3 db test2.database
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
#
|
||||
# 1.1: Journal files.
|
||||
# 1.2: Wal files.
|
||||
# 1.3: Multiplexor with journal file.
|
||||
# 1.4: Multiplexor with wal file.
|
||||
#
|
||||
# 2.* are a copy of 1.* with the multiplexor enabled.
|
||||
#
|
||||
# 3.* tests errors.
|
||||
#
|
||||
|
||||
do_test 1.1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(x, y);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} {test3.database test3.database-journal}
|
||||
|
||||
do_test 1.1.1 {
|
||||
sqlite3_delete_database test3.database
|
||||
files
|
||||
} {}
|
||||
|
||||
do_test 1.2.0 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} {test3.database test3.database-shm test3.database-wal}
|
||||
do_test 1.2.1 {
|
||||
sqlite3_delete_database test3.database
|
||||
files
|
||||
} {}
|
||||
|
||||
db close
|
||||
delete_all
|
||||
sqlite3_multiplex_initialize "" 0
|
||||
sqlite3 db test2.database -vfs multiplex
|
||||
sqlite3_multiplex_control db "main" chunk_size 32768
|
||||
|
||||
do_test 1.3.0 {
|
||||
execsql { PRAGMA auto_vacuum = 0; }
|
||||
execsql {
|
||||
CREATE TABLE x1(a, b);
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000 )
|
||||
INSERT INTO x1 SELECT randomblob(100), randomblob(100) FROM s;
|
||||
BEGIN;
|
||||
UPDATE x1 SET a=randomblob(101)
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} [list {*}{
|
||||
test3.database test3.database-journal test3.database001
|
||||
test3.database002 test3.database003
|
||||
}]
|
||||
do_test 1.3.1 {
|
||||
sqlite3_delete_database test3.database
|
||||
files
|
||||
} {}
|
||||
|
||||
|
||||
do_test 1.4.0 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
PRAGMA journal_mode = wal;
|
||||
UPDATE x1 SET a=randomblob(102)
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} [list {*}{
|
||||
test3.database test3.database-shm test3.database-wal test3.database001
|
||||
test3.database002 test3.database003
|
||||
}]
|
||||
do_test 1.4.1 {
|
||||
sqlite3_delete_database test3.database
|
||||
files
|
||||
} {}
|
||||
|
||||
|
||||
ifcapable 8_3_names {
|
||||
db close
|
||||
delete_all
|
||||
sqlite3 db file:test2.db?8_3_names=1 -uri 1
|
||||
|
||||
do_test 2.1.0 {
|
||||
execsql {
|
||||
CREATE TABLE t1(x, y);
|
||||
BEGIN;
|
||||
INSERT INTO t1 VALUES(1, 2);
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} {test3.db test3.nal}
|
||||
|
||||
do_test 2.1.1 {
|
||||
sqlite3_delete_database test3.db
|
||||
files
|
||||
} {}
|
||||
|
||||
do_test 2.2.0 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
PRAGMA journal_mode = wal;
|
||||
INSERT INTO t1 VALUES(3, 4);
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} {test3.db test3.shm test3.wal}
|
||||
do_test 2.2.1 {
|
||||
sqlite3_delete_database test3.db
|
||||
files
|
||||
} {}
|
||||
|
||||
|
||||
db close
|
||||
delete_all
|
||||
sqlite3_multiplex_initialize "" 0
|
||||
sqlite3 db file:test2.db?8_3_names=1 -uri 1 -vfs multiplex
|
||||
sqlite3_multiplex_control db "main" chunk_size 32768
|
||||
|
||||
do_test 2.3.0 {
|
||||
execsql { PRAGMA auto_vacuum = 0; }
|
||||
execsql {
|
||||
CREATE TABLE x1(a, b);
|
||||
WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERE i<1000 )
|
||||
INSERT INTO x1 SELECT randomblob(100), randomblob(100) FROM s;
|
||||
BEGIN;
|
||||
UPDATE x1 SET a=randomblob(101)
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} [list {*}{
|
||||
test3.001 test3.002 test3.003 test3.db test3.nal
|
||||
}]
|
||||
do_test 2.3.1 {
|
||||
sqlite3_delete_database test3.db
|
||||
files
|
||||
} {}
|
||||
|
||||
|
||||
do_test 2.4.0 {
|
||||
execsql {
|
||||
COMMIT;
|
||||
PRAGMA journal_mode = wal;
|
||||
UPDATE x1 SET a=randomblob(102)
|
||||
}
|
||||
copydb
|
||||
files
|
||||
} [list {*}{
|
||||
test3.001 test3.002 test3.003 test3.db test3.db-shm test3.wal
|
||||
}]
|
||||
do_test 2.4.1 {
|
||||
sqlite3_delete_database test3.db
|
||||
files
|
||||
} {}
|
||||
}
|
||||
|
||||
db close
|
||||
delete_all
|
||||
sqlite3_multiplex_shutdown
|
||||
|
||||
do_test 3.0 {
|
||||
file mkdir dir2.db
|
||||
sqlite3_delete_database dir2.db
|
||||
} {SQLITE_ERROR}
|
||||
do_test 3.1 {
|
||||
sqlite3_delete_database dir2.db/test.db
|
||||
} {SQLITE_OK}
|
||||
|
||||
finish_test
|
||||
+4
-4
@@ -52,11 +52,11 @@ ifcapable trigger&&foreignkey {
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the effects of defining OMIT_TRIGGER but not OMIT_FOREIGN_KEY.
|
||||
#
|
||||
# EVIDENCE-OF: R-44697-61543 If SQLITE_OMIT_TRIGGER is defined but
|
||||
# EVIDENCE-OF: R-10109-20452 If SQLITE_OMIT_TRIGGER is defined but
|
||||
# SQLITE_OMIT_FOREIGN_KEY is not, then SQLite behaves as it did prior to
|
||||
# version 3.6.19 - foreign key definitions are parsed and may be queried
|
||||
# using PRAGMA foreign_key_list, but foreign key constraints are not
|
||||
# enforced.
|
||||
# version 3.6.19 (2009-10-14) - foreign key definitions are parsed and
|
||||
# may be queried using PRAGMA foreign_key_list, but foreign key
|
||||
# constraints are not enforced.
|
||||
#
|
||||
# Specifically, test that "PRAGMA foreign_keys" is a no-op in this case.
|
||||
# When using the pragma to query the current setting, 0 rows are returned.
|
||||
|
||||
+10
-5
@@ -190,8 +190,8 @@ if {![nonzero_reserved_bytes]} {
|
||||
}
|
||||
}
|
||||
|
||||
# EVIDENCE-OF: R-38001-03952 VACUUM only works on the main database. It
|
||||
# is not possible to VACUUM an attached database file.
|
||||
# EVIDENCE-OF: R-55119-57913 By default, VACUUM only works only on the
|
||||
# main database.
|
||||
forcedelete test.db2
|
||||
create_db { PRAGMA auto_vacuum = NONE }
|
||||
do_execsql_test e_vacuum-2.1.1 {
|
||||
@@ -206,6 +206,11 @@ set original_size [file size test.db2]
|
||||
do_execsql_test e_vacuum-2.1.3 { VACUUM } {}
|
||||
do_test e_vacuum-2.1.6 { expr {[file size test.db2]==$::original_size} } 1
|
||||
|
||||
# EVIDENCE-OF: R-36598-60500 Attached databases can be vacuumed by
|
||||
# appending the appropriate schema-name to the VACUUM statement.
|
||||
do_execsql_test e_vacuum-2.1.7 { VACUUM aux; } {}
|
||||
do_test e_vacuum-2.1.8 { expr {[file size test.db2]<$::original_size} } 1
|
||||
|
||||
# EVIDENCE-OF: R-17495-17419 The VACUUM command may change the ROWIDs of
|
||||
# entries in any tables that do not have an explicit INTEGER PRIMARY
|
||||
# KEY.
|
||||
@@ -267,9 +272,9 @@ do_test e_vacuum-3.2.2.1 {
|
||||
} {1 {cannot VACUUM - SQL statements in progress}}
|
||||
|
||||
|
||||
# EVIDENCE-OF: R-38735-12540 As of SQLite version 3.1, an alternative to
|
||||
# using the VACUUM command to reclaim space after data has been deleted
|
||||
# is auto-vacuum mode, enabled using the auto_vacuum pragma.
|
||||
# EVIDENCE-OF: R-55138-13241 An alternative to using the VACUUM command
|
||||
# to reclaim space after data has been deleted is auto-vacuum mode,
|
||||
# enabled using the auto_vacuum pragma.
|
||||
#
|
||||
do_test e_vacuum-3.3.1 {
|
||||
create_db { PRAGMA auto_vacuum = FULL }
|
||||
|
||||
@@ -308,6 +308,33 @@ ifcapable floatingpoint {if {[working_64bit_int]} {
|
||||
test_realnum_expr expr-1.257\
|
||||
{i1=-4294967296, i2=-2147483647} {i1*i2} 9223372032559808512
|
||||
|
||||
test_realnum_expr expr-1.260\
|
||||
{i1=3037000500, i2=3037000500} {i1*i2} 9.22337203700025e+18
|
||||
test_realnum_expr expr-1.261\
|
||||
{i1=3037000500, i2=-3037000500} {i1*i2} -9.22337203700025e+18
|
||||
test_realnum_expr expr-1.262\
|
||||
{i1=-3037000500, i2=3037000500} {i1*i2} -9.22337203700025e+18
|
||||
test_realnum_expr expr-1.263\
|
||||
{i1=-3037000500, i2=-3037000500} {i1*i2} 9.22337203700025e+18
|
||||
|
||||
test_realnum_expr expr-1.264\
|
||||
{i1=3037000500, i2=3037000499} {i1*i2} 9223372033963249500
|
||||
test_realnum_expr expr-1.265\
|
||||
{i1=3037000500, i2=-3037000499} {i1*i2} -9223372033963249500
|
||||
test_realnum_expr expr-1.266\
|
||||
{i1=-3037000500, i2=3037000499} {i1*i2} -9223372033963249500
|
||||
test_realnum_expr expr-1.267\
|
||||
{i1=-3037000500, i2=-3037000499} {i1*i2} 9223372033963249500
|
||||
|
||||
test_realnum_expr expr-1.268\
|
||||
{i1=3037000499, i2=3037000500} {i1*i2} 9223372033963249500
|
||||
test_realnum_expr expr-1.269\
|
||||
{i1=3037000499, i2=-3037000500} {i1*i2} -9223372033963249500
|
||||
test_realnum_expr expr-1.270\
|
||||
{i1=-3037000499, i2=3037000500} {i1*i2} -9223372033963249500
|
||||
test_realnum_expr expr-1.271\
|
||||
{i1=-3037000499, i2=-3037000500} {i1*i2} 9223372033963249500
|
||||
|
||||
}}
|
||||
|
||||
ifcapable floatingpoint {
|
||||
|
||||
+3
-3
@@ -117,12 +117,12 @@ do_test 2.1.2.1 {
|
||||
set cnt 0
|
||||
execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND term='braid' }
|
||||
set cnt
|
||||
} {2}
|
||||
} {1}
|
||||
do_test 2.1.2.2 {
|
||||
set cnt 0
|
||||
execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND +term='braid' }
|
||||
set cnt
|
||||
} {38}
|
||||
} {19}
|
||||
|
||||
# Similar to the test immediately above, but using a term ("breakfast") that
|
||||
# is not featured in the dataset.
|
||||
@@ -136,7 +136,7 @@ do_test 2.1.3.2 {
|
||||
set cnt 0
|
||||
execsql { SELECT * FROM terms_v WHERE rec('cnt', term) AND +term='breakfast' }
|
||||
set cnt
|
||||
} {38}
|
||||
} {19}
|
||||
|
||||
do_execsql_test 2.1.4.1 { SELECT * FROM terms_v WHERE term='braid' } {braid 1 1}
|
||||
do_execsql_test 2.1.4.2 { SELECT * FROM terms_v WHERE +term='braid'} {braid 1 1}
|
||||
|
||||
+21
-2
@@ -214,8 +214,27 @@ do_execsql_test 7.3.2 {
|
||||
SELECT a FROM y1 WHERE b IN (SELECT a FROM y2);
|
||||
} {two}
|
||||
|
||||
finish_test
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Tests to confirm that indexes on the rowid column do not confuse
|
||||
# the query planner. See ticket [0eab1ac7591f511d].
|
||||
#
|
||||
do_execsql_test 8.0 {
|
||||
CREATE TABLE n1(a INTEGER PRIMARY KEY, b VARCHAR(500));
|
||||
CREATE UNIQUE INDEX n1a ON n1(a);
|
||||
}
|
||||
|
||||
do_execsql_test 8.1 {
|
||||
SELECT count(*) FROM n1 WHERE a IN (1, 2, 3)
|
||||
} 0
|
||||
do_execsql_test 8.2 {
|
||||
SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1)
|
||||
} 0
|
||||
do_execsql_test 8.3 {
|
||||
INSERT INTO n1 VALUES(1, NULL), (2, NULL), (3, NULL);
|
||||
SELECT count(*) FROM n1 WHERE a IN (1, 2, 3)
|
||||
} 3
|
||||
do_execsql_test 8.4 {
|
||||
SELECT count(*) FROM n1 WHERE a IN (SELECT +a FROM n1)
|
||||
} 3
|
||||
|
||||
finish_test
|
||||
|
||||
+5
-2
@@ -65,12 +65,15 @@ do_test index6-1.5 {
|
||||
catchsql {
|
||||
CREATE INDEX bad1 ON t1(a,b) WHERE a!=random();
|
||||
}
|
||||
} {1 {functions prohibited in partial index WHERE clauses}}
|
||||
} {1 {non-deterministic functions prohibited in partial index WHERE clauses}}
|
||||
do_test index6-1.6 {
|
||||
catchsql {
|
||||
CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%';
|
||||
}
|
||||
} {1 {functions prohibited in partial index WHERE clauses}}
|
||||
} {0 {}}
|
||||
do_execsql_test index6-1.7 {
|
||||
DROP INDEX IF EXISTS bad1;
|
||||
}
|
||||
|
||||
do_test index6-1.10 {
|
||||
execsql {
|
||||
|
||||
+15
-2
@@ -99,12 +99,25 @@ do_test index7-1.5 {
|
||||
catchsql {
|
||||
CREATE INDEX bad1 ON t1(a,b) WHERE a!=random();
|
||||
}
|
||||
} {1 {functions prohibited in partial index WHERE clauses}}
|
||||
} {1 {non-deterministic functions prohibited in partial index WHERE clauses}}
|
||||
do_test index7-1.6 {
|
||||
catchsql {
|
||||
CREATE INDEX bad1 ON t1(a,b) WHERE a NOT LIKE 'abc%';
|
||||
}
|
||||
} {1 {functions prohibited in partial index WHERE clauses}}
|
||||
} {0 {}}
|
||||
do_execsql_test index7-1.7 {
|
||||
INSERT INTO t1(a,b,c)
|
||||
VALUES('abcde',1,101),('abdef',2,102),('xyz',3,103),('abcz',4,104);
|
||||
SELECT c FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
|
||||
} {7}
|
||||
do_execsql_test index7-1.7eqp {
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT b FROM t1 WHERE a NOT LIKE 'abc%' AND a=7 ORDER BY +b;
|
||||
} {/SEARCH TABLE t1 USING COVERING INDEX bad1 /}
|
||||
do_execsql_test index7-1.8 {
|
||||
DELETE FROM t1 WHERE c>=101;
|
||||
DROP INDEX IF EXISTS bad1;
|
||||
} {}
|
||||
|
||||
do_test index7-1.10 {
|
||||
execsql {
|
||||
|
||||
@@ -323,5 +323,51 @@ do_execsql_test indexexpr1-1010 {
|
||||
SELECT *, '|' FROM t0 ORDER BY +a;
|
||||
} {0 88 2 | 2 99 4 | 5 99 7 |}
|
||||
|
||||
# 2016-10-10
|
||||
# Make sure indexes on expressions skip over initial NULL values in the
|
||||
# index as they are suppose to do.
|
||||
# Ticket https://www.sqlite.org/src/tktview/4baa46491212947
|
||||
#
|
||||
do_execsql_test indexexpr1-1100 {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a);
|
||||
INSERT INTO t1 VALUES(NULL),(1);
|
||||
SELECT '1:', typeof(a), a FROM t1 WHERE a<10;
|
||||
SELECT '2:', typeof(a), a FROM t1 WHERE a+0<10;
|
||||
CREATE INDEX t1x1 ON t1(a);
|
||||
CREATE INDEX t1x2 ON t1(a+0);
|
||||
SELECT '3:', typeof(a), a FROM t1 WHERE a<10;
|
||||
SELECT '4:', typeof(a), a FROM t1 WHERE a+0<10;
|
||||
} {1: integer 1 2: integer 1 3: integer 1 4: integer 1}
|
||||
|
||||
do_execsql_test indexexpr1-1200 {
|
||||
CREATE TABLE t10(a int, b int, c int, d int);
|
||||
INSERT INTO t10(a, b, c, d) VALUES(0, 0, 2, 2);
|
||||
INSERT INTO t10(a, b, c, d) VALUES(0, 0, 0, 0);
|
||||
INSERT INTO t10(a, b, c, d) VALUES(0, 0, 1, 1);
|
||||
INSERT INTO t10(a, b, c, d) VALUES(1, 1, 1, 1);
|
||||
INSERT INTO t10(a, b, c, d) VALUES(1, 1, 0, 0);
|
||||
INSERT INTO t10(a, b, c, d) VALUES(2, 2, 0, 0);
|
||||
|
||||
SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
|
||||
} {
|
||||
0 0 0 2 0 4 2 0 2 2 4 0
|
||||
}
|
||||
do_execsql_test indexexpr1-1200.1 {
|
||||
CREATE INDEX t10_ab ON t10(a+b);
|
||||
}
|
||||
do_execsql_test indexexpr1-1200.2 {
|
||||
SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
|
||||
} {
|
||||
0 0 0 2 0 4 2 0 2 2 4 0
|
||||
}
|
||||
do_execsql_test indexexpr1-1200.3 {
|
||||
CREATE INDEX t10_abcd ON t10(a+b,c+d);
|
||||
}
|
||||
do_execsql_test indexexpr1-1200.4 {
|
||||
SELECT a+b, c+d FROM t10 ORDER BY a+b, c+d;
|
||||
} {
|
||||
0 0 0 2 0 4 2 0 2 2 4 0
|
||||
}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix limit2
|
||||
|
||||
do_execsql_test limit2-100 {
|
||||
CREATE TABLE t1(a,b);
|
||||
@@ -109,7 +110,44 @@ do_execsql_test limit2-310 {
|
||||
SELECT *,'.' FROM t300 WHERE a=0 AND (c=0 OR c=99) ORDER BY c DESC LIMIT 1;
|
||||
} {0 1 99 .}
|
||||
|
||||
# Make sure the SELECT loop is ordered correctly for the direction of
|
||||
# the ORDER BY
|
||||
#
|
||||
do_execsql_test limit2-400 {
|
||||
CREATE TABLE t400(a,b);
|
||||
CREATE INDEX t400_ab ON t400(a,b);
|
||||
INSERT INTO t400(a,b) VALUES(1,90),(1,40),(2,80),(2,30),(3,70),(3,20);
|
||||
SELECT *,'x' FROM t400 WHERE a IN (1,2,3) ORDER BY b DESC LIMIT 3;
|
||||
SELECT *,'y' FROM t400 WHERE a IN (1,2,3) ORDER BY +b DESC LIMIT 3;
|
||||
} {1 90 x 2 80 x 3 70 x 1 90 y 2 80 y 3 70 y}
|
||||
|
||||
|
||||
do_execsql_test 500 {
|
||||
CREATE TABLE t500(i INTEGER PRIMARY KEY, j);
|
||||
INSERT INTO t500 VALUES(1, 1);
|
||||
INSERT INTO t500 VALUES(2, 2);
|
||||
INSERT INTO t500 VALUES(3, 3);
|
||||
INSERT INTO t500 VALUES(4, 0);
|
||||
INSERT INTO t500 VALUES(5, 5);
|
||||
SELECT j FROM t500 WHERE i IN (1,2,3,4,5) ORDER BY j DESC LIMIT 3;
|
||||
} {5 3 2}
|
||||
do_execsql_test 501 {
|
||||
CREATE TABLE t501(i INTEGER PRIMARY KEY, j);
|
||||
INSERT INTO t501 VALUES(1, 5);
|
||||
INSERT INTO t501 VALUES(2, 4);
|
||||
INSERT INTO t501 VALUES(3, 3);
|
||||
INSERT INTO t501 VALUES(4, 6);
|
||||
INSERT INTO t501 VALUES(5, 1);
|
||||
SELECT j FROM t501 WHERE i IN (1,2,3,4,5) ORDER BY j LIMIT 3;
|
||||
} {1 3 4}
|
||||
do_execsql_test 502 {
|
||||
CREATE TABLE t502(i INT PRIMARY KEY, j);
|
||||
INSERT INTO t502 VALUES(1, 5);
|
||||
INSERT INTO t502 VALUES(2, 4);
|
||||
INSERT INTO t502 VALUES(3, 3);
|
||||
INSERT INTO t502 VALUES(4, 6);
|
||||
INSERT INTO t502 VALUES(5, 1);
|
||||
SELECT j FROM t502 WHERE i IN (1,2,3,4,5) ORDER BY j LIMIT 3;
|
||||
} {1 3 4}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -61,4 +61,15 @@ do_malloc_test mallocI-4 -tclprep {
|
||||
}
|
||||
catch { db2 close }
|
||||
|
||||
do_faultsim_test mallocI-5 -faults oom* -prep {
|
||||
catch { db close }
|
||||
sqlite3 db test.db
|
||||
sqlite3_db_config_lookaside db 0 0 0
|
||||
} -body {
|
||||
db eval { Select CAST(1 AS blob) }
|
||||
} -test {
|
||||
faultsim_test_result {0 1}
|
||||
}
|
||||
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -751,6 +751,9 @@ test_suite "inmemory_journal" -description {
|
||||
# statement switches the database out of wal mode at inopportune
|
||||
# times.
|
||||
snapshot_fault.test
|
||||
|
||||
# This test assumes a journal file is created on disk.
|
||||
delete_db.test
|
||||
}]
|
||||
|
||||
ifcapable mem3 {
|
||||
@@ -950,6 +953,7 @@ test_suite "journaltest" -description {
|
||||
async4.test bigfile.test backcompat.test e_wal* fstat.test mmap2.test
|
||||
pager1.test syscall.test tkt3457.test *malloc* mmap* multiplex* nolock*
|
||||
pager2.test *fault* rowal* snapshot* superlock* symlink.test
|
||||
delete_db.test
|
||||
}]
|
||||
|
||||
if {[info commands register_demovfs] != ""} {
|
||||
|
||||
Regular → Executable
+75
-14
@@ -9,21 +9,19 @@ This Tcl script is used to test the various configurations required
|
||||
before releasing a new version. Supported command line options (all
|
||||
optional) are:
|
||||
|
||||
--srcdir TOP-OF-SQLITE-TREE (see below)
|
||||
--platform PLATFORM (see below)
|
||||
--buildonly (Just build testfixture - do not run)
|
||||
--config CONFIGNAME (Run only CONFIGNAME)
|
||||
--dryrun (Print what would have happened)
|
||||
-f|--force (Run even if uncommitted changes)
|
||||
--info (Show diagnostic info)
|
||||
--jobs N (Use N processes - default 1)
|
||||
--keep (Delete no files after each test run)
|
||||
--msvc (Use MSVC as the compiler)
|
||||
--platform PLATFORM (see below)
|
||||
--progress (Show progress messages)
|
||||
--quick (Run "veryquick.test" only)
|
||||
--veryquick (Run "make smoketest" only)
|
||||
--msvc (Use MSVC as the compiler)
|
||||
--buildonly (Just build testfixture - do not run)
|
||||
--dryrun (Print what would have happened)
|
||||
--info (Show diagnostic info)
|
||||
--with-tcl=DIR (Use TCL build at DIR)
|
||||
--jobs N (Use N processes - default 1)
|
||||
--progress (Show progress messages)
|
||||
|
||||
The default value for --srcdir is the parent of the directory holding
|
||||
this script.
|
||||
|
||||
The script determines the default value for --platform using the
|
||||
$tcl_platform(os) and $tcl_platform(machine) variables. Supported
|
||||
@@ -470,14 +468,15 @@ proc count_tests_and_errors {logfile rcVar errmsgVar} {
|
||||
proc run_slave_test {} {
|
||||
# Read global vars configuration from stdin.
|
||||
set V [gets stdin]
|
||||
foreach {::TRACE ::MSVC ::DRYRUN} $V {}
|
||||
foreach {::TRACE ::MSVC ::DRYRUN ::KEEPFILES} $V {}
|
||||
|
||||
# Read the test-suite configuration from stdin.
|
||||
set T [gets stdin]
|
||||
foreach {title dir configOpts testtarget makeOpts cflags opts} $T {}
|
||||
|
||||
# Create and switch to the test directory.
|
||||
set ::env(SQLITE_TMPDIR) [file normalize $dir]
|
||||
set normaldir [file normalize $dir]
|
||||
set ::env(SQLITE_TMPDIR) $normaldir
|
||||
trace_cmd file mkdir $dir
|
||||
trace_cmd cd $dir
|
||||
catch {file delete core}
|
||||
@@ -501,6 +500,9 @@ proc run_slave_test {} {
|
||||
}
|
||||
}
|
||||
|
||||
# Clean up lots of extra files if --keep was not specified.
|
||||
if {$::KEEPFILES==0} { cleanup $normaldir }
|
||||
|
||||
# Exis successfully if the test passed, or with a non-zero error code
|
||||
# otherwise.
|
||||
exit $rc
|
||||
@@ -600,7 +602,7 @@ proc run_all_test_suites {alltests} {
|
||||
set fd [open "|[info nameofexecutable] $script --slave" r+]
|
||||
fconfigure $fd -blocking 0
|
||||
fileevent $fd readable [list slave_fileevent $fd $T $tm1]
|
||||
puts $fd [list $::TRACE $::MSVC $::DRYRUN]
|
||||
puts $fd [list $::TRACE $::MSVC $::DRYRUN $::KEEPFILES]
|
||||
puts $fd [list {*}$T]
|
||||
flush $fd
|
||||
}
|
||||
@@ -778,6 +780,8 @@ proc process_options {argv} {
|
||||
set ::JOBS 1
|
||||
set ::PROGRESS_MSGS 0
|
||||
set ::WITHTCL {}
|
||||
set ::FORCE 0
|
||||
set ::KEEPFILES 0 ;# Keep extra files after test run
|
||||
set config {}
|
||||
set platform $::tcl_platform(os)-$::tcl_platform(machine)
|
||||
|
||||
@@ -790,6 +794,12 @@ proc process_options {argv} {
|
||||
exit
|
||||
}
|
||||
|
||||
# Undocumented legacy option: --srcdir DIRECTORY
|
||||
#
|
||||
# DIRECTORY is the root of the SQLite checkout. This sets the
|
||||
# SRCDIR global variable. But that variable is already set
|
||||
# automatically so there really is no reason to have this option.
|
||||
#
|
||||
-srcdir {
|
||||
incr i
|
||||
set ::SRCDIR [file normalize [lindex $argv $i]]
|
||||
@@ -833,6 +843,11 @@ proc process_options {argv} {
|
||||
set ::DRYRUN 1
|
||||
}
|
||||
|
||||
-force -
|
||||
-f {
|
||||
set ::FORCE 1
|
||||
}
|
||||
|
||||
-trace {
|
||||
set ::TRACE 1
|
||||
}
|
||||
@@ -865,6 +880,10 @@ proc process_options {argv} {
|
||||
lappend ::EXTRACONFIG [lindex $argv $i]
|
||||
}
|
||||
|
||||
-keep {
|
||||
set ::KEEPFILES 1
|
||||
}
|
||||
|
||||
-with-tcl=* {
|
||||
set ::WITHTCL -$x
|
||||
}
|
||||
@@ -926,6 +945,47 @@ proc process_options {argv} {
|
||||
PUTS ""
|
||||
}
|
||||
|
||||
# Check to see if there are uncommitted changes in the SQLite source
|
||||
# checkout. Exit if there are. Except: Do nothing if the --force
|
||||
# flag is used. Also, ignore this test if the fossil binary is
|
||||
# unavailable, or if the source tree is not a valid fossil checkout.
|
||||
#
|
||||
proc check_uncommitted {} {
|
||||
if {$::FORCE} return
|
||||
set pwd [pwd]
|
||||
cd $::SRCDIR
|
||||
if {[catch {exec fossil changes} res]==0 && [string trim $res]!=""} {
|
||||
puts "ERROR: The check-out contains uncommitted changes:"
|
||||
puts $res
|
||||
puts "Use the -f or --force options to override"
|
||||
exit 1
|
||||
}
|
||||
cd $pwd
|
||||
}
|
||||
|
||||
# A test run has just finished in directory $dir. This command deletes all
|
||||
# non-essential files from the directory. Specifically, everything except
|
||||
#
|
||||
# * The "testfixture" and "sqlite3" binaries,
|
||||
# * The "test-out.log" and "test.log" log files.
|
||||
#
|
||||
proc cleanup {dir} {
|
||||
set K(testfixture) 1
|
||||
set K(testfixture.exe) 1
|
||||
set K(sqlite3) 1
|
||||
set K(sqlite3.exe) 1
|
||||
set K(test-out.txt) 1
|
||||
set K(test.log) 1
|
||||
|
||||
foreach f [glob -nocomplain [file join $dir *]] {
|
||||
set tail [file tail $f]
|
||||
if {[info exists K($tail)]==0} {
|
||||
file delete -force $f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Main routine.
|
||||
#
|
||||
proc main {argv} {
|
||||
@@ -933,6 +993,7 @@ proc main {argv} {
|
||||
# Process any command line options.
|
||||
set ::EXTRACONFIG {}
|
||||
process_options $argv
|
||||
if {!$::DRYRUN} check_uncommitted
|
||||
PUTS [string repeat * 79]
|
||||
|
||||
set ::NERR 0
|
||||
|
||||
@@ -17,6 +17,11 @@ set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix rowvalue5
|
||||
|
||||
ifcapable !vtab {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
proc vtab_command {method args} {
|
||||
switch -- $method {
|
||||
xConnect {
|
||||
|
||||
@@ -322,4 +322,19 @@ do_execsql_test skipscan1-8.2 {
|
||||
ORDER BY +x;
|
||||
} {1 AB 2 CD}
|
||||
|
||||
# Segfault reported on the mailing list by Keith Medcalf on 2016-09-18.
|
||||
# A skip-scan with a "column IN (SELECT ...)" on the second term of the
|
||||
# index.
|
||||
#
|
||||
do_execsql_test skipscan1-9.2 {
|
||||
CREATE TABLE t9a(a,b,c);
|
||||
CREATE INDEX t9a_ab ON t9a(a,b);
|
||||
CREATE TABLE t9b(x,y);
|
||||
ANALYZE sqlite_master;
|
||||
INSERT INTO sqlite_stat1 VALUES('t9a','t9a_ab','1000000 250000 1');
|
||||
ANALYZE sqlite_master;
|
||||
EXPLAIN QUERY PLAN
|
||||
SELECT * FROM t9a WHERE b IN (SELECT x FROM t9b WHERE y!=5);
|
||||
} {/USING INDEX t9a_ab .ANY.a. AND b=./}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -421,12 +421,14 @@ void speedtest1_run(void){
|
||||
speedtest1_shrink_memory();
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
/* The sqlite3_trace() callback function */
|
||||
static void traceCallback(void *NotUsed, const char *zSql){
|
||||
int n = (int)strlen(zSql);
|
||||
while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ) n--;
|
||||
fprintf(stderr,"%.*s;\n", n, zSql);
|
||||
}
|
||||
#endif /* SQLITE_OMIT_DEPRECATED */
|
||||
|
||||
/* Substitute random() function that gives the same random
|
||||
** sequence on each run, for repeatability. */
|
||||
@@ -1416,7 +1418,9 @@ int main(int argc, char **argv){
|
||||
|
||||
/* Set database connection options */
|
||||
sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0);
|
||||
#ifndef SQLITE_OMIT_DEPRECATED
|
||||
if( doTrace ) sqlite3_trace(g.db, traceCallback, 0);
|
||||
#endif
|
||||
speedtest1_exec("PRAGMA threads=%d", nThread);
|
||||
if( zKey ){
|
||||
speedtest1_exec("PRAGMA key('%s')", zKey);
|
||||
|
||||
+2
-2
@@ -128,7 +128,7 @@ do_test trace3-5.1 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
}
|
||||
set ::stmtlist(record)
|
||||
} "/^[string trim [string repeat {\d+ } 16]]\$/"
|
||||
} "/^[string trim [string repeat {-?\d+ } 16]]\$/"
|
||||
do_test trace3-5.2 {
|
||||
set ::stmtlist(record) {}
|
||||
db trace_v2 trace_v2_record 4
|
||||
@@ -136,7 +136,7 @@ do_test trace3-5.2 {
|
||||
SELECT a, b FROM t1 ORDER BY a;
|
||||
}
|
||||
set ::stmtlist(record)
|
||||
} "/^[string trim [string repeat {\d+ } 16]]\$/"
|
||||
} "/^[string trim [string repeat {-?\d+ } 16]]\$/"
|
||||
|
||||
do_test trace3-6.1 {
|
||||
set ::stmtlist(record) {}
|
||||
|
||||
@@ -25,6 +25,7 @@ ifcapable !vacuum {
|
||||
|
||||
forcedelete test2.db test3.db
|
||||
do_execsql_test vacuum5-1.1 {
|
||||
PRAGMA auto_vacuum = 0;
|
||||
CREATE TABLE main.t1(a,b);
|
||||
WITH RECURSIVE c(x) AS (VALUES(1) UNION ALL SELECT x+1 FROM c WHERE x<1000)
|
||||
INSERT INTO t1(a,b) SELECT x, randomblob(1000) FROM c;
|
||||
@@ -109,3 +110,5 @@ do_execsql_test vacuum5-1.4.2 {
|
||||
do_catchsql_test vacuum5-2.0 {
|
||||
VACUUM olaf;
|
||||
} {1 {unknown database olaf}}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -22,6 +22,19 @@ if {[permutation]=="memsubsys1"} {
|
||||
return
|
||||
}
|
||||
|
||||
# If ENABLE_MEMORY_MANAGEMENT is defined, when VACUUM is run the temp db
|
||||
# is able to borrow space from the main db (and it does, because the
|
||||
# temp db is configure with a very small cache). When the VACUUM is
|
||||
# finished and the temp db closed, all the page-cache memory currently
|
||||
# assigned to the temp db is freed. If ENABLE_MEMORY_MANAGEMENT is defined
|
||||
# this causes the total memory usage to drop much more than expected,
|
||||
# causing tests in this file to fail.
|
||||
#
|
||||
ifcapable memorymanage {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
proc memory_used {} {
|
||||
set stat [sqlite3_status SQLITE_STATUS_MEMORY_USED 1]
|
||||
|
||||
+8
-2
@@ -77,6 +77,7 @@ IF /I "%PROCESSOR%" == "x86" (
|
||||
|
||||
%_VECHO% TclKitVersion = '%TCLKIT_VERSION%'
|
||||
%_VECHO% TclKitPatchLevel = '%TCLKIT_PATCHLEVEL%'
|
||||
%_VECHO% TclKitNoEnv = '%TCLKIT_NOENV%'
|
||||
%_VECHO% TclKitNoSdk = '%TCLKIT_NOSDK%'
|
||||
%_VECHO% TclKitExe = '%TCLKIT_EXE%'
|
||||
%_VECHO% TclKitLib = '%TCLKIT_LIB%'
|
||||
@@ -147,6 +148,7 @@ FOR %%F IN (%TCLKIT_FILES%) DO (
|
||||
)
|
||||
)
|
||||
|
||||
IF DEFINED TCLKIT_NOENV GOTO skip_sdkUnZip
|
||||
IF DEFINED TCLKIT_NOSDK GOTO skip_sdkUnZip
|
||||
|
||||
IF NOT EXIST "%TEMP%\%TCLKIT_SDK%" (
|
||||
@@ -167,6 +169,8 @@ IF ERRORLEVEL 1 (
|
||||
|
||||
:skip_sdkUnZip
|
||||
|
||||
IF DEFINED TCLKIT_NOENV GOTO skip_sdkEnvironment
|
||||
|
||||
%__ECHO% ECHO SET TCLSH_CMD=%TEMP%\%TCLKIT_EXE%%OVERWRITE%"%ROOT%\SetTclKitEnv.bat"
|
||||
|
||||
IF DEFINED TCLKIT_NOSDK GOTO skip_sdkVariables
|
||||
@@ -184,6 +188,8 @@ ECHO Wrote "%ROOT%\SetTclKitEnv.bat".
|
||||
ECHO Please run it to set the necessary Tcl environment variables.
|
||||
ECHO.
|
||||
|
||||
:skip_sdkEnvironment
|
||||
|
||||
GOTO no_errors
|
||||
|
||||
:fn_TclKitX86Variables
|
||||
@@ -198,7 +204,7 @@ GOTO no_errors
|
||||
SET TCLKIT_SDK=libtclkit-sdk-x86-%TCLKIT_PATCHLEVEL%
|
||||
SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
|
||||
SET TCLKIT_FILES=%TCLKIT_EXE%
|
||||
IF NOT DEFINED TCLKIT_NOSDK (
|
||||
IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
|
||||
SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
|
||||
)
|
||||
GOTO :EOF
|
||||
@@ -223,7 +229,7 @@ GOTO no_errors
|
||||
SET TCLKIT_SDK=libtclkit-sdk-x64-%TCLKIT_PATCHLEVEL%
|
||||
SET TCLKIT_SDK_ZIP=%TCLKIT_SDK%.zip
|
||||
SET TCLKIT_FILES=%TCLKIT_EXE%
|
||||
IF NOT DEFINED TCLKIT_NOSDK (
|
||||
IF NOT DEFINED TCLKIT_NOENV IF NOT DEFINED TCLKIT_NOSDK (
|
||||
SET TCLKIT_FILES=%TCLKIT_FILES% unzip.exe %TCLKIT_SDK_ZIP%
|
||||
)
|
||||
GOTO :EOF
|
||||
|
||||
+1
-1
@@ -872,7 +872,7 @@ void Parse(
|
||||
yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
|
||||
yymajor = YYNOCODE;
|
||||
}else{
|
||||
while( yypParser->yytos >= &yypParser->yystack
|
||||
while( yypParser->yytos >= yypParser->yystack
|
||||
&& yymx != YYERRORSYMBOL
|
||||
&& (yyact = yy_find_reduce_action(
|
||||
yypParser->yytos->stateno,
|
||||
|
||||
+35
-24
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# To build a single huge source file holding all of SQLite (or at
|
||||
# least the core components - the test harness, shell, and TCL
|
||||
# least the core components - the test harness, shell, and TCL
|
||||
# interface are omitted.) first do
|
||||
#
|
||||
# make target_source
|
||||
@@ -11,7 +11,7 @@
|
||||
# there and will not work if they are not found.) There are a few
|
||||
# generated C code files that are also added to the tsrc directory.
|
||||
# For example, the "parse.c" and "parse.h" files to implement the
|
||||
# the parser are derived from "parse.y" using lemon. And the
|
||||
# the parser are derived from "parse.y" using lemon. And the
|
||||
# "keywordhash.h" files is generated by a program named "mkkeywordhash".
|
||||
#
|
||||
# After the "tsrc" directory has been created and populated, run
|
||||
@@ -26,15 +26,20 @@
|
||||
# from in this file. The version number is needed to generate the header
|
||||
# comment of the amalgamation.
|
||||
#
|
||||
if {[lsearch $argv --nostatic]>=0} {
|
||||
set addstatic 0
|
||||
} else {
|
||||
set addstatic 1
|
||||
}
|
||||
if {[lsearch $argv --linemacros]>=0} {
|
||||
set linemacros 1
|
||||
} else {
|
||||
set linemacros 0
|
||||
set addstatic 1
|
||||
set linemacros 0
|
||||
set useapicall 0
|
||||
for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
set x [lindex $argv $i]
|
||||
if {[regexp {^-+nostatic$} $x]} {
|
||||
set addstatic 0
|
||||
} elseif {[regexp {^-+linemacros} $x]} {
|
||||
set linemacros 1
|
||||
} elseif {[regexp {^-+useapicall} $x]} {
|
||||
set useapicall 1
|
||||
} else {
|
||||
error "unknown command-line option: $x"
|
||||
}
|
||||
}
|
||||
set in [open tsrc/sqlite3.h]
|
||||
set cnt 0
|
||||
@@ -57,7 +62,7 @@ set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
|
||||
puts $out [subst \
|
||||
{/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version $VERSION. By combining all the individual C code files into this
|
||||
** version $VERSION. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@@ -66,7 +71,7 @@ puts $out [subst \
|
||||
**
|
||||
** This file is all you need to compile SQLite. To use SQLite in other
|
||||
** programs, you need this file and the "sqlite3.h" header file that defines
|
||||
** the programming interface to the SQLite library. (If you do not have
|
||||
** the programming interface to the SQLite library. (If you do not have
|
||||
** the "sqlite3.h" header file at hand, you will find a copy embedded within
|
||||
** the text of this file. Search for "Begin file sqlite3.h" to find the start
|
||||
** of the embedded sqlite3.h header file.) Additional code files may be needed
|
||||
@@ -83,7 +88,7 @@ if {$addstatic} {
|
||||
#endif}
|
||||
}
|
||||
|
||||
# These are the header files used by SQLite. The first time any of these
|
||||
# These are the header files used by SQLite. The first time any of these
|
||||
# files are seen in a #include statement in the C code, include the complete
|
||||
# text of the file in-line. The file only needs to be included once.
|
||||
#
|
||||
@@ -104,8 +109,8 @@ foreach hdr {
|
||||
parse.h
|
||||
pcache.h
|
||||
pragma.h
|
||||
sqlite3ext.h
|
||||
sqlite3.h
|
||||
sqlite3ext.h
|
||||
sqliteicu.h
|
||||
sqliteInt.h
|
||||
sqliteLimit.h
|
||||
@@ -155,7 +160,8 @@ proc section_comment {text} {
|
||||
# process them appropriately.
|
||||
#
|
||||
proc copy_file {filename} {
|
||||
global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
|
||||
global seen_hdr available_hdr varonly_hdr cdecllist out
|
||||
global addstatic linemacros useapicall
|
||||
set ln 0
|
||||
set tail [file tail $filename]
|
||||
section_comment "Begin file $tail"
|
||||
@@ -203,7 +209,8 @@ proc copy_file {filename} {
|
||||
puts $out "#if 0"
|
||||
} elseif {!$linemacros && [regexp {^#line} $line]} {
|
||||
# Skip #line directives.
|
||||
} elseif {$addstatic && ![regexp {^(static|typedef)} $line]} {
|
||||
} elseif {$addstatic
|
||||
&& ![regexp {^(static|typedef|SQLITE_PRIVATE)} $line]} {
|
||||
# Skip adding the SQLITE_PRIVATE or SQLITE_API keyword before
|
||||
# functions if this header file does not need it.
|
||||
if {![info exists varonly_hdr($tail)]
|
||||
@@ -211,18 +218,20 @@ proc copy_file {filename} {
|
||||
regsub {^SQLITE_API } $line {} line
|
||||
# Add the SQLITE_PRIVATE or SQLITE_API keyword before functions.
|
||||
# so that linkage can be modified at compile-time.
|
||||
if {[regexp {^sqlite3_} $funcname]} {
|
||||
if {[regexp {^sqlite3[a-z]*_} $funcname]} {
|
||||
set line SQLITE_API
|
||||
append line " " [string trim $rettype]
|
||||
if {[string index $rettype end] ne "*"} {
|
||||
append line " "
|
||||
}
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL
|
||||
} else {
|
||||
append line SQLITE_APICALL
|
||||
if {$useapicall} {
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL " "
|
||||
} else {
|
||||
append line SQLITE_APICALL " "
|
||||
}
|
||||
}
|
||||
append line " " $funcname $rest
|
||||
append line $funcname $rest
|
||||
puts $out $line
|
||||
} else {
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
@@ -285,6 +294,7 @@ foreach file {
|
||||
mutex_w32.c
|
||||
malloc.c
|
||||
printf.c
|
||||
treeview.c
|
||||
random.c
|
||||
threads.c
|
||||
utf.c
|
||||
@@ -313,7 +323,6 @@ foreach file {
|
||||
vdbe.c
|
||||
vdbeblob.c
|
||||
vdbesort.c
|
||||
journal.c
|
||||
memjournal.c
|
||||
|
||||
walker.c
|
||||
@@ -339,6 +348,8 @@ foreach file {
|
||||
update.c
|
||||
vacuum.c
|
||||
vtab.c
|
||||
wherecode.c
|
||||
whereexpr.c
|
||||
where.c
|
||||
|
||||
parse.c
|
||||
|
||||
+17
-12
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/tclsh
|
||||
#
|
||||
# To build a single huge source file holding all of SQLite (or at
|
||||
# least the core components - the test harness, shell, and TCL
|
||||
# least the core components - the test harness, shell, and TCL
|
||||
# interface are omitted.) first do
|
||||
#
|
||||
# make target_source
|
||||
@@ -11,7 +11,7 @@
|
||||
# there and will not work if they are not found.) There are a few
|
||||
# generated C code files that are also added to the tsrc directory.
|
||||
# For example, the "parse.c" and "parse.h" files to implement the
|
||||
# the parser are derived from "parse.y" using lemon. And the
|
||||
# the parser are derived from "parse.y" using lemon. And the
|
||||
# "keywordhash.h" files is generated by a program named "mkkeywordhash".
|
||||
#
|
||||
# After the "tsrc" directory has been created and populated, run
|
||||
@@ -28,12 +28,15 @@
|
||||
#
|
||||
set addstatic 1
|
||||
set linemacros 0
|
||||
set useapicall 0
|
||||
for {set i 0} {$i<[llength $argv]} {incr i} {
|
||||
set x [lindex $argv $i]
|
||||
if {[regexp {^-+nostatic$} $x]} {
|
||||
set addstatic 0
|
||||
} elseif {[regexp {^-+linemacros} $x]} {
|
||||
set linemacros 1
|
||||
} elseif {[regexp {^-+useapicall} $x]} {
|
||||
set useapicall 1
|
||||
} else {
|
||||
error "unknown command-line option: $x"
|
||||
}
|
||||
@@ -59,7 +62,7 @@ set today [clock format [clock seconds] -format "%Y-%m-%d %H:%M:%S UTC" -gmt 1]
|
||||
puts $out [subst \
|
||||
{/******************************************************************************
|
||||
** This file is an amalgamation of many separate C source files from SQLite
|
||||
** version $VERSION. By combining all the individual C code files into this
|
||||
** version $VERSION. By combining all the individual C code files into this
|
||||
** single large file, the entire code can be compiled as a single translation
|
||||
** unit. This allows many compilers to do optimizations that would not be
|
||||
** possible if the files were compiled separately. Performance improvements
|
||||
@@ -68,7 +71,7 @@ puts $out [subst \
|
||||
**
|
||||
** This file is all you need to compile SQLite. To use SQLite in other
|
||||
** programs, you need this file and the "sqlite3.h" header file that defines
|
||||
** the programming interface to the SQLite library. (If you do not have
|
||||
** the programming interface to the SQLite library. (If you do not have
|
||||
** the "sqlite3.h" header file at hand, you will find a copy embedded within
|
||||
** the text of this file. Search for "Begin file sqlite3.h" to find the start
|
||||
** of the embedded sqlite3.h header file.) Additional code files may be needed
|
||||
@@ -85,7 +88,7 @@ if {$addstatic} {
|
||||
#endif}
|
||||
}
|
||||
|
||||
# These are the header files used by SQLite. The first time any of these
|
||||
# These are the header files used by SQLite. The first time any of these
|
||||
# files are seen in a #include statement in the C code, include the complete
|
||||
# text of the file in-line. The file only needs to be included once.
|
||||
#
|
||||
@@ -112,7 +115,6 @@ foreach hdr {
|
||||
pragma.h
|
||||
rtree.h
|
||||
sqlite3session.h
|
||||
sqlite3ext.h
|
||||
sqlite3.h
|
||||
sqlite3ext.h
|
||||
sqlite3rbu.h
|
||||
@@ -166,7 +168,8 @@ proc section_comment {text} {
|
||||
# process them appropriately.
|
||||
#
|
||||
proc copy_file {filename} {
|
||||
global seen_hdr available_hdr varonly_hdr cdecllist out addstatic linemacros
|
||||
global seen_hdr available_hdr varonly_hdr cdecllist out
|
||||
global addstatic linemacros useapicall
|
||||
set ln 0
|
||||
set tail [file tail $filename]
|
||||
section_comment "Begin file $tail"
|
||||
@@ -229,12 +232,14 @@ proc copy_file {filename} {
|
||||
if {[string index $rettype end] ne "*"} {
|
||||
append line " "
|
||||
}
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL
|
||||
} else {
|
||||
append line SQLITE_STDCALL
|
||||
if {$useapicall} {
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL " "
|
||||
} else {
|
||||
append line SQLITE_APICALL " "
|
||||
}
|
||||
}
|
||||
append line " " $funcname $rest
|
||||
append line $funcname $rest
|
||||
puts $out $line
|
||||
} else {
|
||||
puts $out "SQLITE_PRIVATE $line"
|
||||
|
||||
+27
-10
@@ -10,17 +10,19 @@
|
||||
#
|
||||
# Run this script by specifying the root directory of the source tree
|
||||
# on the command-line.
|
||||
#
|
||||
#
|
||||
# This script performs processing on src/sqlite.h.in. It:
|
||||
#
|
||||
# 1) Adds SQLITE_EXTERN in front of the declaration of global variables,
|
||||
# 2) Adds SQLITE_API in front of the declaration of API functions,
|
||||
# 3) Replaces the string --VERS-- with the current library version,
|
||||
# 3) Replaces the string --VERS-- with the current library version,
|
||||
# formatted as a string (e.g. "3.6.17"), and
|
||||
# 4) Replaces the string --VERSION-NUMBER-- with current library version,
|
||||
# formatted as an integer (e.g. "3006017").
|
||||
# 5) Replaces the string --SOURCE-ID-- with the date and time and sha1
|
||||
# 5) Replaces the string --SOURCE-ID-- with the date and time and sha1
|
||||
# hash of the fossil-scm manifest for the source tree.
|
||||
# 6) Adds the SQLITE_CALLBACK calling convention macro in front of all
|
||||
# callback declarations.
|
||||
#
|
||||
# This script outputs to stdout.
|
||||
#
|
||||
@@ -34,6 +36,14 @@
|
||||
#
|
||||
set TOP [lindex $argv 0]
|
||||
|
||||
# Enable use of SQLITE_APICALL macros at the right points?
|
||||
#
|
||||
set useapicall 0
|
||||
|
||||
if {[lsearch -regexp [lrange $argv 1 end] {^-+useapicall}] != -1} {
|
||||
set useapicall 1
|
||||
}
|
||||
|
||||
# Get the SQLite version number (ex: 3.6.18) from the $TOP/VERSION file.
|
||||
#
|
||||
set in [open $TOP/VERSION]
|
||||
@@ -96,14 +106,14 @@ foreach file $filelist {
|
||||
puts "/******** Begin file [file tail $file] *********/"
|
||||
}
|
||||
while {![eof $in]} {
|
||||
|
||||
|
||||
set line [gets $in]
|
||||
|
||||
# File sqlite3rtree.h contains a line "#include <sqlite3.h>". Omit this
|
||||
# line when copying sqlite3rtree.h into sqlite3.h.
|
||||
#
|
||||
if {[string match {*#include*[<"]sqlite3.h[>"]*} $line]} continue
|
||||
|
||||
|
||||
regsub -- --VERS-- $line $zVersion line
|
||||
regsub -- --VERSION-NUMBER-- $line $nVersion line
|
||||
regsub -- --SOURCE-ID-- $line "$zDate $zUuid" line
|
||||
@@ -117,14 +127,21 @@ foreach file $filelist {
|
||||
if {[string index $rettype end] ne "*"} {
|
||||
append line " "
|
||||
}
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL
|
||||
} else {
|
||||
append line SQLITE_STDCALL
|
||||
if {$useapicall} {
|
||||
if {[lsearch -exact $cdecllist $funcname] >= 0} {
|
||||
append line SQLITE_CDECL " "
|
||||
} else {
|
||||
append line SQLITE_APICALL " "
|
||||
}
|
||||
}
|
||||
append line " " $funcname $rest
|
||||
append line $funcname $rest
|
||||
}
|
||||
}
|
||||
if {$useapicall} {
|
||||
set line [string map [list (*sqlite3_syscall_ptr) \
|
||||
"(SQLITE_SYSAPI *sqlite3_syscall_ptr)"] $line]
|
||||
regsub {\(\*} $line {(SQLITE_CALLBACK *} line
|
||||
}
|
||||
puts $line
|
||||
}
|
||||
close $in
|
||||
|
||||
+54
-3
@@ -22,6 +22,33 @@ proc is_without_rowid {tname} {
|
||||
return 0
|
||||
}
|
||||
|
||||
# Read and run TCL commands from standard input. Used to implement
|
||||
# the --tclsh option.
|
||||
#
|
||||
proc tclsh {} {
|
||||
set line {}
|
||||
while {![eof stdin]} {
|
||||
if {$line!=""} {
|
||||
puts -nonewline "> "
|
||||
} else {
|
||||
puts -nonewline "% "
|
||||
}
|
||||
flush stdout
|
||||
append line [gets stdin]
|
||||
if {[info complete $line]} {
|
||||
if {[catch {uplevel #0 $line} result]} {
|
||||
puts stderr "Error: $result"
|
||||
} elseif {$result!=""} {
|
||||
puts $result
|
||||
}
|
||||
set line {}
|
||||
} else {
|
||||
append line \n
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Get the name of the database to analyze
|
||||
#
|
||||
proc usage {} {
|
||||
@@ -34,22 +61,37 @@ information for the database and its constituent tables and indexes.
|
||||
|
||||
Options:
|
||||
|
||||
--stats Output SQL text that creates a new database containing
|
||||
statistics about the database that was analyzed
|
||||
--pageinfo Show how each page of the database-file is used
|
||||
|
||||
--pageinfo Show how each page of the database-file is used
|
||||
--stats Output SQL text that creates a new database containing
|
||||
statistics about the database that was analyzed
|
||||
|
||||
--tclsh Run the built-in TCL interpreter interactively (for debugging)
|
||||
|
||||
--version Show the version number of SQLite
|
||||
}
|
||||
exit 1
|
||||
}
|
||||
set file_to_analyze {}
|
||||
set flags(-pageinfo) 0
|
||||
set flags(-stats) 0
|
||||
set flags(-debug) 0
|
||||
append argv {}
|
||||
foreach arg $argv {
|
||||
if {[regexp {^-+pageinfo$} $arg]} {
|
||||
set flags(-pageinfo) 1
|
||||
} elseif {[regexp {^-+stats$} $arg]} {
|
||||
set flags(-stats) 1
|
||||
} elseif {[regexp {^-+debug$} $arg]} {
|
||||
set flags(-debug) 1
|
||||
} elseif {[regexp {^-+tclsh$} $arg]} {
|
||||
tclsh
|
||||
exit 0
|
||||
} elseif {[regexp {^-+version$} $arg]} {
|
||||
sqlite3 mem :memory:
|
||||
puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
|
||||
mem close
|
||||
exit 0
|
||||
} elseif {[regexp {^-} $arg]} {
|
||||
puts stderr "Unknown option: $arg"
|
||||
usage
|
||||
@@ -100,6 +142,10 @@ if {[catch {sqlite3 db $file_to_analyze -uri 1} msg]} {
|
||||
puts stderr "error trying to open $file_to_analyze: $msg"
|
||||
exit 1
|
||||
}
|
||||
if {$flags(-debug)} {
|
||||
proc dbtrace {txt} {puts $txt; flush stdout;}
|
||||
db trace ::dbtrace
|
||||
}
|
||||
|
||||
db eval {SELECT count(*) FROM sqlite_master}
|
||||
set pageSize [expr {wide([db one {PRAGMA page_size}])}]
|
||||
@@ -142,12 +188,17 @@ if {$flags(-stats)} {
|
||||
exit 0
|
||||
}
|
||||
|
||||
|
||||
# In-memory database for collecting statistics. This script loops through
|
||||
# the tables and indices in the database being analyzed, adding a row for each
|
||||
# to an in-memory database (for which the schema is shown below). It then
|
||||
# queries the in-memory db to produce the space-analysis report.
|
||||
#
|
||||
sqlite3 mem :memory:
|
||||
if {$flags(-debug)} {
|
||||
proc dbtrace {txt} {puts $txt; flush stdout;}
|
||||
mem trace ::dbtrace
|
||||
}
|
||||
set tabledef {CREATE TABLE space_used(
|
||||
name clob, -- Name of a table or index in the database file
|
||||
tblname clob, -- Name of associated table
|
||||
|
||||
+19
-2
@@ -21,9 +21,20 @@ then
|
||||
fi
|
||||
NAME=$1
|
||||
shift
|
||||
CC_OPTS="-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MEMSYS5"
|
||||
SPEEDTEST_OPTS="--shrink-memory --reprepare --heap 10000000 64"
|
||||
#CC_OPTS="-DSQLITE_ENABLE_RTREE -DSQLITE_ENABLE_MEMSYS5"
|
||||
CC_OPTS="-DSQLITE_ENABLE_MEMSYS5"
|
||||
SPEEDTEST_OPTS="--shrink-memory --reprepare --stats --heap 10000000 64"
|
||||
SIZE=5
|
||||
LEAN_OPTS="-DSQLITE_THREADSAFE=0"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_MEMSTATUS=0"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_DEFAULT_WAL_SYNCHRONOUS=1"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_LIKE_DOESNT_MATCH_BLOB"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_MAX_EXPR_DEPTH=0"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DECLTYPE"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_DEPRECATED"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_PROGRESS_CALLBACK"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_OMIT_SHARED_CACHE"
|
||||
LEAN_OPTS="$LEAN_OPTS -DSQLITE_USE_ALLOCA"
|
||||
doExplain=0
|
||||
doCachegrind=1
|
||||
while test "$1" != ""; do
|
||||
@@ -55,6 +66,9 @@ while test "$1" != ""; do
|
||||
--size)
|
||||
shift; SIZE=$1
|
||||
;;
|
||||
--cachesize)
|
||||
shift; SPEEDTEST_OPTS="$SPEEDTEST_OPTS --cachesize $1"
|
||||
;;
|
||||
--explain)
|
||||
doExplain=1
|
||||
;;
|
||||
@@ -63,6 +77,9 @@ while test "$1" != ""; do
|
||||
CC_OPTS="$CC_OPTS -DVDBE_PROFILE"
|
||||
doCachegrind=0
|
||||
;;
|
||||
--lean)
|
||||
CC_OPTS="$CC_OPTS $LEAN_OPTS"
|
||||
;;
|
||||
--heap)
|
||||
CC_OPTS="$CC_OPTS -DSQLITE_ENABLE_MEMSYS5"
|
||||
shift;
|
||||
|
||||
+2
-1
@@ -403,7 +403,8 @@ static void printQuoted(FILE *out, sqlite3_value *X){
|
||||
}
|
||||
fprintf(out, "'");
|
||||
}else{
|
||||
fprintf(out, "NULL");
|
||||
/* Could be an OOM, could be a zero-byte blob */
|
||||
fprintf(out, "X''");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
+17
-4
@@ -3,15 +3,26 @@
|
||||
# Run this script in a directory with a working makefile to check for
|
||||
# compiler warnings in SQLite.
|
||||
#
|
||||
|
||||
# Use these for testing on Linux and Mac OSX:
|
||||
WARNING_OPTS="-Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long"
|
||||
WARNING_ANDROID_OPTS="-Wshadow -Wall -Wextra"
|
||||
|
||||
# Use these for testing on OpenBSD:
|
||||
# WARNING_OPTS=-Wall
|
||||
# WARNING_ANDROID_OPTS=-Wall
|
||||
|
||||
rm -f sqlite3.c
|
||||
make sqlite3.c
|
||||
echo '********** No optimizations. Includes FTS4/5, RTREE, JSON1 ***'
|
||||
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
echo '********** ' Options: $WARNING_OPTS
|
||||
gcc -c $WARNING_OPTS -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
|
||||
sqlite3.c
|
||||
if test x`uname` = 'xLinux'; then
|
||||
echo '********** Android configuration ******************************'
|
||||
echo '********** ' Options: $WARNING_ANDROID_OPTS
|
||||
gcc -c \
|
||||
-DHAVE_USLEEP=1 \
|
||||
-DSQLITE_HAVE_ISNAN \
|
||||
@@ -31,15 +42,17 @@ gcc -c \
|
||||
-DSQLITE_DEFAULT_FILE_PERMISSIONS=0600 \
|
||||
-DSQLITE_ENABLE_ICU \
|
||||
-DUSE_PREAD64 \
|
||||
-Wshadow -Wall -Wextra \
|
||||
$WARNING_ANDROID_OPTS \
|
||||
-Os sqlite3.c shell.c
|
||||
fi
|
||||
echo '********** No optimizations. ENABLE_STAT4. THREADSAFE=0 *******'
|
||||
gcc -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
echo '********** ' Options: $WARNING_OPTS
|
||||
gcc -c $WARNING_OPTS -std=c89 \
|
||||
-ansi -DSQLITE_ENABLE_STAT4 -DSQLITE_THREADSAFE=0 \
|
||||
sqlite3.c
|
||||
echo '********** Optimized -O3. Includes FTS4/5, RTREE, JSON1 ******'
|
||||
gcc -O3 -c -Wshadow -Wall -Wextra -pedantic-errors -Wno-long-long -std=c89 \
|
||||
echo '********** ' Options: $WARNING_OPTS
|
||||
gcc -O3 -c $WARNING_OPTS -std=c89 \
|
||||
-ansi -DHAVE_STDINT_H -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_RTREE \
|
||||
-DSQLITE_ENABLE_FTS5 -DSQLITE_ENABLE_JSON1 \
|
||||
sqlite3.c
|
||||
|
||||
Reference in New Issue
Block a user