Compare commits

..

1 Commits

Author SHA1 Message Date
drh f90c49ac61 Avoid adding an artifical "LIMIT 1" on scalar subqueries that do not need it.
This seems like a pointless optimization as it makes minimal run-time difference
but does increase code complexity.  Parked on a branch for historical
reference.

FossilOrigin-Name: c21628e9c166d8481138e04cfbc2ea5a54e92f6588d4407f615094e2e5a4b458
2017-06-17 19:06:17 +00:00
439 changed files with 6530 additions and 53974 deletions
+19 -70
View File
@@ -166,8 +166,7 @@ USE_AMALGAMATION = @USE_AMALGAMATION@
#
LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo \
date.lo dbpage.lo dbstat.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -182,7 +181,7 @@ LIBOBJS0 = alter.lo analyze.lo attach.lo auth.lo \
notify.lo opcodes.lo os.lo os_unix.lo os_win.lo \
pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
random.lo resolve.lo rowset.lo rtree.lo \
sqlite3session.lo select.lo sqlite3rbu.lo status.lo stmt.lo \
sqlite3session.lo select.lo sqlite3rbu.lo status.lo \
table.lo threads.lo tokenize.lo treeview.lo trigger.lo \
update.lo util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo vdbesort.lo \
@@ -216,7 +215,6 @@ SRC = \
$(TOP)/src/complete.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
@@ -267,7 +265,7 @@ SRC = \
$(TOP)/src/rowset.c \
$(TOP)/src/select.c \
$(TOP)/src/status.c \
$(TOP)/src/shell.c.in \
$(TOP)/src/shell.c \
$(TOP)/src/sqlite.h.in \
$(TOP)/src/sqlite3ext.h \
$(TOP)/src/sqliteInt.h \
@@ -352,8 +350,7 @@ SRC += \
$(TOP)/ext/rbu/sqlite3rbu.h \
$(TOP)/ext/rbu/sqlite3rbu.c
SRC += \
$(TOP)/ext/misc/json1.c \
$(TOP)/ext/misc/stmt.c
$(TOP)/ext/misc/json1.c
# Generated source code files
#
@@ -364,7 +361,6 @@ SRC += \
parse.c \
parse.h \
config.h \
shell.c \
sqlite3.h
# Source code to the test files.
@@ -396,7 +392,6 @@ TESTSRC = \
$(TOP)/src/test_intarray.c \
$(TOP)/src/test_journal.c \
$(TOP)/src/test_malloc.c \
$(TOP)/src/test_md5.c \
$(TOP)/src/test_multiplex.c \
$(TOP)/src/test_mutex.c \
$(TOP)/src/test_onefile.c \
@@ -408,7 +403,6 @@ TESTSRC = \
$(TOP)/src/test_server.c \
$(TOP)/src/test_superlock.c \
$(TOP)/src/test_syscall.c \
$(TOP)/src/test_tclsh.c \
$(TOP)/src/test_tclvar.c \
$(TOP)/src/test_thread.c \
$(TOP)/src/test_vfs.c \
@@ -433,7 +427,6 @@ TESTSRC += \
$(TOP)/ext/fts5/fts5_test_mi.c \
$(TOP)/ext/fts5/fts5_test_tok.c \
$(TOP)/ext/misc/ieee754.c \
$(TOP)/ext/misc/mmapwarm.c \
$(TOP)/ext/misc/nextchar.c \
$(TOP)/ext/misc/percentile.c \
$(TOP)/ext/misc/regexp.c \
@@ -441,7 +434,6 @@ TESTSRC += \
$(TOP)/ext/misc/series.c \
$(TOP)/ext/misc/spellfix.c \
$(TOP)/ext/misc/totype.c \
$(TOP)/ext/misc/unionvtab.c \
$(TOP)/ext/misc/wholenumber.c
# Source code to the library files needed by the test fixture
@@ -454,7 +446,6 @@ TESTSRC2 = \
$(TOP)/src/build.c \
$(TOP)/src/ctime.c \
$(TOP)/src/date.c \
$(TOP)/src/dbpage.c \
$(TOP)/src/dbstat.c \
$(TOP)/src/expr.c \
$(TOP)/src/func.c \
@@ -492,8 +483,7 @@ TESTSRC2 = \
$(TOP)/ext/fts3/fts3_tokenizer.c \
$(TOP)/ext/fts3/fts3_write.c \
$(TOP)/ext/async/sqlite3async.c \
$(TOP)/ext/session/sqlite3session.c \
$(TOP)/ext/misc/stmt.c
$(TOP)/ext/session/sqlite3session.c
# Header files used by all library source files.
#
@@ -574,9 +564,6 @@ SHELL_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4
# SHELL_OPT += -DSQLITE_ENABLE_FTS5
SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS
SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB
SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB
SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB
FUZZERSHELL_OPT = -DSQLITE_ENABLE_JSON1
FUZZCHECK_OPT = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ
FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000
@@ -605,9 +592,9 @@ libtclsqlite3.la: tclsqlite.lo libsqlite3.la
-version-info "8:6:8" \
-avoid-version
sqlite3$(TEXE): shell.c sqlite3.c
sqlite3$(TEXE): $(TOP)/src/shell.c sqlite3.c
$(LTLINK) $(READLINE_FLAGS) $(SHELL_OPT) -o $@ \
shell.c sqlite3.c \
$(TOP)/src/shell.c sqlite3.c \
$(LIBREADLINE) $(TLIBS) -rpath "$(libdir)"
sqldiff$(TEXE): $(TOP)/tool/sqldiff.c sqlite3.lo sqlite3.h
@@ -676,7 +663,7 @@ mptest: mptester$(TEXE)
sqlite3.c: .target_source $(TOP)/tool/mksqlite3c.tcl
$(TCLSH_CMD) $(TOP)/tool/mksqlite3c.tcl
cp tsrc/sqlite3ext.h .
cp tsrc/shell.c tsrc/sqlite3ext.h .
cp $(TOP)/ext/session/sqlite3session.h .
sqlite3ext.h: .target_source
@@ -702,11 +689,6 @@ lemon$(BEXE): $(TOP)/tool/lemon.c $(TOP)/tool/lempar.c
$(BCC) -o $@ $(TOP)/tool/lemon.c
cp $(TOP)/tool/lempar.c .
# Rules to build the program that generates the source-id
#
mksourceid$(BEXE): $(TOP)/tool/mksourceid.c
$(BCC) -o $@ $(TOP)/tool/mksourceid.c
# Rules to build individual *.o files from generated *.c files. This
# applies to:
#
@@ -760,9 +742,6 @@ ctime.lo: $(TOP)/src/ctime.c $(HDR)
date.lo: $(TOP)/src/date.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/date.c
dbpage.lo: $(TOP)/src/dbpage.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbpage.c
dbstat.lo: $(TOP)/src/dbstat.c $(HDR)
$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/dbstat.c
@@ -947,7 +926,7 @@ tclsqlite.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -c $(TOP)/src/tclsqlite.c
tclsqlite-shell.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DTCLSH -o $@ -c $(TOP)/src/tclsqlite.c
$(LTCOMPILE) -DTCLSH=1 -o $@ -c $(TOP)/src/tclsqlite.c
tclsqlite-stubs.lo: $(TOP)/src/tclsqlite.c $(HDR)
$(LTCOMPILE) -DUSE_TCL_STUBS=1 -o $@ -c $(TOP)/src/tclsqlite.c
@@ -975,24 +954,13 @@ parse.c: $(TOP)/src/parse.y lemon$(BEXE) $(TOP)/tool/addopcodes.tcl
mv parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)/tool/addopcodes.tcl parse.h.temp >parse.h
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest mksourceid$(BEXE) $(TOP)/VERSION
sqlite3.h: $(TOP)/src/sqlite.h.in $(TOP)/manifest.uuid $(TOP)/VERSION
$(TCLSH_CMD) $(TOP)/tool/mksqlite3h.tcl $(TOP) >sqlite3.h
keywordhash.h: $(TOP)/tool/mkkeywordhash.c
$(BCC) -o mkkeywordhash$(BEXE) $(OPT_FEATURE_FLAGS) $(OPTS) $(TOP)/tool/mkkeywordhash.c
./mkkeywordhash$(BEXE) >keywordhash.h
# Source files that go into making shell.c
SHELL_SRC = \
$(TOP)/src/shell.c.in \
$(TOP)/ext/misc/shathree.c \
$(TOP)/ext/misc/fileio.c \
$(TOP)/ext/misc/completion.c
shell.c: $(SHELL_SRC) $(TOP)/tool/mkshellc.tcl
$(TCLSH_CMD) $(TOP)/tool/mkshellc.tcl >shell.c
# Rules to build the extension objects.
@@ -1066,9 +1034,6 @@ sqlite3session.lo: $(TOP)/ext/session/sqlite3session.c $(HDR) $(EXTHDR)
json1.lo: $(TOP)/ext/misc/json1.c
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/json1.c
stmt.lo: $(TOP)/ext/misc/stmt.c
$(LTCOMPILE) -DSQLITE_CORE -c $(TOP)/ext/misc/stmt.c
# FTS5 things
#
FTS5_SRC = \
@@ -1113,14 +1078,11 @@ sqlite3rbu.lo: $(TOP)/ext/rbu/sqlite3rbu.c $(HDR) $(EXTHDR)
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS += -DTCLSH_INIT_PROC=sqlite3TestInit
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE
TESTFIXTURE_FLAGS += -DBUILD_sqlite
TESTFIXTURE_FLAGS += -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
TESTFIXTURE_FLAGS += -DSQLITE_DEFAULT_PAGE_SIZE=1024
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS += -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_SRC0 = $(TESTSRC2) libsqlite3.la
TESTFIXTURE_SRC1 = sqlite3.c
@@ -1181,28 +1143,18 @@ valgrindtest: $(TESTPROGS) valgrindfuzz
smoketest: $(TESTPROGS) fuzzcheck$(TEXE)
./testfixture$(TEXE) $(TOP)/test/main.test $(TESTOPTS)
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/tool/sqlite3_analyzer.c.in >sqlite3_analyzer.c
sqlite3_analyzer.c: sqlite3.c $(TOP)/src/tclsqlite.c $(TOP)/tool/spaceanal.tcl
echo "#define TCLSH 2" > $@
echo "#define SQLITE_ENABLE_DBSTAT_VTAB 1" >> $@
cat sqlite3.c $(TOP)/src/tclsqlite.c >> $@
echo "static const char *tclsh_main_loop(void){" >> $@
echo "static const char *zMainloop = " >> $@
$(TCLSH_CMD) $(TOP)/tool/tostr.tcl $(TOP)/tool/spaceanal.tcl >> $@
echo "; return zMainloop; }" >> $@
sqlite3_analyzer$(TEXE): sqlite3_analyzer.c
$(LTLINK) sqlite3_analyzer.c -o $@ $(LIBTCL) $(TLIBS)
CHECKER_DEPS =\
$(TOP)/tool/mkccode.tcl \
sqlite3.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/ext/repair/sqlite3_checker.tcl \
$(TOP)/ext/repair/checkindex.c \
$(TOP)/ext/repair/checkfreelist.c \
$(TOP)/ext/misc/btreeinfo.c \
$(TOP)/ext/repair/sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
$(TCLSH_CMD) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
sqlite3_checker$(TEXE): sqlite3_checker.c
$(LTLINK) sqlite3_checker.c -o $@ $(LIBTCL) $(TLIBS)
dbdump$(TEXE): $(TOP)/ext/misc/dbdump.c sqlite3.lo
$(LTLINK) -DDBDUMP_STANDALONE -o $@ \
$(TOP)/ext/misc/dbdump.c sqlite3.lo $(TLIBS)
@@ -1219,9 +1171,6 @@ showjournal$(TEXE): $(TOP)/tool/showjournal.c sqlite3.lo
showwal$(TEXE): $(TOP)/tool/showwal.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/tool/showwal.c sqlite3.lo $(TLIBS)
showshm$(TEXE): $(TOP)/tool/showshm.c
$(LTLINK) -o $@ $(TOP)/tool/showshm.c
changeset$(TEXE): $(TOP)/ext/session/changeset.c sqlite3.lo
$(LTLINK) -o $@ $(TOP)/ext/session/changeset.c sqlite3.lo $(TLIBS)
+27 -68
View File
@@ -1091,8 +1091,7 @@ LTLIBS = $(LTLIBS) $(LIBICU)
#
LIBOBJS0 = vdbe.lo parse.lo alter.lo analyze.lo attach.lo auth.lo \
backup.lo bitvec.lo btmutex.lo btree.lo build.lo \
callback.lo complete.lo ctime.lo \
date.lo dbpage.lo dbstat.lo delete.lo \
callback.lo complete.lo ctime.lo date.lo dbstat.lo delete.lo \
expr.lo fault.lo fkey.lo \
fts3.lo fts3_aux.lo fts3_expr.lo fts3_hash.lo fts3_icu.lo \
fts3_porter.lo fts3_snippet.lo fts3_tokenizer.lo fts3_tokenizer1.lo \
@@ -1155,7 +1154,6 @@ SRC00 = \
$(TOP)\src\complete.c \
$(TOP)\src\ctime.c \
$(TOP)\src\date.c \
$(TOP)\src\dbpage.c \
$(TOP)\src\dbstat.c \
$(TOP)\src\delete.c \
$(TOP)\src\expr.c \
@@ -1222,6 +1220,11 @@ SRC01 = \
$(TOP)\src\wherecode.c \
$(TOP)\src\whereexpr.c
# Shell source code files.
#
SRC02 = \
$(TOP)\src\shell.c
# Core miscellaneous files.
#
SRC03 = \
@@ -1291,8 +1294,7 @@ SRC07 = \
$(TOP)\ext\rtree\rtree.c \
$(TOP)\ext\session\sqlite3session.c \
$(TOP)\ext\rbu\sqlite3rbu.c \
$(TOP)\ext\misc\json1.c \
$(TOP)\ext\misc\stmt.c
$(TOP)\ext\misc\json1.c
# Extension header files, part 1.
#
@@ -1328,7 +1330,6 @@ SRC11 = \
keywordhash.h \
opcodes.h \
parse.h \
shell.c \
$(SQLITE3H)
# Generated Tcl header files
@@ -1343,7 +1344,7 @@ SRC12 =
# All source code files.
#
SRC = $(SRC00) $(SRC01) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
SRC = $(SRC00) $(SRC01) $(SRC02) $(SRC03) $(SRC04) $(SRC05) $(SRC06) $(SRC07) $(SRC08) $(SRC09) $(SRC10) $(SRC11)
# Source code to the test files.
#
@@ -1374,7 +1375,6 @@ TESTSRC = \
$(TOP)\src\test_intarray.c \
$(TOP)\src\test_journal.c \
$(TOP)\src\test_malloc.c \
$(TOP)\src\test_md5.c \
$(TOP)\src\test_multiplex.c \
$(TOP)\src\test_mutex.c \
$(TOP)\src\test_onefile.c \
@@ -1386,7 +1386,6 @@ TESTSRC = \
$(TOP)\src\test_server.c \
$(TOP)\src\test_superlock.c \
$(TOP)\src\test_syscall.c \
$(TOP)\src\test_tclsh.c \
$(TOP)\src\test_tclvar.c \
$(TOP)\src\test_thread.c \
$(TOP)\src\test_vfs.c \
@@ -1411,7 +1410,6 @@ TESTEXT = \
$(TOP)\ext\fts5\fts5_test_mi.c \
$(TOP)\ext\fts5\fts5_test_tok.c \
$(TOP)\ext\misc\ieee754.c \
$(TOP)\ext\misc\mmapwarm.c \
$(TOP)\ext\misc\nextchar.c \
$(TOP)\ext\misc\percentile.c \
$(TOP)\ext\misc\regexp.c \
@@ -1419,7 +1417,6 @@ TESTEXT = \
$(TOP)\ext\misc\series.c \
$(TOP)\ext\misc\spellfix.c \
$(TOP)\ext\misc\totype.c \
$(TOP)\ext\misc\unionvtab.c \
$(TOP)\ext\misc\wholenumber.c
# Source code to the library files needed by the test fixture
@@ -1491,7 +1488,6 @@ TESTPROGS = \
testfixture.exe \
$(SQLITE3EXE) \
sqlite3_analyzer.exe \
sqlite3_checker.exe \
sqldiff.exe \
dbhash.exe
@@ -1509,14 +1505,13 @@ FUZZDATA = \
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
!ENDIF
# <<mark>>
# Extra compiler options for various test tools.
#
MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS5
MPTESTER_COMPILE_OPTS = -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS5
FUZZERSHELL_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1
FUZZCHECK_COMPILE_OPTS = -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ -DSQLITE_MAX_MEMORY=50000000
FUZZCHECK_SRC = $(TOP)\test\fuzzcheck.c $(TOP)\test\ossfuzz.c
@@ -1571,8 +1566,8 @@ sqlite3.def: libsqlite3.lib
| sort >> sqlite3.def
# <</block2>>
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
$(SQLITE3EXE): $(TOP)\src\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\src\shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
# <<mark>>
@@ -1631,6 +1626,7 @@ mptest: mptester.exe
-mkdir tsrc
for %i in ($(SRC00)) do copy /Y %i tsrc
for %i in ($(SRC01)) do copy /Y %i tsrc
for %i in ($(SRC02)) do copy /Y %i tsrc
for %i in ($(SRC03)) do copy /Y %i tsrc
for %i in ($(SRC04)) do copy /Y %i tsrc
for %i in ($(SRC05)) do copy /Y %i tsrc
@@ -1650,6 +1646,7 @@ mptest: mptester.exe
sqlite3.c: .target_source sqlite3ext.h $(MKSQLITE3C_TOOL)
$(TCLSH_CMD) $(MKSQLITE3C_TOOL) $(MKSQLITE3C_ARGS)
copy tsrc\shell.c .
copy $(TOP)\ext\session\sqlite3session.h .
sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl
@@ -1671,12 +1668,6 @@ lemon.exe: $(TOP)\tool\lemon.c lempar.c
$(BCC) $(NO_WARN) -Daccess=_access \
-Fe$@ $(TOP)\tool\lemon.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
# <<mark>>
# Rules to build the source-id generator tool
#
mksourceid.exe: $(TOP)\tool\mksourceid.c
$(BCC) $(NO_WARN) -Fe$@ $(TOP)\tool\mksourceid.c /link $(LDFLAGS) $(NLTLINKOPTS) $(NLTLIBPATHS)
# Rules to build individual *.lo files from generated *.c files. This
# applies to:
#
@@ -1747,10 +1738,7 @@ ctime.lo: $(TOP)\src\ctime.c $(HDR)
date.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\date.c
dbpage.lo: $(TOP)\src\dbpage.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbpage.c
dbstat.lo: $(TOP)\src\dbstat.c $(HDR)
dbstat.lo: $(TOP)\src\date.c $(HDR)
$(LTCOMPILE) $(CORE_COMPILE_OPTS) -c $(TOP)\src\dbstat.c
delete.lo: $(TOP)\src\delete.c $(HDR)
@@ -1934,7 +1922,7 @@ 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) $(SQLITE_TCL_DEP)
$(LTCOMPILE) $(NO_WARN) -DTCLSH -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
$(LTCOMPILE) $(NO_WARN) -DTCLSH=1 -DBUILD_sqlite -I$(TCLINCDIR) -c $(TOP)\src\tclsqlite.c
tclsqlite3.exe: tclsqlite-shell.lo $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
$(LTLINK) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /OUT:$@ tclsqlite-shell.lo $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
@@ -1958,7 +1946,7 @@ parse.c: $(TOP)\src\parse.y lemon.exe $(TOP)\tool\addopcodes.tcl
move parse.h parse.h.temp
$(TCLSH_CMD) $(TOP)\tool\addopcodes.tcl parse.h.temp > parse.h
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest mksourceid.exe $(TOP)\VERSION
$(SQLITE3H): $(TOP)\src\sqlite.h.in $(TOP)\manifest.uuid $(TOP)\VERSION
$(TCLSH_CMD) $(TOP)\tool\mksqlite3h.tcl $(TOP:\=/) > $(SQLITE3H) $(MKSQLITE3H_ARGS)
sqlite3ext.h: .target_source
@@ -1977,15 +1965,6 @@ mkkeywordhash.exe: $(TOP)\tool\mkkeywordhash.c
keywordhash.h: $(TOP)\tool\mkkeywordhash.c mkkeywordhash.exe
.\mkkeywordhash.exe > keywordhash.h
# Source files that go into making shell.c
SHELL_SRC = \
$(TOP)\src\shell.c.in \
$(TOP)\ext\misc\shathree.c \
$(TOP)\ext\misc\fileio.c \
$(TOP)\ext\misc\completion.c
shell.c: $(SHELL_SRC) $(TOP)\tool\mkshellc.tcl
$(TCLSH_CMD) $(TOP)\tool\mkshellc.tcl > shell.c
# Rules to build the extension objects.
@@ -2105,13 +2084,11 @@ sqlite3rbu.lo: $(TOP)\ext\rbu\sqlite3rbu.c $(HDR) $(EXTHDR)
# necessary because the test fixture requires non-API symbols which are
# hidden when the library is built via the amalgamation).
#
TESTFIXTURE_FLAGS = -DTCLSH_INIT_PROC=sqlite3TestInit -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
TESTFIXTURE_FLAGS = -DTCLSH=1 -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1
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) -DSQLITE_ENABLE_STMTVTAB
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) -DSQLITE_ENABLE_DBPAGE_VTAB
TESTFIXTURE_FLAGS = $(TESTFIXTURE_FLAGS) $(TEST_CCONV_OPTS)
TESTFIXTURE_SRC0 = $(TESTEXT) $(TESTSRC2)
@@ -2191,30 +2168,19 @@ 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 $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in $(SQLITE_TCL_DEP)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\tool\sqlite3_analyzer.c.in > $@
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 $@
echo static const char *tclsh_main_loop(void){ >> $@
echo static const char *zMainloop = >> $@
$(TCLSH_CMD) $(TOP)\tool\tostr.tcl $(TOP)\tool\spaceanal.tcl >> $@
echo ; return zMainloop; } >> $@
sqlite3_analyzer.exe: sqlite3_analyzer.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_analyzer.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
CHECKER_DEPS =\
$(TOP)/tool/mkccode.tcl \
sqlite3.c \
$(TOP)/src/tclsqlite.c \
$(TOP)/ext/repair/sqlite3_checker.tcl \
$(TOP)/ext/repair/checkindex.c \
$(TOP)/ext/repair/checkfreelist.c \
$(TOP)/ext/misc/btreeinfo.c \
$(TOP)/ext/repair/sqlite3_checker.c.in
sqlite3_checker.c: $(CHECKER_DEPS)
$(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
sqlite3_checker.exe: sqlite3_checker.c $(LIBRESOBJS)
$(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS) $(TLIBS)
dbdump.exe: $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
/link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
@@ -2241,9 +2207,6 @@ showwal.exe: $(TOP)\tool\showwal.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
$(TOP)\tool\showwal.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
showshm.exe: $(TOP)\tool\showshm.c
$(LTLINK) $(NO_WARN) $(TOP)\tool\showshm.c /link $(LDFLAGS) $(LTLINKOPTS)
changeset.exe: $(TOP)\ext\session\changeset.c $(SQLITE3C) $(SQLITE3H)
$(LTLINK) $(NO_WARN) -DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-DSQLITE_ENABLE_SESSION=1 -DSQLITE_ENABLE_PREUPDATE_HOOK=1 \
@@ -2279,9 +2242,6 @@ rbu.exe: $(TOP)\ext\rbu\rbu.c $(TOP)\ext\rbu\sqlite3rbu.c $(SQLITE3C) $(SQLITE3H
$(LTLINK) $(NO_WARN) -DSQLITE_ENABLE_RBU \
$(TOP)\ext\rbu\rbu.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS)
LSMDIR=$(TOP)\ext\lsm1
!INCLUDE $(LSMDIR)\Makefile.msc
moreclean: clean
del /Q $(SQLITE3C) $(SQLITE3H) 2>NUL
# <</mark>>
@@ -2294,14 +2254,13 @@ clean:
del /Q sqlite3.c sqlite3.h 2>NUL
del /Q opcodes.c opcodes.h 2>NUL
del /Q lemon.* lempar.c parse.* 2>NUL
del /Q mksourceid.* mkkeywordhash.* keywordhash.h 2>NUL
del /Q mkkeywordhash.* keywordhash.h 2>NUL
del /Q notasharedlib.* 2>NUL
-rmdir /Q/S .deps 2>NUL
-rmdir /Q/S .libs 2>NUL
-rmdir /Q/S tsrc 2>NUL
del /Q .target_source 2>NUL
del /Q tclsqlite3.exe $(SQLITETCLH) $(SQLITETCLDECLSH) 2>NUL
del /Q lsm.dll lsmtest.exe 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 dbdump.exe 2>NUL
+22 -34
View File
@@ -34,9 +34,7 @@ archives as follows:
If you do want to use Fossil to check out the source tree,
first install Fossil version 2.0 or later.
(Source tarballs and precompiled binaries available
[here](https://www.fossil-scm.org/fossil/uv/download.html). Fossil is
a stand-alone program. To install, simply download or build the single
executable file and put that file someplace on your $PATH.)
[here](https://www.fossil-scm.org/fossil/uv/download.html).)
Then run commands like this:
mkdir ~/sqlite
@@ -108,22 +106,19 @@ The makefiles also require AWK.
## Source Code Tour
Most of the core source files are in the **src/** subdirectory. The
**src/** folder also contains files used to build the "testfixture" test
harness. The names of the source files used by "testfixture" all begin
with "test".
The **src/** also contains the "shell.c" file
which is the main program for the "sqlite3.exe"
[command-line shell](https://sqlite.org/cli.html) and
the "tclsqlite.c" file which implements the
[TCL bindings](https://sqlite.org/tclsqlite.html) for SQLite.
(Historical note: SQLite began as a Tcl
Most of the core source files are in the **src/** subdirectory. But
src/ also contains files used to build the "testfixture" test harness;
those file all begin with "test". And src/ contains the "shell.c" file
which is the main program for the "sqlite3.exe" command-line shell and
the "tclsqlite.c" file which implements the bindings to SQLite from the
Tcl programming language. (Historical note: SQLite began as a Tcl
extension and only later escaped to the wild as an independent library.)
Test scripts and programs are found in the **test/** subdirectory.
Addtional test code is found in other source repositories.
See [How SQLite Is Tested](http://www.sqlite.org/testing.html) for
additional information.
There are other test suites for SQLite (see
[How SQLite Is Tested](http://www.sqlite.org/testing.html))
but those other test suites are
in separate source repositories.
The **ext/** subdirectory contains code for extensions. The
Full-text search engine is in **ext/fts3**. The R-Tree engine is in
@@ -147,7 +142,7 @@ manually-edited files and automatically-generated files.
The SQLite interface is defined by the **sqlite3.h** header file, which is
generated from src/sqlite.h.in, ./manifest.uuid, and ./VERSION. The
[Tcl script](http://www.tcl.tk) at tool/mksqlite3h.tcl does the conversion.
The manifest.uuid file contains the SHA3 hash of the particular check-in
The manifest.uuid file contains the SHA1 hash of the particular check-in
and is used to generate the SQLITE\_SOURCE\_ID macro. The VERSION file
contains the current SQLite version number. The sqlite3.h header is really
just a copy of src/sqlite.h.in with the source-id and version number inserted
@@ -158,8 +153,9 @@ used to generate that documentation are in a separate source repository.
The SQL language parser is **parse.c** which is generate from a grammar in
the src/parse.y file. The conversion of "parse.y" into "parse.c" is done
by the [lemon](./doc/lemon.html) LALR(1) parser generator. The source code
for lemon is at tool/lemon.c. Lemon uses the tool/lempar.c file as a
template for generating its parser.
for lemon is at tool/lemon.c. Lemon uses a
template for generating its parser. A generic template is in tool/lempar.c,
but SQLite uses a slightly modified template found in src/lempar.c.
Lemon also generates the **parse.h** header file, at the same time it
generates parse.c. But the parse.h header file is
@@ -179,13 +175,6 @@ that maps SQL language keywords (ex: "CREATE", "SELECT", "INDEX", etc.) into
the numeric codes used by the parse.c parser. The keywordhash.h file is
generated by a C-language program at tool mkkeywordhash.c.
The **pragma.h** header file contains various definitions used to parse
and implement the PRAGMA statements. The header is generated by a
script **tool/mkpragmatab.tcl**. If you want to add a new PRAGMA, edit
the **tool/mkpragmatab.tcl** file to insert the information needed by the
parser for your new PRAGMA, then run the script to regenerate the
**pragma.h** header file.
### The Amalgamation
All of the individual C source code and header files (both manually-edited
@@ -203,7 +192,7 @@ subdirectory (using the equivalent of "make target_source") then the
tool/mksqlite3c.tcl script is run to copy them all together in just the
right order while resolving internal "#include" references.
The amalgamation source file is more than 200K lines long. Some symbolic
The amalgamation source file is more than 100K lines long. Some symbolic
debuggers (most notably MSVC) are unable to deal with files longer than 64K
lines. To work around this, a separate Tcl script, tool/split-sqlite3c.tcl,
can be run on the amalgamation to break it up into a single small C file
@@ -220,15 +209,14 @@ See the [architectural description](http://www.sqlite.org/arch.html)
for details. Other documents that are useful in
(helping to understand how SQLite works include the
[file format](http://www.sqlite.org/fileformat2.html) description,
the [virtual machine](http://www.sqlite.org/opcode.html) that runs
the [virtual machine](http://www.sqlite.org/vdbe.html) that runs
prepared statements, the description of
[how transactions work](http://www.sqlite.org/atomiccommit.html), and
the [overview of the query planner](http://www.sqlite.org/optoverview.html).
Years of effort have gone into optimizating SQLite, both
Unfortunately, years of effort have gone into optimizating SQLite, both
for small size and high performance. And optimizations tend to result in
complex code. So there is a lot of complexity in the current SQLite
implementation. It will not be the easiest library in the world to hack.
complex code. So there is a lot of complexity in the SQLite implementation.
Key files:
@@ -239,7 +227,7 @@ Key files:
* **sqliteInt.h** - this header file defines many of the data objects
used internally by SQLite.
* **parse.y** - This file describes the LALR(1) grammar that SQLite uses
* **parse.y** - This file describes the LALR(1) grammer that SQLite uses
to parse SQL statements, and the actions that are taken at each step
in the parsing process.
@@ -272,13 +260,13 @@ Key files:
is not part of the core SQLite library. But as most of the tests in this
repository are written in Tcl, the Tcl language bindings are important.
There are many other source files. Each has a succinct header comment that
There are many other source files. Each has a suscinct header comment that
describes its purpose and role within the larger system.
## Contacts
The main SQLite webpage is [http://www.sqlite.org/](http://www.sqlite.org/)
with geographically distributed backups at
with geographically distributed backup servers at
[http://www2.sqlite.org/](http://www2.sqlite.org) and
[http://www3.sqlite.org/](http://www3.sqlite.org).
+1 -1
View File
@@ -1 +1 @@
3.22.0
3.20.0
+1 -1
View File
@@ -10,7 +10,7 @@ sqlite3_SOURCES = shell.c sqlite3.h
EXTRA_sqlite3_SOURCES = sqlite3.c
sqlite3_LDADD = @EXTRA_SHELL_OBJ@ @READLINE_LIBS@
sqlite3_DEPENDENCIES = @EXTRA_SHELL_OBJ@
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_STMTVTAB -DSQLITE_ENABLE_DBSTAT_VTAB
sqlite3_CFLAGS = $(AM_CFLAGS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS
include_HEADERS = sqlite3.h sqlite3ext.h
+4 -5
View File
@@ -927,8 +927,7 @@ LIBRESOBJS =
# when the shell is not being dynamically linked.
#
!IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS -DSQLITE_ENABLE_STMTVTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_DBPAGE_VTAB -DSQLITE_ENABLE_DBSTAT_VTAB
SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_SHELL_JSON1 -DSQLITE_ENABLE_FTS4 -DSQLITE_ENABLE_EXPLAIN_COMMENTS
!ENDIF
@@ -958,8 +957,8 @@ sqlite3.def: Replace.exe $(LIBOBJ)
| .\Replace.exe "^\s+/EXPORT:_?(sqlite3(?:session|changeset|changegroup)?_[^@,]*)(?:@\d+|,DATA)?$$" $$1 true \
| sort >> sqlite3.def
$(SQLITE3EXE): shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) shell.c $(SHELL_CORE_SRC) \
$(SQLITE3EXE): $(TOP)\shell.c $(SHELL_CORE_DEP) $(LIBRESOBJS) $(SHELL_CORE_SRC) $(SQLITE3H)
$(LTLINK) $(SHELL_COMPILE_OPTS) $(READLINE_FLAGS) $(TOP)\shell.c $(SHELL_CORE_SRC) \
/link $(SQLITE3EXEPDB) $(LDFLAGS) $(LTLINKOPTS) $(SHELL_LINK_OPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LIBREADLINE) $(LTLIBS) $(TLIBS)
@@ -974,7 +973,7 @@ sqlite3.lo: $(SQLITE3C)
!IF $(USE_RC)!=0
_HASHCHAR=^#
!IF ![echo !IFNDEF VERSION > rcver.vc] && \
![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| "%SystemRoot%\System32\find.exe" "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
![for /F "delims=" %V in ('type "$(SQLITE3H)" ^| find "$(_HASHCHAR)define SQLITE_VERSION "') do (echo VERSION = ^^%V >> rcver.vc)] && \
![echo !ENDIF >> rcver.vc]
!INCLUDE rcver.vc
!ENDIF
-1
View File
@@ -12,7 +12,6 @@
AC_PREREQ(2.61)
AC_INIT(sqlite, --SQLITE-VERSION--, http://www.sqlite.org)
AC_CONFIG_SRCDIR([sqlite3.c])
AC_CONFIG_AUX_DIR([.])
# Use automake.
AM_INIT_AUTOMAKE([foreign])
Vendored
+24 -40
View File
@@ -1,6 +1,6 @@
#! /bin/sh
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.69 for sqlite 3.22.0.
# Generated by GNU Autoconf 2.69 for sqlite 3.20.0.
#
#
# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
@@ -726,8 +726,8 @@ MAKEFLAGS=
# Identity of this package.
PACKAGE_NAME='sqlite'
PACKAGE_TARNAME='sqlite'
PACKAGE_VERSION='3.22.0'
PACKAGE_STRING='sqlite 3.22.0'
PACKAGE_VERSION='3.20.0'
PACKAGE_STRING='sqlite 3.20.0'
PACKAGE_BUGREPORT=''
PACKAGE_URL=''
@@ -909,7 +909,6 @@ enable_fts3
enable_fts4
enable_fts5
enable_json1
enable_update_limit
enable_rtree
enable_session
enable_gcov
@@ -1464,7 +1463,7 @@ if test "$ac_init_help" = "long"; then
# Omit some internal or obsolete options to make the list less imposing.
# This message is too long to be a string in the A/UX 3.1 sh.
cat <<_ACEOF
\`configure' configures sqlite 3.22.0 to adapt to many kinds of systems.
\`configure' configures sqlite 3.20.0 to adapt to many kinds of systems.
Usage: $0 [OPTION]... [VAR=VALUE]...
@@ -1529,7 +1528,7 @@ fi
if test -n "$ac_init_help"; then
case $ac_init_help in
short | recursive ) echo "Configuration of sqlite 3.22.0:";;
short | recursive ) echo "Configuration of sqlite 3.20.0:";;
esac
cat <<\_ACEOF
@@ -1561,7 +1560,6 @@ Optional Features:
--enable-fts4 Enable the FTS4 extension
--enable-fts5 Enable the FTS5 extension
--enable-json1 Enable the JSON1 extension
--enable-update-limit Enable the UPDATE/DELETE LIMIT clause
--enable-rtree Enable the RTREE extension
--enable-session Enable the SESSION extension
--enable-gcov Enable coverage testing using gcov
@@ -1654,7 +1652,7 @@ fi
test -n "$ac_init_help" && exit $ac_status
if $ac_init_version; then
cat <<\_ACEOF
sqlite configure 3.22.0
sqlite configure 3.20.0
generated by GNU Autoconf 2.69
Copyright (C) 2012 Free Software Foundation, Inc.
@@ -2073,7 +2071,7 @@ cat >config.log <<_ACEOF
This file contains any messages produced by compilers while
running configure, to aid debugging if configure makes a mistake.
It was created by sqlite $as_me 3.22.0, which was
It was created by sqlite $as_me 3.20.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
$ $0 $@
@@ -3931,13 +3929,13 @@ if ${lt_cv_nm_interface+:} false; then :
else
lt_cv_nm_interface="BSD nm"
echo "int some_variable = 0;" > conftest.$ac_ext
(eval echo "\"\$as_me:3934: $ac_compile\"" >&5)
(eval echo "\"\$as_me:3932: $ac_compile\"" >&5)
(eval "$ac_compile" 2>conftest.err)
cat conftest.err >&5
(eval echo "\"\$as_me:3937: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval echo "\"\$as_me:3935: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
(eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
cat conftest.err >&5
(eval echo "\"\$as_me:3940: output\"" >&5)
(eval echo "\"\$as_me:3938: output\"" >&5)
cat conftest.out >&5
if $GREP 'External.*some_variable' conftest.out > /dev/null; then
lt_cv_nm_interface="MS dumpbin"
@@ -5143,7 +5141,7 @@ ia64-*-hpux*)
;;
*-*-irix6*)
# Find out which ABI we are using.
echo '#line 5146 "configure"' > conftest.$ac_ext
echo '#line 5144 "configure"' > conftest.$ac_ext
if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5
(eval $ac_compile) 2>&5
ac_status=$?
@@ -6668,11 +6666,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:6671: $lt_compile\"" >&5)
(eval echo "\"\$as_me:6669: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:6675: \$? = $ac_status" >&5
echo "$as_me:6673: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7007,11 +7005,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7010: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7008: $lt_compile\"" >&5)
(eval "$lt_compile" 2>conftest.err)
ac_status=$?
cat conftest.err >&5
echo "$as_me:7014: \$? = $ac_status" >&5
echo "$as_me:7012: \$? = $ac_status" >&5
if (exit $ac_status) && test -s "$ac_outfile"; then
# The compiler can only warn and ignore the option if not recognized
# So say no if there are warnings other than the usual output.
@@ -7112,11 +7110,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7115: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7113: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7119: \$? = $ac_status" >&5
echo "$as_me:7117: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -7167,11 +7165,11 @@ else
-e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
-e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
-e 's:$: $lt_compiler_flag:'`
(eval echo "\"\$as_me:7170: $lt_compile\"" >&5)
(eval echo "\"\$as_me:7168: $lt_compile\"" >&5)
(eval "$lt_compile" 2>out/conftest.err)
ac_status=$?
cat out/conftest.err >&5
echo "$as_me:7174: \$? = $ac_status" >&5
echo "$as_me:7172: \$? = $ac_status" >&5
if (exit $ac_status) && test -s out/conftest2.$ac_objext
then
# The compiler can only warn and ignore the option if not recognized
@@ -9547,7 +9545,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9550 "configure"
#line 9548 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -9643,7 +9641,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 9646 "configure"
#line 9644 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -10304,7 +10302,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
for ac_prog in tclsh8.7 tclsh8.6 tclsh8.5 tclsh
for ac_prog in tclsh8.6 tclsh8.5 tclsh
do
# Extract the first word of "$ac_prog", so it can be a program name with args.
set dummy $ac_prog; ac_word=$2
@@ -11541,20 +11539,6 @@ if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
#########
# See whether we should enable the LIMIT clause on UPDATE and DELETE
# statements.
# Check whether --enable-update-limit was given.
if test "${enable_update_limit+set}" = set; then :
enableval=$enable_update_limit; enable_udlimit=yes
else
enable_udlimit=no
fi
if test "${enable_udlimit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
fi
#########
# See whether we should enable RTREE
# Check whether --enable-rtree was given.
@@ -12167,7 +12151,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
# report actual input values of CONFIG_FILES etc. instead of their
# values after options handling.
ac_log="
This file was extended by sqlite $as_me 3.22.0, which was
This file was extended by sqlite $as_me 3.20.0, which was
generated by GNU Autoconf 2.69. Invocation command line was
CONFIG_FILES = $CONFIG_FILES
@@ -12233,7 +12217,7 @@ _ACEOF
cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
ac_cs_version="\\
sqlite config.status 3.22.0
sqlite config.status 3.20.0
configured by $0, generated by GNU Autoconf 2.69,
with options \\"\$ac_cs_config\\"
+1 -11
View File
@@ -120,7 +120,7 @@ USE_AMALGAMATION=1
# if not, then we fall back to plain tclsh.
# TODO: try other versions before falling back?
#
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.7 tclsh8.6 tclsh8.5 tclsh], none)
AC_CHECK_PROGS(TCLSH_CMD, [tclsh8.6 tclsh8.5 tclsh], none)
if test "$TCLSH_CMD" = "none"; then
# If we can't find a local tclsh, then building the amalgamation will fail.
# We act as though --disable-amalgamation has been used.
@@ -644,16 +644,6 @@ if test "${enable_json1}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_JSON1"
fi
#########
# See whether we should enable the LIMIT clause on UPDATE and DELETE
# statements.
AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit],
[Enable the UPDATE/DELETE LIMIT clause]),
[enable_udlimit=yes],[enable_udlimit=no])
if test "${enable_udlimit}" = "yes" ; then
OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT"
fi
#########
# See whether we should enable RTREE
AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree],
+176 -203
View File
@@ -2,12 +2,12 @@
<head>
<title>The Lemon Parser Generator</title>
</head>
<body bgcolor='white'>
<h1 align='center'>The Lemon Parser Generator</h1>
<body bgcolor=white>
<h1 align=center>The Lemon Parser Generator</h1>
<p>Lemon is an LALR(1) parser generator for C.
It does the same job as "bison" and "yacc".
But Lemon is not a bison or yacc clone. Lemon
But lemon is not a bison or yacc clone. Lemon
uses a different grammar syntax which is designed to
reduce the number of coding errors. Lemon also uses a
parsing engine that is faster than yacc and
@@ -16,7 +16,7 @@ bison and which is both reentrant and threadsafe.
has also been updated so that it too can generate a
reentrant and threadsafe parser.)
Lemon also implements features that can be used
to eliminate resource leaks, making it suitable for use
to eliminate resource leaks, making is suitable for use
in long-running programs such as graphical user interfaces
or embedded controllers.</p>
@@ -58,8 +58,8 @@ Lemon comes with a default parser template which works fine for most
applications. But the user is free to substitute a different parser
template if desired.</p>
<p>Depending on command-line options, Lemon will generate up to
three output files.
<p>Depending on command-line options, Lemon will generate between
one and three files of outputs.
<ul>
<li>C code to implement the parser.
<li>A header file defining an integer ID for each terminal symbol.
@@ -90,20 +90,17 @@ the states used by the parser automaton.</p>
You can obtain a list of the available command-line options together
with a brief explanation of what each does by typing
<pre>
lemon "-?"
lemon -?
</pre>
As of this writing, the following command-line options are supported:
<ul>
<li><b>-b</b>
Show only the basis for each parser state in the report file.
<li><b>-c</b>
Do not compress the generated action tables. The parser will be a
little larger and slower, but it will detect syntax errors sooner.
Do not compress the generated action tables.
<li><b>-D<i>name</i></b>
Define C preprocessor macro <i>name</i>. This macro is usable by
"<tt><a href='#pifdef'>%ifdef</a></tt>" and
"<tt><a href='#pifdef'>%ifndef</a></tt>" lines
in the grammar file.
Define C preprocessor macro <i>name</i>. This macro is useable by
"%ifdef" lines in the grammar file.
<li><b>-g</b>
Do not generate a parser. Instead write the input grammar to standard
output with all comments, actions, and other extraneous text removed.
@@ -111,9 +108,9 @@ output with all comments, actions, and other extraneous text removed.
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.
program.
<li><b>-p</b>
Display all conflicts that are resolved by
Display all conflicts that are resolved by
<a href='#precrules'>precedence rules</a>.
<li><b>-q</b>
Suppress generation of the report file.
@@ -168,7 +165,7 @@ once for each token:
</pre>
The first argument to the Parse() routine is the pointer returned by
ParseAlloc().
The second argument is a small positive integer that tells the parser the
The second argument is a small positive integer that tells the parse the
type of the next token in the data stream.
There is one token type for each terminal symbol in the grammar.
The gram.h file generated by Lemon contains #define statements that
@@ -176,7 +173,7 @@ map symbolic terminal symbol names into appropriate integer values.
A value of 0 for the second argument is a special flag to the
parser to indicate that the end of input has been reached.
The third argument is the value of the given token. By default,
the type of the third argument is "void*", but the grammar will
the type of the third argument is integer, but the grammar will
usually redefine this type to be some kind of structure.
Typically the second argument will be a broad category of tokens
such as "identifier" or "number" and the third argument will
@@ -184,7 +181,7 @@ be the name of the identifier or the value of the number.</p>
<p>The Parse() function may have either three or four arguments,
depending on the grammar. If the grammar specification file requests
it (via the <tt><a href='#extraarg'>%extra_argument</a></tt> directive),
it (via the <a href='#extraarg'><tt>extra_argument</tt> directive</a>),
the Parse() function will have a fourth parameter that can be
of any type chosen by the programmer. The parser doesn't do anything
with this argument except to pass it through to action routines.
@@ -194,20 +191,20 @@ to the action routines without having to use global variables.</p>
<p>A typical use of a Lemon parser might look something like the
following:
<pre>
1 ParseTree *ParseFile(const char *zFilename){
2 Tokenizer *pTokenizer;
3 void *pParser;
4 Token sToken;
5 int hTokenId;
6 ParserState sState;
7
8 pTokenizer = TokenizerCreate(zFilename);
9 pParser = ParseAlloc( malloc );
10 InitParserState(&amp;sState);
11 while( GetNextToken(pTokenizer, &amp;hTokenId, &amp;sToken) ){
12 Parse(pParser, hTokenId, sToken, &amp;sState);
01 ParseTree *ParseFile(const char *zFilename){
02 Tokenizer *pTokenizer;
03 void *pParser;
04 Token sToken;
05 int hTokenId;
06 ParserState sState;
07
08 pTokenizer = TokenizerCreate(zFilename);
09 pParser = ParseAlloc( malloc );
10 InitParserState(&sState);
11 while( GetNextToken(pTokenizer, &hTokenId, &sToken) ){
12 Parse(pParser, hTokenId, sToken, &sState);
13 }
14 Parse(pParser, 0, sToken, &amp;sState);
14 Parse(pParser, 0, sToken, &sState);
15 ParseFree(pParser, free );
16 TokenizerFree(pTokenizer);
17 return sState.treeRoot;
@@ -220,10 +217,10 @@ simple.)
We assume the existence of some kind of tokenizer which is created
using TokenizerCreate() on line 8 and deleted by TokenizerFree()
on line 16. The GetNextToken() function on line 11 retrieves the
next token from the input file and puts its type in the
next token from the input file and puts its type in the
integer variable hTokenId. The sToken variable is assumed to be
some kind of structure that contains details about each token,
such as its complete text, what line it occurs on, etc.</p>
such as its complete text, what line it occurs on, etc. </p>
<p>This example also assumes the existence of structure of type
ParserState that holds state information about a particular parse.
@@ -240,7 +237,7 @@ tree.</p>
<pre>
ParseFile(){
pParser = ParseAlloc( malloc );
while( GetNextToken(pTokenizer,&amp;hTokenId, &amp;sToken) ){
while( GetNextToken(pTokenizer,&hTokenId, &sToken) ){
Parse(pParser, hTokenId, sToken);
}
Parse(pParser, 0, sToken);
@@ -300,25 +297,25 @@ specifies additional information Lemon requires to do its job.
Most of the work in using Lemon is in writing an appropriate
grammar file.</p>
<p>The grammar file for Lemon is, for the most part, free format.
<p>The grammar file for lemon is, for the most part, free format.
It does not have sections or divisions like yacc or bison. Any
declaration can occur at any point in the file.
Lemon ignores whitespace (except where it is needed to separate
tokens), and it honors the same commenting conventions as C and C++.</p>
tokens) and it honors the same commenting conventions as C and C++.</p>
<h3>Terminals and Nonterminals</h3>
<p>A terminal symbol (token) is any string of alphanumeric
and/or underscore characters
that begins with an uppercase letter.
that begins with an upper case letter.
A terminal can contain lowercase letters after the first character,
but the usual convention is to make terminals all uppercase.
but the usual convention is to make terminals all upper case.
A nonterminal, on the other hand, is any string of alphanumeric
and underscore characters than begins with a lowercase letter.
Again, the usual convention is to make nonterminals use all lowercase
letters.</p>
and underscore characters than begins with a lower case letter.
Again, the usual convention is to make nonterminals use all lower
case letters.</p>
<p>In Lemon, terminal and nonterminal symbols do not need to
<p>In Lemon, terminal and nonterminal symbols do not need to
be declared or identified in a separate section of the grammar file.
Lemon is able to generate a list of all terminals and nonterminals
by examining the grammar rules, and it can always distinguish a
@@ -342,8 +339,7 @@ The list of terminals and nonterminals on the right-hand side of the
rule can be empty.
Rules can occur in any order, except that the left-hand side of the
first rule is assumed to be the start symbol for the grammar (unless
specified otherwise using the <tt><a href='#start_symbol'>%start_symbol</a></tt>
directive described below.)
specified otherwise using the <tt>%start</tt> directive described below.)
A typical sequence of grammar rules might look something like this:
<pre>
expr ::= expr PLUS expr.
@@ -386,7 +382,7 @@ names to each symbol in a grammar rule and then using those symbolic
names in the action.
In yacc or bison, one would write this:
<pre>
expr -&gt; expr PLUS expr { $$ = $1 + $3; };
expr -> expr PLUS expr { $$ = $1 + $3; };
</pre>
But in Lemon, the same rule becomes the following:
<pre>
@@ -426,14 +422,14 @@ of the shift, and a reduce-reduce conflict is resolved by reducing
whichever rule comes first in the grammar file.</p>
<p>Just like in
yacc and bison, Lemon allows a measure of control
over the resolution of parsing conflicts using precedence rules.
yacc and bison, Lemon allows a measure of control
over the resolution of paring conflicts using precedence rules.
A precedence value can be assigned to any terminal symbol
using the
<tt><a href='#pleft'>%left</a></tt>,
<tt><a href='#pright'>%right</a></tt> or
<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives. Terminal symbols
mentioned in earlier directives have a lower precedence than
using the
<a href='#pleft'>%left</a>,
<a href='#pright'>%right</a> or
<a href='#pnonassoc'>%nonassoc</a> directives. Terminal symbols
mentioned in earlier directives have a lower precedence that
terminal symbols mentioned in later directives. For example:</p>
<p><pre>
@@ -509,29 +505,29 @@ as follows:
<li> If the precedence of the token to be shifted is greater than
the precedence of the rule to reduce, then resolve in favor
of the shift. No parsing conflict is reported.
<li> If the precedence of the token to be shifted is less than the
<li> If the precedence of the token it be shifted is less than the
precedence of the rule to reduce, then resolve in favor of the
reduce action. No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
right-associative, then resolve in favor of the shift.
No parsing conflict is reported.
<li> If the precedences are the same and the shift token is
<li> If the precedences are the same the shift token is
left-associative, then resolve in favor of the reduce.
No parsing conflict is reported.
<li> Otherwise, resolve the conflict by doing the shift, and
report a parsing conflict.
<li> Otherwise, resolve the conflict by doing the shift and
report the parsing conflict.
</ul>
Reduce-reduce conflicts are resolved this way:
<ul>
<li> If either reduce rule
<li> If either reduce rule
lacks precedence information, then resolve in favor of the
rule that appears first in the grammar, and report a parsing
rule that appears first in the grammar and report a parsing
conflict.
<li> If both rules have precedence and the precedence is different,
<li> If both rules have precedence and the precedence is different
then resolve the dispute in favor of the rule with the highest
precedence, and do not report a conflict.
precedence and do not report a conflict.
<li> Otherwise, resolve the conflict by reducing by the rule that
appears first in the grammar, and report a parsing conflict.
appears first in the grammar and report a parsing conflict.
</ul>
<h3>Special Directives</h3>
@@ -540,40 +536,40 @@ Reduce-reduce conflicts are resolved this way:
directives. We've described all the grammar rules, so now we'll
talk about the special directives.</p>
<p>Directives in Lemon can occur in any order. You can put them before
the grammar rules, or after the grammar rules, or in the midst of the
<p>Directives in lemon can occur in any order. You can put them before
the grammar rules, or after the grammar rules, or in the mist of the
grammar rules. It doesn't matter. The relative order of
directives used to assign precedence to terminals is important, but
other than that, the order of directives in Lemon is arbitrary.</p>
<p>Lemon supports the following special directives:
<ul>
<li><tt><a href='#pcode'>%code</a></tt>
<li><tt><a href='#default_destructor'>%default_destructor</a></tt>
<li><tt><a href='#default_type'>%default_type</a></tt>
<li><tt><a href='#destructor'>%destructor</a></tt>
<li><tt><a href='#pifdef'>%endif</a></tt>
<li><tt><a href='#extraarg'>%extra_argument</a></tt>
<li><tt><a href='#pfallback'>%fallback</a></tt>
<li><tt><a href='#pifdef'>%ifdef</a></tt>
<li><tt><a href='#pifdef'>%ifndef</a></tt>
<li><tt><a href='#pinclude'>%include</a></tt>
<li><tt><a href='#pleft'>%left</a></tt>
<li><tt><a href='#pname'>%name</a></tt>
<li><tt><a href='#pnonassoc'>%nonassoc</a></tt>
<li><tt><a href='#parse_accept'>%parse_accept</a></tt>
<li><tt><a href='#parse_failure'>%parse_failure</a></tt>
<li><tt><a href='#pright'>%right</a></tt>
<li><tt><a href='#stack_overflow'>%stack_overflow</a></tt>
<li><tt><a href='#stack_size'>%stack_size</a></tt>
<li><tt><a href='#start_symbol'>%start_symbol</a></tt>
<li><tt><a href='#syntax_error'>%syntax_error</a></tt>
<li><tt><a href='#token_class'>%token_class</a></tt>
<li><tt><a href='#token_destructor'>%token_destructor</a></tt>
<li><tt><a href='#token_prefix'>%token_prefix</a></tt>
<li><tt><a href='#token_type'>%token_type</a></tt>
<li><tt><a href='#ptype'>%type</a></tt>
<li><tt><a href='#pwildcard'>%wildcard</a></tt>
<li><tt>%code</tt>
<li><tt>%default_destructor</tt>
<li><tt>%default_type</tt>
<li><tt>%destructor</tt>
<li><tt>%endif</tt>
<li><tt>%extra_argument</tt>
<li><tt>%fallback</tt>
<li><tt>%ifdef</tt>
<li><tt>%ifndef</tt>
<li><tt>%include</tt>
<li><tt>%left</tt>
<li><tt>%name</tt>
<li><tt>%nonassoc</tt>
<li><tt>%parse_accept</tt>
<li><tt>%parse_failure </tt>
<li><tt>%right</tt>
<li><tt>%stack_overflow</tt>
<li><tt>%stack_size</tt>
<li><tt>%start_symbol</tt>
<li><tt>%syntax_error</tt>
<li><tt>%token_class</tt>
<li><tt>%token_destructor</tt>
<li><tt>%token_prefix</tt>
<li><tt>%token_type</tt>
<li><tt>%type</tt>
<li><tt>%wildcard</tt>
</ul>
Each of these directives will be described separately in the
following sections:</p>
@@ -581,42 +577,43 @@ following sections:</p>
<a name='pcode'></a>
<h4>The <tt>%code</tt> directive</h4>
<p>The <tt>%code</tt> directive is used to specify additional C code that
<p>The %code directive is used to specify addition C code that
is added to the end of the main output file. This is similar to
the <tt><a href='#pinclude'>%include</a></tt> directive except that
<tt>%include</tt> is inserted at the beginning of the main output file.</p>
the <a href='#pinclude'>%include</a> directive except that %include
is inserted at the beginning of the main output file.</p>
<p><tt>%code</tt> is typically used to include some action routines or perhaps
a tokenizer or even the "main()" function
<p>%code is typically used to include some action routines or perhaps
a tokenizer or even the "main()" function
as part of the output file.</p>
<a name='default_destructor'></a>
<h4>The <tt>%default_destructor</tt> directive</h4>
<p>The <tt>%default_destructor</tt> directive specifies a destructor to
<p>The %default_destructor directive specifies a destructor to
use for non-terminals that do not have their own destructor
specified by a separate <tt>%destructor</tt> directive. See the documentation
on the <tt><a name='#destructor'>%destructor</a></tt> directive below for
specified by a separate %destructor directive. See the documentation
on the <a name='#destructor'>%destructor</a> directive below for
additional information.</p>
<p>In some grammars, many different non-terminal symbols have the
same data type and hence the same destructor. This directive is
a convenient way to specify the same destructor for all those
<p>In some grammers, many different non-terminal symbols have the
same datatype and hence the same destructor. This directive is
a convenience way to specify the same destructor for all those
non-terminals using a single statement.</p>
<a name='default_type'></a>
<h4>The <tt>%default_type</tt> directive</h4>
<p>The <tt>%default_type</tt> directive specifies the data type of non-terminal
symbols that do not have their own data type defined using a separate
<tt><a href='#ptype'>%type</a></tt> directive.</p>
<p>The %default_type directive specifies the datatype of non-terminal
symbols that do no have their own datatype defined using a separate
<a href='#ptype'>%type</a> directive.
</p>
<a name='destructor'></a>
<h4>The <tt>%destructor</tt> directive</h4>
<p>The <tt>%destructor</tt> directive is used to specify a destructor for
<p>The %destructor directive is used to specify a destructor for
a non-terminal symbol.
(See also the <tt><a href='#token_destructor'>%token_destructor</a></tt>
(See also the <a href='#token_destructor'>%token_destructor</a>
directive which is used to specify a destructor for terminal symbols.)</p>
<p>A non-terminal's destructor is called to dispose of the
@@ -638,7 +635,7 @@ or other resources held by that non-terminal.</p>
%destructor nt { free($$); }
nt(A) ::= ID NUM. { A = malloc( 100 ); }
</pre>
This example is a bit contrived, but it serves to illustrate how
This example is a bit contrived but it serves to illustrate how
destructors work. The example shows a non-terminal named
"nt" that holds values of type "void*". When the rule for
an "nt" reduces, it sets the value of the non-terminal to
@@ -654,17 +651,17 @@ stack, unless the non-terminal is used in a C-code action. If
the non-terminal is used by C-code, then it is assumed that the
C-code will take care of destroying it.
More commonly, the value is used to build some
larger structure, and we don't want to destroy it, which is why
larger structure and we don't want to destroy it, which is why
the destructor is not called in this circumstance.</p>
<p>Destructors help avoid memory leaks by automatically freeing
allocated objects when they go out of scope.
To do the same using yacc or bison is much more difficult.</p>
<a name='extraarg'></a>
<a name="extraarg"></a>
<h4>The <tt>%extra_argument</tt> directive</h4>
The <tt>%extra_argument</tt> directive instructs Lemon to add a 4th parameter
The %extra_argument directive instructs Lemon to add a 4th parameter
to the parameter list of the Parse() function it generates. Lemon
doesn't do anything itself with this extra argument, but it does
make the argument available to C-code action routines, destructors,
@@ -682,64 +679,61 @@ in the most recent call to Parse().</p>
<a name='pfallback'></a>
<h4>The <tt>%fallback</tt> directive</h4>
<p>The <tt>%fallback</tt> directive specifies an alternative meaning for one
<p>The %fallback directive specifies an alternative meaning for one
or more tokens. The alternative meaning is tried if the original token
would have generated a syntax error.</p>
would have generated a syntax error.
<p>The <tt>%fallback</tt> directive was added to support robust parsing of SQL
syntax in <a href='https://www.sqlite.org/'>SQLite</a>.
<p>The %fallback directive was added to support robust parsing of SQL
syntax in <a href="https://www.sqlite.org/">SQLite</a>.
The SQL language contains a large assortment of keywords, each of which
appears as a different token to the language parser. SQL contains so
many keywords that it can be difficult for programmers to keep up with
many keywords, that it can be difficult for programmers to keep up with
them all. Programmers will, therefore, sometimes mistakenly use an
obscure language keyword for an identifier. The <tt>%fallback</tt> directive
obscure language keyword for an identifier. The %fallback directive
provides a mechanism to tell the parser: "If you are unable to parse
this keyword, try treating it as an identifier instead."</p>
this keyword, try treating it as an identifier instead."
<p>The syntax of <tt>%fallback</tt> is as follows:
<p>The syntax of %fallback is as follows:
<blockquote>
<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
</blockquote></p>
<tt>%fallback</tt> <i>ID</i> <i>TOKEN...</i> <b>.</b>
</blockquote>
<p>In words, the <tt>%fallback</tt> directive is followed by a list of token
names terminated by a period.
The first token name is the fallback token &mdash; the
<p>In words, the %fallback directive is followed by a list of token names
terminated by a period. The first token name is the fallback token - the
token to which all the other tokens fall back to. The second and subsequent
arguments are tokens which fall back to the token identified by the first
argument.</p>
argument.
<a name='pifdef'></a>
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives</h4>
<h4>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives.</h4>
<p>The <tt>%ifdef</tt>, <tt>%ifndef</tt>, and <tt>%endif</tt> directives
are similar to #ifdef, #ifndef, and #endif in the C-preprocessor,
just not as general.
<p>The %ifdef, %ifndef, and %endif directives are similar to
#ifdef, #ifndef, and #endif in the C-preprocessor, just not as general.
Each of these directives must begin at the left margin. No whitespace
is allowed between the "%" and the directive name.</p>
is allowed between the "%" and the directive name.
<p>Grammar text in between "<tt>%ifdef MACRO</tt>" and the next nested
"<tt>%endif</tt>" is
<p>Grammar text in between "%ifdef MACRO" and the next nested "%endif" is
ignored unless the "-DMACRO" command-line option is used. Grammar text
betwen "<tt>%ifndef MACRO</tt>" and the next nested "<tt>%endif</tt>" is
included except when the "-DMACRO" command-line option is used.</p>
betwen "%ifndef MACRO" and the next nested "%endif" is included except when
the "-DMACRO" command-line option is used.
<p>Note that the argument to <tt>%ifdef</tt> and <tt>%ifndef</tt> must
be a single preprocessor symbol name, not a general expression.
There is no "<tt>%else</tt>" directive.</p>
<p>Note that the argument to %ifdef and %ifndef must be a single
preprocessor symbol name, not a general expression. There is no "%else"
directive.
<a name='pinclude'></a>
<h4>The <tt>%include</tt> directive</h4>
<p>The <tt>%include</tt> directive specifies C code that is included at the
top of the generated parser. You can include any text you want &mdash;
<p>The %include directive specifies C code that is included at the
top of the generated parser. You can include any text you want --
the Lemon parser generator copies it blindly. If you have multiple
<tt>%include</tt> directives in your grammar file, their values are concatenated
so that all <tt>%include</tt> code ultimately appears near the top of the
generated parser, in the same order as it appeared in the grammar.</p>
%include directives in your grammar file, their values are concatenated
so that all %include code ultimately appears near the top of the
generated parser, in the same order as it appeared in the grammer.</p>
<p>The <tt>%include</tt> directive is very handy for getting some extra #include
<p>The %include directive is very handy for getting some extra #include
preprocessor statements at the beginning of the generated parser.
For example:</p>
@@ -748,19 +742,17 @@ For example:</p>
</pre></p>
<p>This might be needed, for example, if some of the C actions in the
grammar call functions that are prototyped in unistd.h.</p>
grammar call functions that are prototyed in unistd.h.</p>
<a name='pleft'></a>
<h4>The <tt>%left</tt> directive</h4>
The <tt>%left</tt> directive is used (along with the
<tt><a href='#pright'>%right</a></tt> and
<tt><a href='#pnonassoc'>%nonassoc</a></tt> directives) to declare
precedences of terminal symbols.
Every terminal symbol whose name appears after
a <tt>%left</tt> directive but before the next period (".") is
The %left directive is used (along with the <a href='#pright'>%right</a> and
<a href='#pnonassoc'>%nonassoc</a> directives) to declare precedences of
terminal symbols. Every terminal symbol whose name appears after
a %left directive but before the next period (".") is
given the same left-associative precedence value. Subsequent
<tt>%left</tt> directives have higher precedence. For example:</p>
%left directives have higher precedence. For example:</p>
<p><pre>
%left AND.
@@ -771,21 +763,20 @@ given the same left-associative precedence value. Subsequent
%right EXP NOT.
</pre></p>
<p>Note the period that terminates each <tt>%left</tt>,
<tt>%right</tt> or <tt>%nonassoc</tt>
<p>Note the period that terminates each %left, %right or %nonassoc
directive.</p>
<p>LALR(1) grammars can get into a situation where they require
a large amount of stack space if you make heavy use or right-associative
operators. For this reason, it is recommended that you use <tt>%left</tt>
rather than <tt>%right</tt> whenever possible.</p>
operators. For this reason, it is recommended that you use %left
rather than %right whenever possible.</p>
<a name='pname'></a>
<h4>The <tt>%name</tt> directive</h4>
<p>By default, the functions generated by Lemon all begin with the
five-character string "Parse". You can change this string to something
different using the <tt>%name</tt> directive. For instance:</p>
different using the %name directive. For instance:</p>
<p><pre>
%name Abcde
@@ -799,22 +790,22 @@ functions named
<li> AbcdeTrace(), and
<li> Abcde().
</ul>
The <tt>%name</tt> directive allows you to generate two or more different
parsers and link them all into the same executable.</p>
The %name directive allows you to generator two or more different
parsers and link them all into the same executable.
</p>
<a name='pnonassoc'></a>
<h4>The <tt>%nonassoc</tt> directive</h4>
<p>This directive is used to assign non-associative precedence to
one or more terminal symbols. See the section on
one or more terminal symbols. See the section on
<a href='#precrules'>precedence rules</a>
or on the <tt><a href='#pleft'>%left</a></tt> directive
for additional information.</p>
or on the <a href='#pleft'>%left</a> directive for additional information.</p>
<a name='parse_accept'></a>
<h4>The <tt>%parse_accept</tt> directive</h4>
<p>The <tt>%parse_accept</tt> directive specifies a block of C code that is
<p>The %parse_accept directive specifies a block of C code that is
executed whenever the parser accepts its input string. To "accept"
an input string means that the parser was able to process all tokens
without error.</p>
@@ -830,7 +821,7 @@ without error.</p>
<a name='parse_failure'></a>
<h4>The <tt>%parse_failure</tt> directive</h4>
<p>The <tt>%parse_failure</tt> directive specifies a block of C code that
<p>The %parse_failure directive specifies a block of C code that
is executed whenever the parser fails complete. This code is not
executed until the parser has tried and failed to resolve an input
error using is usual error recovery strategy. The routine is
@@ -846,14 +837,14 @@ only invoked when parsing is unable to continue.</p>
<h4>The <tt>%right</tt> directive</h4>
<p>This directive is used to assign right-associative precedence to
one or more terminal symbols. See the section on
one or more terminal symbols. See the section on
<a href='#precrules'>precedence rules</a>
or on the <a href='#pleft'>%left</a> directive for additional information.</p>
<a name='stack_overflow'></a>
<h4>The <tt>%stack_overflow</tt> directive</h4>
<p>The <tt>%stack_overflow</tt> directive specifies a block of C code that
<p>The %stack_overflow directive specifies a block of C code that
is executed if the parser's internal stack ever overflows. Typically
this just prints an error message. After a stack overflow, the parser
will be unable to continue and must be reset.</p>
@@ -866,7 +857,7 @@ will be unable to continue and must be reset.</p>
<p>You can help prevent parser stack overflows by avoiding the use
of right recursion and right-precedence operators in your grammar.
Use left recursion and and left-precedence operators instead to
Use left recursion and and left-precedence operators instead, to
encourage rules to reduce sooner and keep the stack size down.
For example, do rules like this:
<pre>
@@ -877,7 +868,7 @@ Not like this:
<pre>
list ::= element list. // right-recursion. Bad!
list ::= .
</pre></p>
</pre>
<a name='stack_size'></a>
<h4>The <tt>%stack_size</tt> directive</h4>
@@ -885,7 +876,7 @@ Not like this:
<p>If stack overflow is a problem and you can't resolve the trouble
by using left-recursion, then you might want to increase the size
of the parser's stack using this directive. Put an positive integer
after the <tt>%stack_size</tt> directive and Lemon will generate a parse
after the %stack_size directive and Lemon will generate a parse
with a stack of the requested size. The default value is 100.</p>
<p><pre>
@@ -895,40 +886,25 @@ with a stack of the requested size. The default value is 100.</p>
<a name='start_symbol'></a>
<h4>The <tt>%start_symbol</tt> directive</h4>
<p>By default, the start symbol for the grammar that Lemon generates
<p>By default, the start-symbol for the grammar that Lemon generates
is the first non-terminal that appears in the grammar file. But you
can choose a different start symbol using the
<tt>%start_symbol</tt> directive.</p>
can choose a different start-symbol using the %start_symbol directive.</p>
<p><pre>
%start_symbol prog
</pre></p>
<a name='syntax_error'></a>
<h4>The <tt>%syntax_error</tt> directive</h4>
<p>See <a href='#error_processing'>Error Processing</a>.</p>
<a name='token_class'></a>
<h4>The <tt>%token_class</tt> directive</h4>
<p>Undocumented. Appears to be related to the MULTITERMINAL concept.
<a href='http://sqlite.org/src/fdiff?v1=796930d5fc2036c7&v2=624b24c5dc048e09&sbs=0'>Implementation</a>.</p>
<a name='token_destructor'></a>
<h4>The <tt>%token_destructor</tt> directive</h4>
<p>The <tt>%destructor</tt> directive assigns a destructor to a non-terminal
symbol. (See the description of the
<tt><a href='%destructor'>%destructor</a></tt> directive above.)
The <tt>%token_destructor</tt> directive does the same thing
for all terminal symbols.</p>
<p>The %destructor directive assigns a destructor to a non-terminal
symbol. (See the description of the %destructor directive above.)
This directive does the same thing for all terminal symbols.</p>
<p>Unlike non-terminal symbols which may each have a different data type
for their values, terminals all use the same data type (defined by
the <tt><a href='#token_type'>%token_type</a></tt> directive)
and so they use a common destructor.
Other than that, the token destructor works just like the non-terminal
the %token_type directive) and so they use a common destructor. Other
than that, the token destructor works just like the non-terminal
destructors.</p>
<a name='token_prefix'></a>
@@ -937,9 +913,8 @@ destructors.</p>
<p>Lemon generates #defines that assign small integer constants
to each terminal symbol in the grammar. If desired, Lemon will
add a prefix specified by this directive
to each of the #defines it generates.</p>
<p>So if the default output of Lemon looked like this:
to each of the #defines it generates.
So if the default output of Lemon looked like this:
<pre>
#define AND 1
#define MINUS 2
@@ -956,7 +931,7 @@ to cause Lemon to produce these symbols instead:
#define TOKEN_MINUS 2
#define TOKEN_OR 3
#define TOKEN_PLUS 4
</pre></p>
</pre>
<a name='token_type'></a><a name='ptype'></a>
<h4>The <tt>%token_type</tt> and <tt>%type</tt> directives</h4>
@@ -977,7 +952,7 @@ token structure. Like this:</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
the data type of a non-terminal is a pointer to the root of a parse-tree
structure that contains all information about that non-terminal.
For example:</p>
@@ -998,15 +973,14 @@ and able to pay that price, fine. You just need to know.</p>
<a name='pwildcard'></a>
<h4>The <tt>%wildcard</tt> directive</h4>
<p>The <tt>%wildcard</tt> directive is followed by a single token name and a
period. This directive specifies that the identified token should
match any input token.</p>
<p>The %wildcard directive is followed by a single token name and a
period. This directive specifies that the identified token should
match any input token.
<p>When the generated parser has the choice of matching an input against
the wildcard token and some other token, the other token is always used.
The wildcard token is only matched if there are no alternatives.</p>
The wildcard token is only matched if there are no other alternatives.
<a name='error_processing'></a>
<h3>Error Processing</h3>
<p>After extensive experimentation over several years, it has been
@@ -1014,20 +988,19 @@ discovered that the error recovery strategy used by yacc is about
as good as it gets. And so that is what Lemon uses.</p>
<p>When a Lemon-generated parser encounters a syntax error, it
first invokes the code specified by the <tt>%syntax_error</tt> directive, if
first invokes the code specified by the %syntax_error directive, if
any. It then enters its error recovery strategy. The error recovery
strategy is to begin popping the parsers stack until it enters a
state where it is permitted to shift a special non-terminal symbol
named "error". It then shifts this non-terminal and continues
parsing. The <tt>%syntax_error</tt> routine will not be called again
parsing. But the %syntax_error routine will not be called again
until at least three new tokens have been successfully shifted.</p>
<p>If the parser pops its stack until the stack is empty, and it still
is unable to shift the error symbol, then the
<tt><a href='#parse_failure'>%parse_failure</a></tt> routine
is unable to shift the error symbol, then the %parse_failed routine
is invoked and the parser resets itself to its start state, ready
to begin parsing a new file. This is what will happen at the very
first syntax error, of course, if there are no instances of the
first syntax error, of course, if there are no instances of the
"error" non-terminal in your grammar.</p>
</body>
+18 -28
View File
@@ -1707,19 +1707,6 @@ static void fts3CursorFinalizeStmt(Fts3Cursor *pCsr){
sqlite3_finalize(pCsr->pStmt);
}
/*
** Free all resources currently held by the cursor passed as the only
** argument.
*/
static void fts3ClearCursor(Fts3Cursor *pCsr){
fts3CursorFinalizeStmt(pCsr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&(&pCsr->base)[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
}
/*
** Close the cursor. For additional information see the documentation
** on the xClose method of the virtual table interface.
@@ -1727,7 +1714,11 @@ static void fts3ClearCursor(Fts3Cursor *pCsr){
static int fts3CloseMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor *)pCursor;
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
fts3ClearCursor(pCsr);
fts3CursorFinalizeStmt(pCsr);
sqlite3Fts3ExprFree(pCsr->pExpr);
sqlite3Fts3FreeDeferredTokens(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
sqlite3_free(pCsr);
return SQLITE_OK;
@@ -1753,7 +1744,7 @@ static int fts3CursorSeekStmt(Fts3Cursor *pCsr){
}else{
zSql = sqlite3_mprintf("SELECT %s WHERE rowid = ?", p->zReadExprlist);
if( !zSql ) return SQLITE_NOMEM;
rc = sqlite3_prepare_v3(p->db, zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}
if( rc==SQLITE_OK ) pCsr->bSeekStmt = 1;
@@ -3228,7 +3219,11 @@ static int fts3FilterMethod(
assert( iIdx==nVal );
/* In case the cursor has been used before, clear it now. */
fts3ClearCursor(pCsr);
fts3CursorFinalizeStmt(pCsr);
sqlite3_free(pCsr->aDoclist);
sqlite3Fts3MIBufferFree(pCsr->pMIBuffer);
sqlite3Fts3ExprFree(pCsr->pExpr);
memset(&pCursor[1], 0, sizeof(Fts3Cursor)-sizeof(sqlite3_vtab_cursor));
/* Set the lower and upper bounds on docids to return */
pCsr->iMinDocid = fts3DocidRange(pDocidGe, SMALLEST_INT64);
@@ -3286,7 +3281,7 @@ static int fts3FilterMethod(
);
}
if( zSql ){
rc = sqlite3_prepare_v3(p->db,zSql,-1,SQLITE_PREPARE_PERSISTENT,&pCsr->pStmt,0);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
}else{
rc = SQLITE_NOMEM;
@@ -3307,12 +3302,7 @@ static int fts3FilterMethod(
** routine to find out if it has reached the end of a result set.
*/
static int fts3EofMethod(sqlite3_vtab_cursor *pCursor){
Fts3Cursor *pCsr = (Fts3Cursor*)pCursor;
if( pCsr->isEof ){
fts3ClearCursor(pCsr);
pCsr->isEof = 1;
}
return pCsr->isEof;
return ((Fts3Cursor *)pCursor)->isEof;
}
/*
@@ -3353,7 +3343,8 @@ static int fts3ColumnMethod(
switch( iCol-p->nColumn ){
case 0:
/* The special 'table-name' column */
sqlite3_result_pointer(pCtx, pCsr, "fts3cursor", 0);
sqlite3_result_blob(pCtx, &pCsr, sizeof(Fts3Cursor*), SQLITE_TRANSIENT);
sqlite3_result_subtype(pCtx, SQLITE_BLOB);
break;
case 1:
@@ -3571,10 +3562,9 @@ static int fts3FunctionArg(
sqlite3_value *pVal, /* argv[0] passed to function */
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
){
int rc;
*ppCsr = (Fts3Cursor*)sqlite3_value_pointer(pVal, "fts3cursor");
if( (*ppCsr)!=0 ){
rc = SQLITE_OK;
int rc = SQLITE_OK;
if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){
*ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal);
}else{
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
sqlite3_result_error(pContext, zErr, -1);
+1 -2
View File
@@ -407,8 +407,7 @@ static int fts3SqlStmt(
if( !zSql ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(p->db, zSql, -1, SQLITE_PREPARE_PERSISTENT,
&pStmt, NULL);
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, NULL);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pStmt==0 );
p->aStmt[eStmt] = pStmt;
+2 -4
View File
@@ -728,8 +728,7 @@ static int fts5IndexPrepareStmt(
){
if( p->rc==SQLITE_OK ){
if( zSql ){
p->rc = sqlite3_prepare_v3(p->pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, ppStmt, 0);
p->rc = sqlite3_prepare_v2(p->pConfig->db, zSql, -1, ppStmt, 0);
}else{
p->rc = SQLITE_NOMEM;
}
@@ -778,8 +777,7 @@ static void fts5DataDelete(Fts5Index *p, i64 iFirst, i64 iLast){
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &p->pDeleter, 0);
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->pDeleter, 0);
sqlite3_free(zSql);
}
if( rc!=SQLITE_OK ){
+10 -11
View File
@@ -883,8 +883,7 @@ static int fts5PrepareStatement(
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &pRet, 0);
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pRet, 0);
if( rc!=SQLITE_OK ){
*pConfig->pzErrmsg = sqlite3_mprintf("%s", sqlite3_errmsg(pConfig->db));
}
@@ -1020,8 +1019,7 @@ static int fts5FindRankFunction(Fts5Cursor *pCsr){
char *zSql = sqlite3Fts5Mprintf(&rc, "SELECT %s", zRankArgs);
if( zSql ){
sqlite3_stmt *pStmt = 0;
rc = sqlite3_prepare_v3(pConfig->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &pStmt, 0);
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &pStmt, 0);
sqlite3_free(zSql);
assert( rc==SQLITE_OK || pCsr->pRankArgStmt==0 );
if( rc==SQLITE_OK ){
@@ -2609,14 +2607,15 @@ static void fts5ModuleDestroy(void *pCtx){
static void fts5Fts5Func(
sqlite3_context *pCtx, /* Function call context */
int nArg, /* Number of args */
sqlite3_value **apArg /* Function arguments */
sqlite3_value **apUnused /* Function arguments */
){
Fts5Global *pGlobal = (Fts5Global*)sqlite3_user_data(pCtx);
fts5_api **ppApi;
UNUSED_PARAM(nArg);
assert( nArg==1 );
ppApi = (fts5_api**)sqlite3_value_pointer(apArg[0], "fts5_api_ptr");
if( ppApi ) *ppApi = &pGlobal->api;
char buf[8];
UNUSED_PARAM2(nArg, apUnused);
assert( nArg==0 );
assert( sizeof(buf)>=sizeof(pGlobal) );
memcpy(buf, (void*)&pGlobal, sizeof(pGlobal));
sqlite3_result_blob(pCtx, buf, sizeof(pGlobal), SQLITE_TRANSIENT);
}
/*
@@ -2681,7 +2680,7 @@ static int fts5Init(sqlite3 *db){
if( rc==SQLITE_OK ) rc = sqlite3Fts5VocabInit(pGlobal, db);
if( rc==SQLITE_OK ){
rc = sqlite3_create_function(
db, "fts5", 1, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
db, "fts5", 0, SQLITE_UTF8, p, fts5Fts5Func, 0, 0
);
}
if( rc==SQLITE_OK ){
+1 -2
View File
@@ -136,8 +136,7 @@ static int fts5StorageGetStmt(
if( zSql==0 ){
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare_v3(pC->db, zSql, -1,
SQLITE_PREPARE_PERSISTENT, &p->aStmt[eStmt], 0);
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
sqlite3_free(zSql);
if( rc!=SQLITE_OK && pzErrMsg ){
*pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
+6 -3
View File
@@ -99,13 +99,16 @@ static int SQLITE_TCLAPI f5tDbAndApi(
sqlite3_stmt *pStmt = 0;
fts5_api *pApi = 0;
rc = sqlite3_prepare_v2(db, "SELECT fts5(?1)", -1, &pStmt, 0);
rc = sqlite3_prepare_v2(db, "SELECT fts5()", -1, &pStmt, 0);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
return TCL_ERROR;
}
sqlite3_bind_pointer(pStmt, 1, (void*)&pApi, "fts5_api_ptr", 0);
sqlite3_step(pStmt);
if( SQLITE_ROW==sqlite3_step(pStmt) ){
const void *pPtr = sqlite3_column_blob(pStmt, 0);
memcpy((void*)&pApi, pPtr, sizeof(pApi));
}
if( sqlite3_finalize(pStmt)!=SQLITE_OK ){
Tcl_AppendResult(interp, "error: ", sqlite3_errmsg(db), 0);
+7 -3
View File
@@ -73,10 +73,13 @@ static int fts5_api_from_db(sqlite3 *db, fts5_api **ppApi){
int rc;
*ppApi = 0;
rc = sqlite3_prepare(db, "SELECT fts5(?1)", -1, &pStmt, 0);
rc = sqlite3_prepare(db, "SELECT fts5()", -1, &pStmt, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_pointer(pStmt, 1, (void*)ppApi, "fts5_api_ptr", 0);
(void)sqlite3_step(pStmt);
if( SQLITE_ROW==sqlite3_step(pStmt)
&& sizeof(fts5_api*)==sqlite3_column_bytes(pStmt, 0)
){
memcpy(ppApi, sqlite3_column_blob(pStmt, 0), sizeof(fts5_api*));
}
rc = sqlite3_finalize(pStmt);
}
@@ -419,3 +422,4 @@ int sqlite3Fts5TestRegisterMatchinfo(sqlite3 *db){
}
#endif /* SQLITE_ENABLE_FTS5 */
+26 -138
View File
@@ -29,11 +29,6 @@
** the number of fts5 rows that contain at least one instance of term
** $term. Field $cnt is set to the total number of instances of term
** $term in the database.
**
** instance:
** CREATE TABLE vocab(term, doc, col, offset, PRIMARY KEY(<all-fields>));
**
** One row for each term instance in the database.
*/
@@ -49,7 +44,7 @@ struct Fts5VocabTable {
char *zFts5Db; /* Db containing fts5 table */
sqlite3 *db; /* Database handle */
Fts5Global *pGlobal; /* FTS5 global object for this database */
int eType; /* FTS5_VOCAB_COL, ROW or INSTANCE */
int eType; /* FTS5_VOCAB_COL or ROW */
};
struct Fts5VocabCursor {
@@ -69,22 +64,16 @@ struct Fts5VocabCursor {
i64 *aCnt;
i64 *aDoc;
/* Output values used by all tables. */
/* Output values used by 'row' and 'col' tables */
i64 rowid; /* This table's current rowid value */
Fts5Buffer term; /* Current value of 'term' column */
/* Output values Used by 'instance' tables only */
i64 iInstPos;
int iInstOff;
};
#define FTS5_VOCAB_COL 0
#define FTS5_VOCAB_ROW 1
#define FTS5_VOCAB_INSTANCE 2
#define FTS5_VOCAB_COL 0
#define FTS5_VOCAB_ROW 1
#define FTS5_VOCAB_COL_SCHEMA "term, col, doc, cnt"
#define FTS5_VOCAB_ROW_SCHEMA "term, doc, cnt"
#define FTS5_VOCAB_INST_SCHEMA "term, doc, col, offset"
/*
** Bits for the mask used as the idxNum value by xBestIndex/xFilter.
@@ -112,9 +101,6 @@ static int fts5VocabTableType(const char *zType, char **pzErr, int *peType){
if( sqlite3_stricmp(zCopy, "row")==0 ){
*peType = FTS5_VOCAB_ROW;
}else
if( sqlite3_stricmp(zCopy, "instance")==0 ){
*peType = FTS5_VOCAB_INSTANCE;
}else
{
*pzErr = sqlite3_mprintf("fts5vocab: unknown table type: %Q", zCopy);
rc = SQLITE_ERROR;
@@ -175,8 +161,7 @@ static int fts5VocabInitVtab(
){
const char *azSchema[] = {
"CREATE TABlE vocab(" FTS5_VOCAB_COL_SCHEMA ")",
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")",
"CREATE TABlE vocab(" FTS5_VOCAB_INST_SCHEMA ")"
"CREATE TABlE vocab(" FTS5_VOCAB_ROW_SCHEMA ")"
};
Fts5VocabTable *pRet = 0;
@@ -250,15 +235,6 @@ static int fts5VocabCreateMethod(
/*
** Implementation of the xBestIndex method.
**
** Only constraints of the form:
**
** term <= ?
** term == ?
** term >= ?
**
** are interpreted. Less-than and less-than-or-equal are treated
** identically, as are greater-than and greater-than-or-equal.
*/
static int fts5VocabBestIndexMethod(
sqlite3_vtab *pUnused,
@@ -402,54 +378,6 @@ static int fts5VocabCloseMethod(sqlite3_vtab_cursor *pCursor){
return SQLITE_OK;
}
static int fts5VocabInstanceNewTerm(Fts5VocabCursor *pCsr){
int rc = SQLITE_OK;
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
const char *zTerm;
int nTerm;
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
if( pCsr->nLeTerm>=0 ){
int nCmp = MIN(nTerm, pCsr->nLeTerm);
int bCmp = memcmp(pCsr->zLeTerm, zTerm, nCmp);
if( bCmp<0 || (bCmp==0 && pCsr->nLeTerm<nTerm) ){
pCsr->bEof = 1;
}
}
sqlite3Fts5BufferSet(&rc, &pCsr->term, nTerm, (const u8*)zTerm);
}
return rc;
}
static int fts5VocabInstanceNext(Fts5VocabCursor *pCsr){
int eDetail = pCsr->pConfig->eDetail;
int rc = SQLITE_OK;
Fts5IndexIter *pIter = pCsr->pIter;
i64 *pp = &pCsr->iInstPos;
int *po = &pCsr->iInstOff;
while( eDetail==FTS5_DETAIL_NONE
|| sqlite3Fts5PoslistNext64(pIter->pData, pIter->nData, po, pp)
){
pCsr->iInstPos = 0;
pCsr->iInstOff = 0;
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
if( rc==SQLITE_OK ){
rc = fts5VocabInstanceNewTerm(pCsr);
if( eDetail==FTS5_DETAIL_NONE ) break;
}
if( rc ){
pCsr->bEof = 1;
break;
}
}
return rc;
}
/*
** Advance the cursor to the next row in the table.
@@ -462,17 +390,13 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
pCsr->rowid++;
if( pTab->eType==FTS5_VOCAB_INSTANCE ){
return fts5VocabInstanceNext(pCsr);
}
if( pTab->eType==FTS5_VOCAB_COL ){
for(pCsr->iCol++; pCsr->iCol<nCol; pCsr->iCol++){
if( pCsr->aDoc[pCsr->iCol] ) break;
}
}
if( pTab->eType!=FTS5_VOCAB_COL || pCsr->iCol>=nCol ){
if( pTab->eType==FTS5_VOCAB_ROW || pCsr->iCol>=nCol ){
if( sqlite3Fts5IterEof(pCsr->pIter) ){
pCsr->bEof = 1;
}else{
@@ -496,26 +420,22 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
assert( pTab->eType==FTS5_VOCAB_COL || pTab->eType==FTS5_VOCAB_ROW );
while( rc==SQLITE_OK ){
int eDetail = pCsr->pConfig->eDetail;
const u8 *pPos; int nPos; /* Position list */
i64 iPos = 0; /* 64-bit position read from poslist */
int iOff = 0; /* Current offset within position list */
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
switch( pTab->eType ){
case FTS5_VOCAB_ROW:
if( eDetail==FTS5_DETAIL_FULL ){
switch( pCsr->pConfig->eDetail ){
case FTS5_DETAIL_FULL:
pPos = pCsr->pIter->pData;
nPos = pCsr->pIter->nData;
if( pTab->eType==FTS5_VOCAB_ROW ){
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
pCsr->aCnt[0]++;
}
}
pCsr->aDoc[0]++;
break;
case FTS5_VOCAB_COL:
if( eDetail==FTS5_DETAIL_FULL ){
pCsr->aDoc[0]++;
}else{
int iCol = -1;
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff, &iPos) ){
int ii = FTS5_POS2COLUMN(iPos);
@@ -529,7 +449,13 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
iCol = ii;
}
}
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
}
break;
case FTS5_DETAIL_COLUMNS:
if( pTab->eType==FTS5_VOCAB_ROW ){
pCsr->aDoc[0]++;
}else{
while( 0==sqlite3Fts5PoslistNext64(pPos, nPos, &iOff,&iPos) ){
assert_nc( iPos>=0 && iPos<nCol );
if( iPos>=nCol ){
@@ -538,21 +464,18 @@ static int fts5VocabNextMethod(sqlite3_vtab_cursor *pCursor){
}
pCsr->aDoc[iPos]++;
}
}else{
assert( eDetail==FTS5_DETAIL_NONE );
pCsr->aDoc[0]++;
}
break;
default:
assert( pTab->eType==FTS5_VOCAB_INSTANCE );
default:
assert( pCsr->pConfig->eDetail==FTS5_DETAIL_NONE );
pCsr->aDoc[0]++;
break;
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IterNextScan(pCsr->pIter);
}
if( pTab->eType==FTS5_VOCAB_INSTANCE ) break;
if( rc==SQLITE_OK ){
zTerm = sqlite3Fts5IterTerm(pCsr->pIter, &nTerm);
@@ -582,9 +505,7 @@ static int fts5VocabFilterMethod(
int nUnused, /* Number of elements in apVal */
sqlite3_value **apVal /* Arguments for the indexing scheme */
){
Fts5VocabTable *pTab = (Fts5VocabTable*)pCursor->pVtab;
Fts5VocabCursor *pCsr = (Fts5VocabCursor*)pCursor;
int eType = pTab->eType;
int rc = SQLITE_OK;
int iVal = 0;
@@ -624,16 +545,11 @@ static int fts5VocabFilterMethod(
}
}
if( rc==SQLITE_OK ){
rc = sqlite3Fts5IndexQuery(pCsr->pIndex, zTerm, nTerm, f, 0, &pCsr->pIter);
}
if( rc==SQLITE_OK && eType==FTS5_VOCAB_INSTANCE ){
rc = fts5VocabInstanceNewTerm(pCsr);
}
if( rc==SQLITE_OK
&& !pCsr->bEof
&& (eType!=FTS5_VOCAB_INSTANCE || pCsr->pConfig->eDetail!=FTS5_DETAIL_NONE)
){
if( rc==SQLITE_OK ){
rc = fts5VocabNextMethod(pCursor);
}
@@ -675,41 +591,13 @@ static int fts5VocabColumnMethod(
}else{
iVal = pCsr->aCnt[pCsr->iCol];
}
}else if( eType==FTS5_VOCAB_ROW ){
}else{
assert( iCol==1 || iCol==2 );
if( iCol==1 ){
iVal = pCsr->aDoc[0];
}else{
iVal = pCsr->aCnt[0];
}
}else{
assert( eType==FTS5_VOCAB_INSTANCE );
switch( iCol ){
case 1:
sqlite3_result_int64(pCtx, pCsr->pIter->iRowid);
break;
case 2: {
int ii = -1;
if( eDetail==FTS5_DETAIL_FULL ){
ii = FTS5_POS2COLUMN(pCsr->iInstPos);
}else if( eDetail==FTS5_DETAIL_COLUMNS ){
ii = (int)pCsr->iInstPos;
}
if( ii>=0 && ii<pCsr->pConfig->nCol ){
const char *z = pCsr->pConfig->azCol[ii];
sqlite3_result_text(pCtx, z, -1, SQLITE_STATIC);
}
break;
}
default: {
assert( iCol==3 );
if( eDetail==FTS5_DETAIL_FULL ){
int ii = FTS5_POS2OFFSET(pCsr->iInstPos);
sqlite3_result_int(pCtx, ii);
}
break;
}
}
}
if( iVal>0 ) sqlite3_result_int64(pCtx, iVal);
+3 -1
View File
@@ -441,7 +441,7 @@ db func funk funk
do_catchsql_test 16.2 {
SELECT funk(), bm25(n1), funk() FROM n1 WHERE n1 MATCH 'a+b+c+d'
} {0 {{} -1e-06 {}}}
# {1 {SQL logic error}}
# {1 {SQL logic error or missing database}}
#-------------------------------------------------------------------------
#
@@ -595,3 +595,5 @@ do_execsql_test 22.1 {
finish_test
+1
View File
@@ -294,3 +294,4 @@ do_execsql_test 7.0 {
finish_test
+1
View File
@@ -276,3 +276,4 @@ foreach {tn expr tclexpr} {
}
finish_test
+2
View File
@@ -231,6 +231,7 @@ foreach {T create} {
set res [lsort -integer -increasing $res]
}
set n [llength $res]
if {$T==5} breakpoint
do_execsql_test $T.$bAsc.$tn.$n $sql $res
}
}
@@ -241,3 +242,4 @@ foreach {T create} {
}
finish_test
+1
View File
@@ -309,3 +309,4 @@ foreach {tn q cnt} {
}
finish_test
+1
View File
@@ -178,3 +178,4 @@ do_execsql_test 5.1 {
} ;# foreach_detail_mode
finish_test
+1
View File
@@ -142,3 +142,4 @@ if {[detail_is_full]} {
finish_test
+1
View File
@@ -167,3 +167,4 @@ do_execsql_test 1.8.2 {
#db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM t1_data} {puts $r}
finish_test
+1
View File
@@ -55,3 +55,4 @@ do_execsql_test 1.2 {
finish_test
+1
View File
@@ -66,3 +66,4 @@ do_execsql_test 2.0 { INSERT INTO t1(t1) VALUES('integrity-check') }
finish_test
+1
View File
@@ -147,3 +147,4 @@ do_execsql_test 3.1 {
}
finish_test
+2 -1
View File
@@ -77,7 +77,7 @@ foreach {tn defn} {
} {
do_test 2.2.$tn {
catchsql { INSERT INTO ft1(ft1, rank) VALUES('rank', $defn) }
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
}
#-------------------------------------------------------------------------
@@ -297,3 +297,4 @@ do_catchsql_test 4.4.4 {
finish_test
+2
View File
@@ -89,6 +89,7 @@ do_execsql_test 3.1 {
BEGIN;
INSERT INTO abc(rowid, a) VALUES(2, 'a');
}
breakpoint
do_execsql_test 3.2 {
SELECT rowid FROM abc WHERE abc MATCH 'a';
} {1 2}
@@ -99,3 +100,4 @@ do_execsql_test 3.3 {
} {1 2}
finish_test
+1
View File
@@ -342,3 +342,4 @@ foreach {tn expr} {
finish_test
+2
View File
@@ -240,6 +240,7 @@ foreach {tn lRow res} {
} {
execsql { DELETE FROM x1 }
foreach row $lRow { execsql { INSERT INTO x1 VALUES($row) } }
breakpoint
do_execsql_test 8.$tn {
SELECT highlight(x1, 0, '[', ']') FROM x1 WHERE x1 MATCH 'a OR (b AND d)';
} $res
@@ -278,3 +279,4 @@ do_execsql_test 9.3 {
finish_test
+1
View File
@@ -112,3 +112,4 @@ db eval {
}
finish_test
+1
View File
@@ -61,3 +61,4 @@ do_test 2.1...slow {
} {}
finish_test
+2
View File
@@ -64,3 +64,5 @@ foreach_detail_mode $::testprefix {
}
finish_test
+2
View File
@@ -84,3 +84,5 @@ foreach_detail_mode $::testprefix {
finish_test
+1
View File
@@ -143,6 +143,7 @@ do_execsql_test 4.1.1 {
INSERT INTO t5 VALUES('2 4 6 8');
}
breakpoint
do_execsql_test 4.1.2 {
INSERT INTO t5(t5) VALUES('integrity-check');
}
+16 -14
View File
@@ -66,7 +66,7 @@ foreach {tn val} {
} {
do_catchsql_test 3.$tn {
INSERT INTO t1(t1, rank) VALUES('rank', $val);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
}
#-------------------------------------------------------------------------
@@ -110,6 +110,7 @@ do_catchsql_test 5.1 {
CREATE VIRTUAL TABLE xx USING fts5(x, tokenize="porter 'ascii");
} {1 {parse error in tokenize directive}}
breakpoint
do_catchsql_test 5.2 {
CREATE VIRTUAL TABLE xx USING fts5(x, [y[]);
} {0 {}}
@@ -168,33 +169,33 @@ do_execsql_test 9.0 {
} {}
do_catchsql_test 9.1.1 {
INSERT INTO abc(abc, rank) VALUES('pgsz', -5);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.1.2 {
INSERT INTO abc(abc, rank) VALUES('pgsz', 50000000);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.1.3 {
INSERT INTO abc(abc, rank) VALUES('pgsz', 66.67);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.2.1 {
INSERT INTO abc(abc, rank) VALUES('automerge', -5);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.2.2 {
INSERT INTO abc(abc, rank) VALUES('automerge', 50000000);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.2.3 {
INSERT INTO abc(abc, rank) VALUES('automerge', 66.67);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_execsql_test 9.2.4 {
INSERT INTO abc(abc, rank) VALUES('automerge', 1);
} {}
do_catchsql_test 9.3.1 {
INSERT INTO abc(abc, rank) VALUES('crisismerge', -5);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.3.2 {
INSERT INTO abc(abc, rank) VALUES('crisismerge', 66.67);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_execsql_test 9.3.3 {
INSERT INTO abc(abc, rank) VALUES('crisismerge', 1);
} {}
@@ -204,14 +205,14 @@ do_execsql_test 9.3.4 {
do_catchsql_test 9.4.1 {
INSERT INTO abc(abc, rank) VALUES('nosuchoption', 1);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.5.1 {
INSERT INTO abc(abc, rank) VALUES('hashsize', 'not an integer');
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.5.2 {
INSERT INTO abc(abc, rank) VALUES('hashsize', -500000);
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
do_catchsql_test 9.5.3 {
INSERT INTO abc(abc, rank) VALUES('hashsize', 500000);
} {0 {}}
@@ -244,7 +245,7 @@ foreach {tn opt} {
do_catchsql_test 12.1 {
INSERT INTO t1(t1, rank) VALUES('rank', NULL);;
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
#-------------------------------------------------------------------------
# errors in the 'usermerge' option
@@ -259,7 +260,8 @@ foreach {tn val} {
4 1
} {
set sql "INSERT INTO tt(tt, rank) VALUES('usermerge', $val)"
do_catchsql_test 13.$tn $sql {1 {SQL logic error}}
do_catchsql_test 13.$tn $sql {1 {SQL logic error or missing database}}
}
finish_test
+2
View File
@@ -66,3 +66,5 @@ do_execsql_test 2.1 {
}
finish_test
-247
View File
@@ -1,247 +0,0 @@
# 2017 August 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5connect
ifcapable !fts5 {
finish_test
return
}
#-------------------------------------------------------------------------
# The tests in this file test the outcome of a schema-reset happening
# within the xConnect() method of an FTS5 table. At one point this
# was causing a problem in SQLite. Each test proceeds as follows:
#
# 1. Connection [db] opens the db and reads from some unrelated, non-FTS5
# table causing SQLite to load the db schema into memory.
#
# 2. Connection [db2] opens the db and modifies the db schema.
#
# 3. Connection [db] reads or writes an existing fts5 table. That the
# schema has been modified is detected inside the fts5 xConnect()
# callback that is invoked by sqlite3_prepare().
#
# 4. Verify that the statement in 3 has worked. SQLite should detect
# that the schema has changed and successfully prepare the
# statement against the new schema.
#
# Test plan:
#
# 1.*: Trigger the xConnect()/schema-reset using statements executed
# directly against an FTS5 table.
#
# 2.*: Using various statements executed by various BEFORE triggers.
#
# 3.*: Using various statements executed by various AFTER triggers.
#
# 4.*: Using various statements executed by various INSTEAD OF triggers.
#
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE ft1 USING fts5(a, b);
CREATE TABLE abc(x INTEGER PRIMARY KEY);
CREATE TABLE t1(i INTEGER PRIMARY KEY, a, b);
INSERT INTO ft1 VALUES('one', 'two');
INSERT INTO ft1 VALUES('three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM ft1" {one two three four}
2 "REPLACE INTO ft1(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft1" {five six three four}
4 "INSERT INTO ft1 VALUES('seven', 'eight')" {}
5 "SELECT * FROM ft1" {five six three four seven eight}
6 "DELETE FROM ft1 WHERE rowid=2" {}
7 "UPDATE ft1 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft1" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 1.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 1.$tn.2 $sql $res
do_execsql_test 1.$tn.3 {
INSERT INTO ft1(ft1) VALUES('integrity-check');
}
}
do_execsql_test 2.0 {
CREATE VIRTUAL TABLE ft2 USING fts5(a, b);
CREATE TABLE t2(a, b);
CREATE TABLE log(txt);
CREATE TRIGGER t2_ai AFTER INSERT ON t2 BEGIN
INSERT INTO ft2(rowid, a, b) VALUES(new.rowid, new.a, new.b);
INSERT INTO log VALUES('insert');
END;
CREATE TRIGGER t2_ad AFTER DELETE ON t2 BEGIN
DELETE FROM ft2 WHERE rowid = old.rowid;
INSERT INTO log VALUES('delete');
END;
CREATE TRIGGER t2_au AFTER UPDATE ON t2 BEGIN
UPDATE ft2 SET a=new.a, b=new.b WHERE rowid=new.rowid;
INSERT INTO log VALUES('update');
END;
INSERT INTO t2 VALUES('one', 'two');
INSERT INTO t2 VALUES('three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM t2" {one two three four}
2 "REPLACE INTO t2(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft2" {five six three four}
4 "INSERT INTO t2 VALUES('seven', 'eight')" {}
5 "SELECT * FROM ft2" {five six three four seven eight}
6 "DELETE FROM t2 WHERE rowid=2" {}
7 "UPDATE t2 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft2" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 2.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 2.$tn.2 $sql $res
do_execsql_test 2.$tn.3 {
INSERT INTO ft2(ft2) VALUES('integrity-check');
}
}
do_execsql_test 3.0 {
CREATE VIRTUAL TABLE ft3 USING fts5(a, b);
CREATE TABLE t3(a, b);
CREATE TRIGGER t3_ai BEFORE INSERT ON t3 BEGIN
INSERT INTO ft3(rowid, a, b) VALUES(new.rowid, new.a, new.b);
INSERT INTO log VALUES('insert');
END;
CREATE TRIGGER t3_ad BEFORE DELETE ON t3 BEGIN
DELETE FROM ft3 WHERE rowid = old.rowid;
INSERT INTO log VALUES('delete');
END;
CREATE TRIGGER t3_au BEFORE UPDATE ON t3 BEGIN
UPDATE ft3 SET a=new.a, b=new.b WHERE rowid=new.rowid;
INSERT INTO log VALUES('update');
END;
INSERT INTO t3(rowid, a, b) VALUES(1, 'one', 'two');
INSERT INTO t3(rowid, a, b) VALUES(2, 'three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM t3" {one two three four}
2 "REPLACE INTO t3(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft3" {five six three four}
4 "INSERT INTO t3(rowid, a, b) VALUES(3, 'seven', 'eight')" {}
5 "SELECT * FROM ft3" {five six three four seven eight}
6 "DELETE FROM t3 WHERE rowid=2" {}
7 "UPDATE t3 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft3" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 3.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 3.$tn.2 $sql $res
do_execsql_test 3.$tn.3 {
INSERT INTO ft3(ft3) VALUES('integrity-check');
}
}
do_execsql_test 4.0 {
CREATE VIRTUAL TABLE ft4 USING fts5(a, b);
CREATE VIEW v4 AS SELECT rowid, * FROM ft4;
CREATE TRIGGER t4_ai INSTEAD OF INSERT ON v4 BEGIN
INSERT INTO ft4(rowid, a, b) VALUES(new.rowid, new.a, new.b);
INSERT INTO log VALUES('insert');
END;
CREATE TRIGGER t4_ad INSTEAD OF DELETE ON v4 BEGIN
DELETE FROM ft4 WHERE rowid = old.rowid;
INSERT INTO log VALUES('delete');
END;
CREATE TRIGGER t4_au INSTEAD OF UPDATE ON v4 BEGIN
UPDATE ft4 SET a=new.a, b=new.b WHERE rowid=new.rowid;
INSERT INTO log VALUES('update');
END;
INSERT INTO ft4(rowid, a, b) VALUES(1, 'one', 'two');
INSERT INTO ft4(rowid, a, b) VALUES(2, 'three', 'four');
}
foreach {tn sql res} {
1 "SELECT * FROM ft4" {one two three four}
2 "REPLACE INTO v4(rowid, a, b) VALUES(1, 'five', 'six')" {}
3 "SELECT * FROM ft4" {five six three four}
4 "INSERT INTO v4(rowid, a, b) VALUES(3, 'seven', 'eight')" {}
5 "SELECT * FROM ft4" {five six three four seven eight}
6 "DELETE FROM v4 WHERE rowid=2" {}
7 "UPDATE v4 SET b='nine' WHERE rowid=1" {}
8 "SELECT * FROM ft4" {five nine seven eight}
} {
catch { db close }
catch { db2 close }
sqlite3 db test.db
sqlite3 db2 test.db
do_test 4.$tn.1 {
db eval { INSERT INTO abc DEFAULT VALUES }
db2 eval { CREATE TABLE newtable(x,y); DROP TABLE newtable }
} {}
do_execsql_test 4.$tn.2 $sql $res
do_execsql_test 4.$tn.3 {
INSERT INTO ft3(ft3) VALUES('integrity-check');
}
}
finish_test
+1
View File
@@ -255,3 +255,4 @@ do_execsql_test 6.2 {
finish_test
+1
View File
@@ -96,3 +96,4 @@ do_catchsql_test 3.1 {
} {1 {database disk image is malformed}}
finish_test
+1
View File
@@ -269,3 +269,4 @@ do_catchsql_test 6.2 {
sqlite3_fts5_may_be_corrupt 0
finish_test
+1
View File
@@ -409,3 +409,4 @@ do_catchsql_test 9.2.2 {
sqlite3_fts5_may_be_corrupt 0
finish_test
+1
View File
@@ -51,3 +51,4 @@ do_test 1.2 {
} {}
finish_test
+1
View File
@@ -241,3 +241,4 @@ do_execsql_test 5.3 {
finish_test
+2
View File
@@ -63,3 +63,5 @@ foreach_detail_mode $::testprefix {
finish_test
+3
View File
@@ -66,6 +66,7 @@ proc do_dlidx_test1 {tn spc1 spc2 nEntry iFirst nStep} {
}
execsql COMMIT
breakpoint
do_test $tn.1 {
execsql { INSERT INTO t1(t1) VALUES('integrity-check') }
} {}
@@ -123,6 +124,7 @@ proc do_dlidx_test2 {tn nEntry iFirst nStep} {
do_execsql_test $tn.1 {
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a'
} {1}
breakpoint
do_execsql_test $tn.2 {
SELECT rowid FROM t1 WHERE t1 MATCH 'b AND a' ORDER BY rowid DESC
} {1}
@@ -195,3 +197,4 @@ foreach v $vocab {
finish_test
+1
View File
@@ -44,3 +44,4 @@ do_execsql_test 1.2 {
finish_test
+3
View File
@@ -81,3 +81,6 @@ do_execsql_test 3.3 {
finish_test
+1
View File
@@ -351,3 +351,4 @@ do_faultsim_test 9.1 -faults oom-* -prep {
finish_test
+1
View File
@@ -137,3 +137,4 @@ do_faultsim_test 5.0 -faults oom-* -prep {
}
finish_test
+1
View File
@@ -110,3 +110,4 @@ do_faultsim_test 3.2 -faults oom-* -prep {
finish_test
+1
View File
@@ -395,3 +395,4 @@ do_faultsim_test 14.1 -faults oom-t* -prep {
}
finish_test
+2
View File
@@ -105,6 +105,7 @@ do_faultsim_test 3.2 -faults oom-t* -body {
faultsim_test_result {0 {1 10 11 12 13 14 15 16 17 18 19 2}}
}
breakpoint
do_execsql_test 3.3.0 {
SELECT * FROM tv2;
} {
@@ -129,3 +130,4 @@ do_faultsim_test 3.3 -faults oom-t* -body {
finish_test
+2
View File
@@ -280,6 +280,7 @@ do_faultsim_test 5.4 -faults oom* -prep {
#-------------------------------------------------------------------------
catch { db close }
breakpoint
do_faultsim_test 6 -faults oom* -prep {
sqlite_orig db test.db
sqlite3_db_config_lookaside db 0 0 0
@@ -291,3 +292,4 @@ do_faultsim_test 6 -faults oom* -prep {
db close
}
finish_test
+1
View File
@@ -116,3 +116,4 @@ do_faultsim_test 2.2 -faults oom-* -body {
}
finish_test
+1
View File
@@ -82,3 +82,4 @@ do_faultsim_test 4 -faults oom-* -prep {
finish_test
+1
View File
@@ -153,3 +153,4 @@ do_faultsim_test 6 -faults oom-* -body {
} ;# foreach_detail_mode...
finish_test
+1
View File
@@ -61,3 +61,4 @@ do_faultsim_test 2 -faults oom* -prep {
faultsim_test_result {0 {1 2}}
}
finish_test
+1
View File
@@ -132,3 +132,4 @@ do_faultsim_test 4.2 -faults oom* -body {
finish_test
+1
View File
@@ -40,3 +40,4 @@ do_test 1.1 {
finish_test
+1
View File
@@ -90,3 +90,4 @@ do_catchsql_test 4.1 {
} {1 {fts5: syntax error near "`"}}
finish_test
+2
View File
@@ -121,6 +121,7 @@ foreach_detail_mode $testprefix {
}
execsql { CREATE VIRTUAL TABLE t2 USING fts5(x, detail=%DETAIL%) }
breakpoint
execsql {
INSERT INTO t2 VALUES($small || ' ' || $big);
}
@@ -129,3 +130,4 @@ foreach_detail_mode $testprefix {
} ;# foreach_detail_mode
finish_test
+1
View File
@@ -210,3 +210,4 @@ foreach {tn pgsz} {
}
finish_test
+1
View File
@@ -70,3 +70,4 @@ do_execsql_test 1.6 {
finish_test
-43
View File
@@ -1,43 +0,0 @@
# 2014 June 17
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library. The
# focus of this script is testing the FTS5 module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5leftjoin
# If SQLITE_ENABLE_FTS5 is not defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE vt USING fts5(x);
INSERT INTO vt VALUES('abc');
INSERT INTO vt VALUES('xyz');
CREATE TABLE t1(a INTEGER PRIMARY KEY);
INSERT INTO t1 VALUES(1), (2);
}
do_execsql_test 1.1 {
SELECT * FROM t1 LEFT JOIN (
SELECT rowid AS rrr, * FROM vt WHERE vt MATCH 'abc'
) ON t1.a = rrr
} {1 1 abc 2 {} {}}
do_execsql_test 1.2 {
SELECT * FROM t1 LEFT JOIN vt ON (vt MATCH 'abc')
} {1 abc 2 abc}
finish_test
+2 -1
View File
@@ -472,7 +472,7 @@ do_execsql_test 12.1 {
#
reset_db
proc xyz {} {}
db func fts5 -argcount 1 xyz
db func fts5 -argcount 0 xyz
do_test 13.1 {
list [catch { sqlite3_fts5_register_matchinfo db } msg] $msg
} {1 SQLITE_ERROR}
@@ -492,3 +492,4 @@ do_catchsql_test 14.2 {
} {1 {unrecognized matchinfo flag: d}}
finish_test
+1
View File
@@ -241,3 +241,4 @@ do_execsql_test 6.3 {
finish_test
+1
View File
@@ -55,3 +55,4 @@ do_execsql_test 1.2 {
}
finish_test
+1
View File
@@ -45,3 +45,4 @@ do_multiclient_test tn {
};# do_multiclient_test
};# foreach_detail_mode
finish_test
+1
View File
@@ -68,3 +68,4 @@ do_near_test 1.25 "a b c d e f g h i" { NEAR(i a+b+c+d b+c, 4) } 0
finish_test
+1
View File
@@ -178,3 +178,4 @@ do_execsql_test 4.3.1 {
do_test 4.2.2 { fts5_level_segs ttt } {3}
finish_test
+1
View File
@@ -106,3 +106,4 @@ foreach {tn nStep} {
do_test 2.$tn.6 { fts5_segcount t1 } 1
}
finish_test
+1
View File
@@ -116,3 +116,4 @@ do_execsql_test 2.0 {
}
finish_test
+1
View File
@@ -64,3 +64,4 @@ do_eqp_test 1.5 {
finish_test
+1
View File
@@ -11803,3 +11803,4 @@ foreach {in out} $test_vocab {
finish_test
+1
View File
@@ -67,3 +67,4 @@ foreach {in out} $test_vocab {
finish_test
+2
View File
@@ -341,3 +341,5 @@ foreach {tn create} {
}
finish_test
+2
View File
@@ -79,3 +79,5 @@ for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} {
finish_test
+1
View File
@@ -152,3 +152,4 @@ do_execsql_test 4.1 {
finish_test
+1
View File
@@ -64,3 +64,4 @@ do_catchsql_test 2.2 {
INSERT INTO nc(nc) VALUES('rebuild');
} {1 {'rebuild' may not be used with a contentless fts5 table}}
finish_test
+1
View File
@@ -149,3 +149,4 @@ do_test 4.3 {
finish_test
+1
View File
@@ -216,3 +216,4 @@ do_execsql_test 6.2 {
finish_test
+1
View File
@@ -411,6 +411,7 @@ do_catchsql_test 19.2 {
#-------------------------------------------------------------------------
reset_db
breakpoint
do_execsql_test 20.0 {
CREATE VIRTUAL TABLE x1 USING fts5(x);
INSERT INTO x1(x1, rank) VALUES('pgsz', 32);
+1
View File
@@ -370,3 +370,4 @@ do_execsql_test 17.6 {
#db eval {SELECT rowid, fts5_decode_none(rowid, block) aS r FROM t2_data} {puts $r}
finish_test
+1
View File
@@ -116,3 +116,4 @@ do_execsql_test 4.6 {
finish_test
+1
View File
@@ -421,3 +421,4 @@ do_execsql_test 7.1.2 {
} ;# foreach_detail_mode
finish_test
+1
View File
@@ -161,3 +161,4 @@ foreach {tn expr} {
}
finish_test
+1 -1
View File
@@ -109,7 +109,7 @@ do_catchsql_test 2.0 {
do_catchsql_test 2.1 {
CREATE VIRTUAL TABLE t4 USING fts5tokenize;
SELECT * FROM t4;
} {1 {SQL logic error}}
} {1 {SQL logic error or missing database}}
finish_test
+1
View File
@@ -302,3 +302,4 @@ do_test 9.5.2 { set ::flags } {query}
finish_test
+2
View File
@@ -50,6 +50,7 @@ do_execsql_test 2.0 "
INSERT INTO t2 VALUES('\xC0\xC8\xCC');
INSERT INTO t3 VALUES('\xC0\xC8\xCC');
"
breakpoint
do_execsql_test 2.1 "
SELECT 't1' FROM t1 WHERE t1 MATCH '\xE0\xE8\xEC';
SELECT 't2' FROM t2 WHERE t2 MATCH '\xE0\xE8\xEC';
@@ -58,3 +59,4 @@ do_execsql_test 2.1 "
finish_test
+1
View File
@@ -281,6 +281,7 @@ do_test 4.4 {
#-------------------------------------------------------------------------
breakpoint
do_unicode_token_test3 5.1 {tokenchars {}} {
sqlite3_reset sqlite3_column_int
} {
+1
View File
@@ -126,3 +126,4 @@ do_test 1.5 {
finish_test
+1
View File
@@ -76,3 +76,4 @@ do_execsql_test 3.2 {
finish_test
+2
View File
@@ -117,3 +117,5 @@ do_execsql_test 2.2.integrity {
}
finish_test
+1
View File
@@ -61,3 +61,4 @@ do_test 1.7 {
finish_test
+1
View File
@@ -210,6 +210,7 @@ do_execsql_test 5.0 {
INSERT INTO aux.t1 VALUES('x n z');
}
breakpoint
do_execsql_test 5.1 {
CREATE VIRTUAL TABLE temp.vm USING fts5vocab(main, t1, row);
CREATE VIRTUAL TABLE temp.vt1 USING fts5vocab(t1, row);
-209
View File
@@ -1,209 +0,0 @@
# 2017 August 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.
#
#***********************************************************************
#
# The tests in this file focus on testing the fts5vocab module.
#
source [file join [file dirname [info script]] fts5_common.tcl]
set testprefix fts5vocab
# If SQLITE_ENABLE_FTS5 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE t1 USING fts5(a, b);
CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
INSERT INTO t1 VALUES('one two', 'two three');
INSERT INTO t1 VALUES('three four', 'four five five five');
}
do_execsql_test 1.1 {
SELECT * FROM v1;
} {
five 2 b 1
five 2 b 2
five 2 b 3
four 2 a 1
four 2 b 0
one 1 a 0
three 1 b 1
three 2 a 0
two 1 a 1
two 1 b 0
}
do_execsql_test 1.2 {
SELECT * FROM v1 WHERE term='three';
} {
three 1 b 1
three 2 a 0
}
do_execsql_test 1.3 {
BEGIN;
DELETE FROM t1 WHERE rowid=2;
SELECT * FROM v1;
ROLLBACK;
} {
one 1 a 0
three 1 b 1
two 1 a 1
two 1 b 0
}
do_execsql_test 1.4 {
BEGIN;
DELETE FROM t1 WHERE rowid=1;
SELECT * FROM v1;
ROLLBACK;
} {
five 2 b 1
five 2 b 2
five 2 b 3
four 2 a 1
four 2 b 0
three 2 a 0
}
do_execsql_test 1.5 {
DELETE FROM t1;
SELECT * FROM v1;
} {
}
#-------------------------------------------------------------------------
#
do_execsql_test 2.0 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS v1;
CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=column);
CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
INSERT INTO t1 VALUES('one two', 'two three');
INSERT INTO t1 VALUES('three four', 'four five five five');
}
do_execsql_test 2.1 {
SELECT * FROM v1;
} {
five 2 b {}
four 2 a {}
four 2 b {}
one 1 a {}
three 1 b {}
three 2 a {}
two 1 a {}
two 1 b {}
}
do_execsql_test 2.2 {
SELECT * FROM v1 WHERE term='three';
} {
three 1 b {}
three 2 a {}
}
do_execsql_test 2.3 {
BEGIN;
DELETE FROM t1 WHERE rowid=2;
SELECT * FROM v1;
ROLLBACK;
} {
one 1 a {}
three 1 b {}
two 1 a {}
two 1 b {}
}
do_execsql_test 2.4 {
BEGIN;
DELETE FROM t1 WHERE rowid=1;
SELECT * FROM v1;
ROLLBACK;
} {
five 2 b {}
four 2 a {}
four 2 b {}
three 2 a {}
}
do_execsql_test 2.5 {
DELETE FROM t1;
SELECT * FROM v1;
} {
}
#-------------------------------------------------------------------------
#
do_execsql_test 3.0 {
DROP TABLE IF EXISTS t1;
DROP TABLE IF EXISTS v1;
CREATE VIRTUAL TABLE t1 USING fts5(a, b, detail=none);
CREATE VIRTUAL TABLE v1 USING fts5vocab(t1, instance);
INSERT INTO t1 VALUES('one two', 'two three');
INSERT INTO t1 VALUES('three four', 'four five five five');
}
do_execsql_test 3.1 {
SELECT * FROM v1;
} {
five 2 {} {}
four 2 {} {}
one 1 {} {}
three 1 {} {}
three 2 {} {}
two 1 {} {}
}
do_execsql_test 3.2 {
SELECT * FROM v1 WHERE term='three';
} {
three 1 {} {}
three 2 {} {}
}
do_execsql_test 3.3 {
BEGIN;
DELETE FROM t1 WHERE rowid=2;
SELECT * FROM v1;
ROLLBACK;
} {
one 1 {} {}
three 1 {} {}
two 1 {} {}
}
do_execsql_test 3.4 {
BEGIN;
DELETE FROM t1 WHERE rowid=1;
SELECT * FROM v1;
ROLLBACK;
} {
five 2 {} {}
four 2 {} {}
three 2 {} {}
}
do_execsql_test 3.5 {
DELETE FROM t1;
SELECT * FROM v1;
} {
}
finish_test

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