Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge in all the trunk changes that have occurred since this branch was opened. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | vtab-IN-opt |
Files: | files | file ages | folders |
SHA1: |
6d507e4de924e2f4556ea4a03ee0fa7d |
User & Date: | drh 2012-12-14 15:54:05.684 |
Context
2012-12-14
| ||
17:48 | Remove an unreachable branch. Improvements to comments. (Closed-Leaf check-in: d2fb7619b0 user: drh tags: vtab-IN-opt) | |
15:54 | Merge in all the trunk changes that have occurred since this branch was opened. (check-in: 6d507e4de9 user: drh tags: vtab-IN-opt) | |
15:36 | Fix the virtual table IN optimizer so that it work even if the virtual table implementation leaves the sqlite3_index_info.aConstraintUsage[].omit flag clear for an equality constraint that it intends to use. (check-in: d6e045f89c user: drh tags: vtab-IN-opt) | |
2012-12-13
| ||
18:57 | Generalize the min/max optimization so that if an appropriate index exists, the index it can be used by any aggregate query that contains only a single max() or min() and does not contain a GROUP BY clause. (check-in: 52e755943f user: drh tags: trunk) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
41 42 43 44 45 46 47 | # Compiler options needed for programs that use the TCL library. # TCC += @TCL_INCLUDE_SPEC@ # The library that programs using TCL must link against. # | | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | # Compiler options needed for programs that use the TCL library. # TCC += @TCL_INCLUDE_SPEC@ # The library that programs using TCL must link against. # LIBTCL = @TCL_LIB_SPEC@ # Compiler options needed for programs that use the readline() library. # READLINE_FLAGS = -DHAVE_READLINE=@TARGET_HAVE_READLINE@ @TARGET_READLINE_INC@ # The library that programs using readline() must link against. # |
︙ | ︙ | |||
931 932 933 934 935 936 937 | clean: rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la rm -f sqlite3.h opcodes.* rm -rf .libs .deps rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz rm -f mkkeywordhash$(BEXE) keywordhash.h | < | | 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 | clean: rm -f *.lo *.la *.o sqlite3$(TEXE) libsqlite3.la rm -f sqlite3.h opcodes.* rm -rf .libs .deps rm -f lemon$(BEXE) lempar.c parse.* sqlite*.tar.gz rm -f mkkeywordhash$(BEXE) keywordhash.h rm -f *.da *.bb *.bbg gmon.out rm -rf quota2a quota2b quota2c rm -rf tsrc .target_source rm -f tclsqlite3$(TEXE) rm -f testfixture$(TEXE) test.db rm -f sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def rm -f sqlite3.c rm -f sqlite3_analyzer$(TEXE) sqlite3_analyzer.c rm -f sqlite-*-output.vsix distclean: clean rm -f config.log config.status libtool Makefile sqlite3.pc # # Windows section # |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
825 826 827 828 829 830 831 | $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl | | | | 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 | $(TCLSH_CMD) $(TOP)\tool\vdbe-compress.tcl < tsrc\vdbe.c > vdbe.new move vdbe.new tsrc\vdbe.c echo > .target_source sqlite3.c: .target_source $(TOP)\tool\mksqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\mksqlite3c.tcl sqlite3-all.c: sqlite3.c $(TOP)\tool\split-sqlite3c.tcl $(TCLSH_CMD) $(TOP)\tool\split-sqlite3c.tcl # Rule to build the amalgamation # sqlite3.lo: sqlite3.c $(LTCOMPILE) -c sqlite3.c # Rules to build the LEMON compiler generator |
︙ | ︙ | |||
1243 1244 1245 1246 1247 1248 1249 | del /Q .target_source del /Q tclsqlite3.exe tclsqlite3.exp del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c del /Q sqlite3rc.h del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c | | | 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 | del /Q .target_source del /Q tclsqlite3.exe tclsqlite3.exp del /Q testfixture.exe testfixture.exp test.db del /Q sqlite3.dll sqlite3.lib sqlite3.exp sqlite3.def del /Q sqlite3.c del /Q sqlite3rc.h del /Q sqlite3_analyzer.exe sqlite3_analyzer.exp sqlite3_analyzer.c del /Q sqlite-*-output.vsix # Dynamic link library section. # dll: sqlite3.dll sqlite3.def: libsqlite3.lib echo EXPORTS > sqlite3.def dumpbin /all libsqlite3.lib \ | $(NAWK) "/ 1 _?sqlite3_/ { sub(/^.* _?/,\"\");print }" \ | sort >> sqlite3.def sqlite3.dll: $(LIBOBJ) $(LIBRESOBJS) sqlite3.def $(LD) $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) /DLL /DEF:sqlite3.def /OUT:$@ $(LIBOBJ) $(LIBRESOBJS) $(LTLIBS) $(TLIBS) |
Changes to VERSION.
|
| | | 1 | 3.7.16 |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.62 for sqlite 3.7.16. # # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. ## --------------------- ## ## M4sh Initialization. ## |
︙ | ︙ | |||
739 740 741 742 743 744 745 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | MFLAGS= MAKEFLAGS= SHELL=${CONFIG_SHELL-/bin/sh} # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.7.16' PACKAGE_STRING='sqlite 3.7.16' PACKAGE_BUGREPORT='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H # include <sys/types.h> |
︙ | ︙ | |||
875 876 877 878 879 880 881 | SQLITE_OS_UNIX SQLITE_OS_WIN SQLITE_OS_OS2 TARGET_EXEEXT TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR | < | 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | SQLITE_OS_UNIX SQLITE_OS_WIN SQLITE_OS_OS2 TARGET_EXEEXT TCL_VERSION TCL_BIN_DIR TCL_SRC_DIR TCL_INCLUDE_SPEC TCL_LIB_FILE TCL_LIB_FLAG TCL_LIB_SPEC TCL_STUB_LIB_FILE TCL_STUB_LIB_FLAG TCL_STUB_LIB_SPEC |
︙ | ︙ | |||
1481 1482 1483 1484 1485 1486 1487 | # # Report the --help message. # 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 | | | 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | # # Report the --help message. # 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.7.16 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1546 1547 1548 1549 1550 1551 1552 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.7.16:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1662 1663 1664 1665 1666 1667 1668 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | | 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.7.16 generated by GNU Autoconf 2.62 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit fi 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.7.16, which was generated by GNU Autoconf 2.62. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
3730 3731 3732 3733 3734 3735 3736 | { $as_echo "$as_me:$LINENO: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if test "${lt_cv_nm_interface+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext | | | | | 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 | { $as_echo "$as_me:$LINENO: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if test "${lt_cv_nm_interface+set}" = set; then $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext (eval echo "\"\$as_me:3736: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:3739: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:3742: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" fi rm -f conftest* fi { $as_echo "$as_me:$LINENO: result: $lt_cv_nm_interface" >&5 |
︙ | ︙ | |||
4958 4959 4960 4961 4962 4963 4964 | ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. | | | 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 | ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 4964 "configure"' > conftest.$ac_ext if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5 (exit $ac_status); }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in |
︙ | ︙ | |||
6827 6828 6829 6830 6831 6832 6833 | # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` | | | | 6826 6827 6828 6829 6830 6831 6832 6833 6834 6835 6836 6837 6838 6839 6840 6841 6842 6843 6844 | # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -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:6833: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:6837: \$? = $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. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes |
︙ | ︙ | |||
7166 7167 7168 7169 7170 7171 7172 | # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` | | | | 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 | # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. # The option is referenced via a variable to avoid confusing sed. lt_compile=`echo "$ac_compile" | $SED \ -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:7172: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7176: \$? = $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. $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes |
︙ | ︙ | |||
7271 7272 7273 7274 7275 7276 7277 | # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` | | | | 7270 7271 7272 7273 7274 7275 7276 7277 7278 7279 7280 7281 7282 7283 7284 7285 7286 7287 7288 | # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -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:7277: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7281: \$? = $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 # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then |
︙ | ︙ | |||
7326 7327 7328 7329 7330 7331 7332 | # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` | | | | 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 | # (2) before a word containing "conftest.", or (3) at the end. # Note that $ac_compile itself does not contain backslashes and begins # with a dollar sign (not a hyphen), so the echo should work correctly. lt_compile=`echo "$ac_compile" | $SED \ -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:7332: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7336: \$? = $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 # So say no if there are warnings $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then |
︙ | ︙ | |||
10139 10140 10141 10142 10143 10144 10145 | else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF | | | 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 10150 10151 10152 | else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 10145 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> |
︙ | ︙ | |||
10235 10236 10237 10238 10239 10240 10241 | else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF | | | 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 10245 10246 10247 10248 | else if test "$cross_compiling" = yes; then : lt_cv_dlopen_self_static=cross else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF #line 10241 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> |
︙ | ︙ | |||
12905 12906 12907 12908 12909 12910 12911 |
| < | 12904 12905 12906 12907 12908 12909 12910 12911 12912 12913 12914 12915 12916 12917 | fi fi if test "${use_tcl}" = "no" ; then HAVE_TCL="" else HAVE_TCL=1 fi |
︙ | ︙ | |||
14030 14031 14032 14033 14034 14035 14036 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 14028 14029 14030 14031 14032 14033 14034 14035 14036 14037 14038 14039 14040 14041 14042 | exec 6>&1 # Save the log message, to keep $[0] and so on meaningful, and to # 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.7.16, which was generated by GNU Autoconf 2.62. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
14083 14084 14085 14086 14087 14088 14089 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ | | | 14081 14082 14083 14084 14085 14086 14087 14088 14089 14090 14091 14092 14093 14094 14095 | $config_commands Report bugs to <bug-autoconf@gnu.org>." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_version="\\ sqlite config.status 3.7.16 configured by $0, generated by GNU Autoconf 2.62, with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\" Copyright (C) 2008 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to configure.ac.
︙ | ︙ | |||
497 498 499 500 501 502 503 | eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" AC_SUBST(TCL_VERSION) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) | < | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | eval "TCL_STUB_LIB_FILE=\"${TCL_STUB_LIB_FILE}\"" eval "TCL_STUB_LIB_FLAG=\"${TCL_STUB_LIB_FLAG}\"" eval "TCL_STUB_LIB_SPEC=\"${TCL_STUB_LIB_SPEC}\"" AC_SUBST(TCL_VERSION) AC_SUBST(TCL_BIN_DIR) AC_SUBST(TCL_SRC_DIR) AC_SUBST(TCL_INCLUDE_SPEC) AC_SUBST(TCL_LIB_FILE) AC_SUBST(TCL_LIB_FLAG) AC_SUBST(TCL_LIB_SPEC) AC_SUBST(TCL_STUB_LIB_FILE) |
︙ | ︙ |
Changes to ext/async/README.txt.
1 2 3 4 5 6 7 | Normally, when SQLite writes to a database file, it waits until the write operation is finished before returning control to the calling application. Since writing to the file-system is usually very slow compared with CPU bound operations, this can be a performance bottleneck. This directory contains an extension that causes SQLite to perform all write requests using a separate thread running in the background. Although this does not | > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | NOTE (2012-11-29): The functionality implemented by this extension has been superseded by WAL-mode. This module is no longer supported or maintained. The code is retained for historical reference only. ------------------------------------------------------------------------------ Normally, when SQLite writes to a database file, it waits until the write operation is finished before returning control to the calling application. Since writing to the file-system is usually very slow compared with CPU bound operations, this can be a performance bottleneck. This directory contains an extension that causes SQLite to perform all write requests using a separate thread running in the background. Although this does not |
︙ | ︙ | |||
157 158 159 160 161 162 163 | static void async_mutex_leave(int eMutex); static void async_cond_wait(int eCond, int eMutex); static void async_cond_signal(int eCond); static void async_sched_yield(void); The functionality required of each of the above functions is described in comments in sqlite3async.c. | < | 164 165 166 167 168 169 170 | static void async_mutex_leave(int eMutex); static void async_cond_wait(int eCond, int eMutex); static void async_cond_signal(int eCond); static void async_sched_yield(void); The functionality required of each of the above functions is described in comments in sqlite3async.c. |
Changes to ext/async/sqlite3async.c.
︙ | ︙ | |||
1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | } break; } case ASYNC_DELETE: ASYNC_TRACE(("DELETE %s\n", p->zBuf)); rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset); break; case ASYNC_OPENEXCLUSIVE: { int flags = (int)p->iOffset; AsyncFileData *pData = p->pFileData; ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset)); assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0); | > | 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 | } break; } case ASYNC_DELETE: ASYNC_TRACE(("DELETE %s\n", p->zBuf)); rc = pVfs->xDelete(pVfs, p->zBuf, (int)p->iOffset); if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK; break; case ASYNC_OPENEXCLUSIVE: { int flags = (int)p->iOffset; AsyncFileData *pData = p->pFileData; ASYNC_TRACE(("OPEN %s flags=%d\n", p->zBuf, (int)p->iOffset)); assert(pData->pBaseRead->pMethods==0 && pData->pBaseWrite->pMethods==0); |
︙ | ︙ |
Changes to ext/async/sqlite3async.h.
︙ | ︙ | |||
71 72 73 74 75 76 77 | /* ** This function unregisters the asynchronous IO VFS using ** sqlite3_vfs_unregister(). ** ** On win32 platforms, this function also releases the small number of ** critical section and event objects created by sqlite3async_initialize(). */ | | | | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | /* ** This function unregisters the asynchronous IO VFS using ** sqlite3_vfs_unregister(). ** ** On win32 platforms, this function also releases the small number of ** critical section and event objects created by sqlite3async_initialize(). */ void sqlite3async_shutdown(void); /* ** This function may only be called when the asynchronous IO VFS is ** installed (after a call to sqlite3async_initialize()). It processes ** zero or more queued write operations before returning. It is expected ** (but not required) that this function will be called by a different ** thread than those threads that use SQLite. The "background thread" ** that performs IO. ** ** How many queued write operations are performed before returning ** depends on the global setting configured by passing the SQLITEASYNC_HALT ** verb to sqlite3async_control() (see below for details). By default ** this function never returns - it processes all pending operations and ** then blocks waiting for new ones. ** ** If multiple simultaneous calls are made to sqlite3async_run() from two ** or more threads, then the calls are serialized internally. */ void sqlite3async_run(void); /* ** This function may only be called when the asynchronous IO VFS is ** installed (after a call to sqlite3async_initialize()). It is used ** to query or configure various parameters that affect the operation ** of the asynchronous IO VFS. At present there are three parameters ** supported: |
︙ | ︙ |
Changes to ext/fts2/fts2_icu.c.
︙ | ︙ | |||
114 115 116 117 118 119 120 | if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ | | | | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ ); if( !pCsr ){ return SQLITE_NOMEM; } memset(pCsr, 0, sizeof(IcuCursor)); pCsr->aChar = (UChar *)&pCsr[1]; pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3]; pCsr->aOffset[iOut] = iInput; U8_NEXT(zInput, iInput, nInput, c); while( c>0 ){ int isError = 0; c = u_foldCase(c, opt); U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); |
︙ | ︙ |
Changes to ext/fts3/fts3.c.
︙ | ︙ | |||
4739 4740 4741 4742 4743 4744 4745 | char *aTmp; /* Temp space for PoslistNearMerge() */ /* Allocate temporary working space. */ for(p=pExpr; p->pLeft; p=p->pLeft){ nTmp += p->pRight->pPhrase->doclist.nList; } nTmp += p->pPhrase->doclist.nList; | > > > | | | | | | | | | | | | | | | | | | | | | | | | | | | > | 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 | char *aTmp; /* Temp space for PoslistNearMerge() */ /* Allocate temporary working space. */ for(p=pExpr; p->pLeft; p=p->pLeft){ nTmp += p->pRight->pPhrase->doclist.nList; } nTmp += p->pPhrase->doclist.nList; if( nTmp==0 ){ res = 0; }else{ aTmp = sqlite3_malloc(nTmp*2); if( !aTmp ){ *pRc = SQLITE_NOMEM; res = 0; }else{ char *aPoslist = p->pPhrase->doclist.pList; int nToken = p->pPhrase->nToken; for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){ Fts3Phrase *pPhrase = p->pRight->pPhrase; int nNear = p->nNear; res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); } aPoslist = pExpr->pRight->pPhrase->doclist.pList; nToken = pExpr->pRight->pPhrase->nToken; for(p=pExpr->pLeft; p && res; p=p->pLeft){ int nNear; Fts3Phrase *pPhrase; assert( p->pParent && p->pParent->pLeft==p ); nNear = p->pParent->nNear; pPhrase = ( p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase ); res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase); } } sqlite3_free(aTmp); } } return res; } /* ** This function is a helper function for fts3EvalTestDeferredAndNear(). |
︙ | ︙ |
Changes to ext/fts3/fts3_expr.c.
︙ | ︙ | |||
181 182 183 184 185 186 187 | sqlite3_tokenizer_cursor *pCursor; Fts3Expr *pRet = 0; int nConsumed = 0; rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; | | | 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | sqlite3_tokenizer_cursor *pCursor; Fts3Expr *pRet = 0; int nConsumed = 0; rc = sqlite3Fts3OpenTokenizer(pTokenizer, pParse->iLangid, z, n, &pCursor); if( rc==SQLITE_OK ){ const char *zToken; int nToken = 0, iStart = 0, iEnd = 0, iPosition = 0; int nByte; /* total space to allocate */ rc = pModule->xNext(pCursor, &zToken, &nToken, &iStart, &iEnd, &iPosition); if( rc==SQLITE_OK ){ nByte = sizeof(Fts3Expr) + sizeof(Fts3Phrase) + nToken; pRet = (Fts3Expr *)fts3MallocZero(nByte); if( !pRet ){ |
︙ | ︙ | |||
296 297 298 299 300 301 302 | */ rc = sqlite3Fts3OpenTokenizer( pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); if( rc==SQLITE_OK ){ int ii; for(ii=0; rc==SQLITE_OK; ii++){ const char *zByte; | | | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | */ rc = sqlite3Fts3OpenTokenizer( pTokenizer, pParse->iLangid, zInput, nInput, &pCursor); if( rc==SQLITE_OK ){ int ii; for(ii=0; rc==SQLITE_OK; ii++){ const char *zByte; int nByte = 0, iBegin = 0, iEnd = 0, iPos = 0; rc = pModule->xNext(pCursor, &zByte, &nByte, &iBegin, &iEnd, &iPos); if( rc==SQLITE_OK ){ Fts3PhraseToken *pToken; p = fts3ReallocOrFree(p, nSpace + ii*sizeof(Fts3PhraseToken)); if( !p ) goto no_mem; |
︙ | ︙ |
Changes to ext/fts3/fts3_icu.c.
︙ | ︙ | |||
115 116 117 118 119 120 121 | zInput = ""; }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ | | | | 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | zInput = ""; }else if( nInput<0 ){ nInput = strlen(zInput); } nChar = nInput+1; pCsr = (IcuCursor *)sqlite3_malloc( sizeof(IcuCursor) + /* IcuCursor */ ((nChar+3)&~3) * sizeof(UChar) + /* IcuCursor.aChar[] */ (nChar+1) * sizeof(int) /* IcuCursor.aOffset[] */ ); if( !pCsr ){ return SQLITE_NOMEM; } memset(pCsr, 0, sizeof(IcuCursor)); pCsr->aChar = (UChar *)&pCsr[1]; pCsr->aOffset = (int *)&pCsr->aChar[(nChar+3)&~3]; pCsr->aOffset[iOut] = iInput; U8_NEXT(zInput, iInput, nInput, c); while( c>0 ){ int isError = 0; c = u_foldCase(c, opt); U16_APPEND(pCsr->aChar, iOut, nChar, c, isError); |
︙ | ︙ |
Changes to ext/fts3/fts3_snippet.c.
︙ | ︙ | |||
572 573 574 575 576 577 578 | ** or more tokens in zDoc/nDoc. */ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ | | | 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 | ** or more tokens in zDoc/nDoc. */ rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, iLangid, zDoc, nDoc, &pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK && iCurrent<(nSnippet+nDesired) ){ const char *ZDUMMY; int DUMMY1 = 0, DUMMY2 = 0, DUMMY3 = 0; rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &DUMMY2, &DUMMY3, &iCurrent); } pMod->xClose(pC); if( rc!=SQLITE_OK && rc!=SQLITE_DONE ){ return rc; } nShift = (rc==SQLITE_DONE)+iCurrent-nSnippet; assert( nShift<=nDesired ); |
︙ | ︙ | |||
616 617 618 619 620 621 622 | int iEnd = 0; /* Byte offset of end of current token */ int isShiftDone = 0; /* True after snippet is shifted */ int iPos = pFragment->iPos; /* First token of snippet */ u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ int iCol = pFragment->iCol+1; /* Query column to extract text from */ sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ | < < > > | | | > > > > > > > > > > > | 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 | int iEnd = 0; /* Byte offset of end of current token */ int isShiftDone = 0; /* True after snippet is shifted */ int iPos = pFragment->iPos; /* First token of snippet */ u64 hlmask = pFragment->hlmask; /* Highlight-mask for snippet */ int iCol = pFragment->iCol+1; /* Query column to extract text from */ sqlite3_tokenizer_module *pMod; /* Tokenizer module methods object */ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor open on zDoc/nDoc */ zDoc = (const char *)sqlite3_column_text(pCsr->pStmt, iCol); if( zDoc==0 ){ if( sqlite3_column_type(pCsr->pStmt, iCol)!=SQLITE_NULL ){ return SQLITE_NOMEM; } return SQLITE_OK; } nDoc = sqlite3_column_bytes(pCsr->pStmt, iCol); /* Open a token cursor on the document. */ pMod = (sqlite3_tokenizer_module *)pTab->pTokenizer->pModule; rc = sqlite3Fts3OpenTokenizer(pTab->pTokenizer, pCsr->iLangid, zDoc,nDoc,&pC); if( rc!=SQLITE_OK ){ return rc; } while( rc==SQLITE_OK ){ const char *ZDUMMY; /* Dummy argument used with tokenizer */ int DUMMY1 = -1; /* Dummy argument used with tokenizer */ int iBegin = 0; /* Offset in zDoc of start of token */ int iFin = 0; /* Offset in zDoc of end of token */ int isHighlight = 0; /* True for highlighted terms */ /* Variable DUMMY1 is initialized to a negative value above. Elsewhere ** in the FTS code the variable that the third argument to xNext points to ** is initialized to zero before the first (*but not necessarily ** subsequent*) call to xNext(). This is done for a particular application ** that needs to know whether or not the tokenizer is being used for ** snippet generation or for some other purpose. ** ** Extreme care is required when writing code to depend on this ** initialization. It is not a documented part of the tokenizer interface. ** If a tokenizer is used directly by any code outside of FTS, this ** convention might not be respected. */ rc = pMod->xNext(pC, &ZDUMMY, &DUMMY1, &iBegin, &iFin, &iCurrent); if( rc!=SQLITE_OK ){ if( rc==SQLITE_DONE ){ /* Special case - the last token of the snippet is also the last token ** of the column. Append any punctuation that occurred between the end ** of the previous token and the end of the document to the output. ** Then break out of the loop. */ |
︙ | ︙ | |||
1329 1330 1331 1332 1333 1334 1335 | */ void sqlite3Fts3Offsets( sqlite3_context *pCtx, /* SQLite function call context */ Fts3Cursor *pCsr /* Cursor object */ ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; | < < | 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 | */ void sqlite3Fts3Offsets( sqlite3_context *pCtx, /* SQLite function call context */ Fts3Cursor *pCsr /* Cursor object */ ){ Fts3Table *pTab = (Fts3Table *)pCsr->base.pVtab; sqlite3_tokenizer_module const *pMod = pTab->pTokenizer->pModule; int rc; /* Return Code */ int nToken; /* Number of tokens in query */ int iCol; /* Column currently being processed */ StrBuffer res = {0, 0, 0}; /* Result string */ TermOffsetCtx sCtx; /* Context for fts3ExprTermOffsetInit() */ if( !pCsr->pExpr ){ |
︙ | ︙ | |||
1363 1364 1365 1366 1367 1368 1369 | sCtx.pCsr = pCsr; /* Loop through the table columns, appending offset information to ** string-buffer res for each column. */ for(iCol=0; iCol<pTab->nColumn; iCol++){ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ | > > | | | | 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 | sCtx.pCsr = pCsr; /* Loop through the table columns, appending offset information to ** string-buffer res for each column. */ for(iCol=0; iCol<pTab->nColumn; iCol++){ sqlite3_tokenizer_cursor *pC; /* Tokenizer cursor */ const char *ZDUMMY; /* Dummy argument used with xNext() */ int NDUMMY = 0; /* Dummy argument used with xNext() */ int iStart = 0; int iEnd = 0; int iCurrent = 0; const char *zDoc; int nDoc; /* Initialize the contents of sCtx.aTerm[] for column iCol. There is ** no way that this operation can fail, so the return code from ** fts3ExprIterate() can be discarded. */ |
︙ | ︙ |
Changes to ext/fts3/fts3_tokenizer.c.
︙ | ︙ | |||
247 248 249 250 251 252 253 | int nName; const char *zInput; int nInput; const char *azArg[64]; const char *zToken; | | | | | | 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | int nName; const char *zInput; int nInput; const char *azArg[64]; const char *zToken; int nToken = 0; int iStart = 0; int iEnd = 0; int iPos = 0; int i; Tcl_Obj *pRet; if( argc<2 ){ sqlite3_result_error(context, "insufficient arguments", -1); return; |
︙ | ︙ |
Changes to ext/fts3/fts3_write.c.
︙ | ︙ | |||
772 773 774 775 776 777 778 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ static int fts3PendingTermsAdd( Fts3Table *p, /* Table into which text will be inserted */ int iLangid, /* Language id to use */ const char *zText, /* Text of document to be inserted */ int iCol, /* Column into which text is being inserted */ | | | | | | | 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | ** If successful, SQLITE_OK is returned. Otherwise, an SQLite error code. */ static int fts3PendingTermsAdd( Fts3Table *p, /* Table into which text will be inserted */ int iLangid, /* Language id to use */ const char *zText, /* Text of document to be inserted */ int iCol, /* Column into which text is being inserted */ u32 *pnWord /* IN/OUT: Incr. by number tokens inserted */ ){ int rc; int iStart = 0; int iEnd = 0; int iPos = 0; int nWord = 0; char const *zToken; int nToken = 0; sqlite3_tokenizer *pTokenizer = p->pTokenizer; sqlite3_tokenizer_module const *pModule = pTokenizer->pModule; sqlite3_tokenizer_cursor *pCsr; int (*xNext)(sqlite3_tokenizer_cursor *pCursor, const char**,int*,int*,int*,int*); |
︙ | ︙ | |||
836 837 838 839 840 841 842 | rc = fts3PendingTermsAddOne( p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix ); } } pModule->xClose(pCsr); | | | 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | rc = fts3PendingTermsAddOne( p, iCol, iPos, &pIndex->hPending, zToken, pIndex->nPrefix ); } } pModule->xClose(pCsr); *pnWord += nWord; return (rc==SQLITE_DONE ? SQLITE_OK : rc); } /* ** Calling this function indicates that subsequent calls to ** fts3PendingTermsAdd() are to add term/position-list pairs for the ** contents of the document with docid iDocid. |
︙ | ︙ | |||
1040 1041 1042 1043 1044 1045 1046 | ** (an integer) of a row about to be deleted. Remove all terms from the ** full-text index. */ static void fts3DeleteTerms( int *pRC, /* Result code */ Fts3Table *p, /* The FTS table to delete from */ sqlite3_value *pRowid, /* The docid to be deleted */ | | > > > | 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 | ** (an integer) of a row about to be deleted. Remove all terms from the ** full-text index. */ static void fts3DeleteTerms( int *pRC, /* Result code */ Fts3Table *p, /* The FTS table to delete from */ sqlite3_value *pRowid, /* The docid to be deleted */ u32 *aSz, /* Sizes of deleted document written here */ int *pbFound /* OUT: Set to true if row really does exist */ ){ int rc; sqlite3_stmt *pSelect; assert( *pbFound==0 ); if( *pRC ) return; rc = fts3SqlStmt(p, SQL_SELECT_CONTENT_BY_ROWID, &pSelect, &pRowid); if( rc==SQLITE_OK ){ if( SQLITE_ROW==sqlite3_step(pSelect) ){ int i; int iLangid = langidFromSelect(p, pSelect); rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pSelect, 0)); for(i=1; rc==SQLITE_OK && i<=p->nColumn; i++){ const char *zText = (const char *)sqlite3_column_text(pSelect, i); rc = fts3PendingTermsAdd(p, iLangid, zText, -1, &aSz[i-1]); aSz[p->nColumn] += sqlite3_column_bytes(pSelect, i); } if( rc!=SQLITE_OK ){ sqlite3_reset(pSelect); *pRC = rc; return; } *pbFound = 1; } rc = sqlite3_reset(pSelect); }else{ sqlite3_reset(pSelect); } *pRC = rc; } |
︙ | ︙ | |||
3286 3287 3288 3289 3290 3291 3292 | } } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); | | | 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 | } } while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){ int iCol; int iLangid = langidFromSelect(p, pStmt); rc = fts3PendingTermsDocid(p, iLangid, sqlite3_column_int64(pStmt, 0)); memset(aSz, 0, sizeof(aSz[0]) * (p->nColumn+1)); for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){ const char *z = (const char *) sqlite3_column_text(pStmt, iCol+1); rc = fts3PendingTermsAdd(p, iLangid, z, iCol, &aSz[iCol]); aSz[p->nColumn] += sqlite3_column_bytes(pStmt, iCol+1); } if( p->bHasDocsize ){ fts3InsertDocsize(&rc, p, aSz); |
︙ | ︙ | |||
4930 4931 4932 4933 4934 4935 4936 | const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); int nText = sqlite3_column_bytes(pStmt, iCol+1); sqlite3_tokenizer_cursor *pT = 0; rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ | | | | | 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 | const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1); int nText = sqlite3_column_bytes(pStmt, iCol+1); sqlite3_tokenizer_cursor *pT = 0; rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ int nToken = 0; /* Number of bytes in token */ int iDum1 = 0, iDum2 = 0; /* Dummy variables */ int iPos = 0; /* Position of token in zText */ rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos); if( rc==SQLITE_OK ){ int i; cksum2 = cksum2 ^ fts3ChecksumEntry( zToken, nToken, iLang, 0, iDocid, iCol, iPos ); |
︙ | ︙ | |||
5099 5100 5101 5102 5103 5104 5105 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); sqlite3_tokenizer_cursor *pTC = 0; rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ | | | | | 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 | for(i=0; i<p->nColumn && rc==SQLITE_OK; i++){ const char *zText = (const char *)sqlite3_column_text(pCsr->pStmt, i+1); sqlite3_tokenizer_cursor *pTC = 0; rc = sqlite3Fts3OpenTokenizer(pT, pCsr->iLangid, zText, -1, &pTC); while( rc==SQLITE_OK ){ char const *zToken; /* Buffer containing token */ int nToken = 0; /* Number of bytes in token */ int iDum1 = 0, iDum2 = 0; /* Dummy variables */ int iPos = 0; /* Position of token in zText */ rc = pModule->xNext(pTC, &zToken, &nToken, &iDum1, &iDum2, &iPos); for(pDef=pCsr->pDeferred; pDef && rc==SQLITE_OK; pDef=pDef->pNext){ Fts3PhraseToken *pPT = pDef->pToken; if( (pDef->iCol>=p->nColumn || pDef->iCol==i) && (pPT->bFirst==0 || iPos==0) && (pPT->n==nToken || (pPT->isPrefix && pPT->n<nToken)) |
︙ | ︙ | |||
5190 5191 5192 5193 5194 5195 5196 | ** SQLite value pRowid contains the rowid of a row that may or may not be ** present in the FTS3 table. If it is, delete it and adjust the contents ** of subsiduary data structures accordingly. */ static int fts3DeleteByRowid( Fts3Table *p, sqlite3_value *pRowid, | | > > > > > | | | | | | | | | > | < > | | < < < | | | > | 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 | ** SQLite value pRowid contains the rowid of a row that may or may not be ** present in the FTS3 table. If it is, delete it and adjust the contents ** of subsiduary data structures accordingly. */ static int fts3DeleteByRowid( Fts3Table *p, sqlite3_value *pRowid, int *pnChng, /* IN/OUT: Decrement if row is deleted */ u32 *aSzDel ){ int rc = SQLITE_OK; /* Return code */ int bFound = 0; /* True if *pRowid really is in the table */ fts3DeleteTerms(&rc, p, pRowid, aSzDel, &bFound); if( bFound && rc==SQLITE_OK ){ int isEmpty = 0; /* Deleting *pRowid leaves the table empty */ rc = fts3IsEmpty(p, pRowid, &isEmpty); if( rc==SQLITE_OK ){ if( isEmpty ){ /* Deleting this row means the whole table is empty. In this case ** delete the contents of all three tables and throw away any ** data in the pendingTerms hash table. */ rc = fts3DeleteAll(p, 1); *pnChng = 0; memset(aSzDel, 0, sizeof(u32) * (p->nColumn+1) * 2); }else{ *pnChng = *pnChng - 1; if( p->zContentTbl==0 ){ fts3SqlExec(&rc, p, SQL_DELETE_CONTENT, &pRowid); } if( p->bHasDocsize ){ fts3SqlExec(&rc, p, SQL_DELETE_DOCSIZE, &pRowid); } } } } return rc; } |
︙ | ︙ | |||
5242 5243 5244 5245 5246 5247 5248 | sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ | | | 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 | sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts3Table *p = (Fts3Table *)pVtab; int rc = SQLITE_OK; /* Return Code */ int isRemove = 0; /* True for an UPDATE or DELETE */ u32 *aSzIns = 0; /* Sizes of inserted documents */ u32 *aSzDel = 0; /* Sizes of deleted documents */ int nChng = 0; /* Net change in number of documents */ int bInsertDone = 0; assert( p->pSegments==0 ); assert( nArg==1 /* DELETE operations */ || nArg==(2 + p->nColumn + 3) /* INSERT or UPDATE operations */ |
︙ | ︙ | |||
5270 5271 5272 5273 5274 5275 5276 | if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ rc = SQLITE_CONSTRAINT; goto update_out; } /* Allocate space to hold the change in document sizes */ | | | | | | 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 | if( nArg>1 && sqlite3_value_int(apVal[2 + p->nColumn + 2])<0 ){ rc = SQLITE_CONSTRAINT; goto update_out; } /* Allocate space to hold the change in document sizes */ aSzDel = sqlite3_malloc( sizeof(aSzDel[0])*(p->nColumn+1)*2 ); if( aSzDel==0 ){ rc = SQLITE_NOMEM; goto update_out; } aSzIns = &aSzDel[p->nColumn+1]; memset(aSzDel, 0, sizeof(aSzDel[0])*(p->nColumn+1)*2); /* If this is an INSERT operation, or an UPDATE that modifies the rowid ** value, then this operation requires constraint handling. ** ** If the on-conflict mode is REPLACE, this means that the existing row ** should be deleted from the database before inserting the new row. Or, ** if the on-conflict mode is other than REPLACE, then this method must |
︙ | ︙ | |||
5361 5362 5363 5364 5365 5366 5367 | } if( p->bFts4 ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); } update_out: | | | 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 | } if( p->bFts4 ){ fts3UpdateDocTotals(&rc, p, aSzIns, aSzDel, nChng); } update_out: sqlite3_free(aSzDel); sqlite3Fts3SegmentsClose(p); return rc; } /* ** Flush any data in the pending-terms hash table to disk. If successful, ** merge all segments in the database (including the new segment, if |
︙ | ︙ |
Changes to main.mk.
︙ | ︙ | |||
253 254 255 256 257 258 259 260 261 262 263 264 265 266 | $(TOP)/src/test_osinst.c \ $(TOP)/src/test_pcache.c \ $(TOP)/src/test_quota.c \ $(TOP)/src/test_rtree.c \ $(TOP)/src/test_schema.c \ $(TOP)/src/test_server.c \ $(TOP)/src/test_stat.c \ $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_wholenumber.c \ $(TOP)/src/test_wsd.c | > | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 | $(TOP)/src/test_osinst.c \ $(TOP)/src/test_pcache.c \ $(TOP)/src/test_quota.c \ $(TOP)/src/test_rtree.c \ $(TOP)/src/test_schema.c \ $(TOP)/src/test_server.c \ $(TOP)/src/test_stat.c \ $(TOP)/src/test_sqllog.c \ $(TOP)/src/test_superlock.c \ $(TOP)/src/test_syscall.c \ $(TOP)/src/test_tclvar.c \ $(TOP)/src/test_thread.c \ $(TOP)/src/test_vfs.c \ $(TOP)/src/test_wholenumber.c \ $(TOP)/src/test_wsd.c |
︙ | ︙ | |||
542 543 544 545 546 547 548 | # TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 | # TESTFIXTURE_FLAGS = -DSQLITE_TEST=1 -DSQLITE_CRASH_TEST=1 TESTFIXTURE_FLAGS += -DSQLITE_SERVER=1 -DSQLITE_PRIVATE="" -DSQLITE_CORE testfixture$(EXE): $(TESTSRC2) libsqlite3.a $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TESTSRC2) $(TOP)/src/tclsqlite.c \ -o testfixture$(EXE) $(LIBTCL) libsqlite3.a $(THREADLIB) amalgamation-testfixture$(EXE): sqlite3.c $(TESTSRC) $(TOP)/src/tclsqlite.c $(TCCX) $(TCL_FLAGS) -DTCLSH=1 $(TESTFIXTURE_FLAGS) \ $(TESTSRC) $(TOP)/src/tclsqlite.c sqlite3.c \ -o testfixture$(EXE) $(LIBTCL) $(THREADLIB) fts3-testfixture$(EXE): sqlite3.c fts3amal.c $(TESTSRC) $(TOP)/src/tclsqlite.c |
︙ | ︙ | |||
615 616 617 618 619 620 621 | rm -f testloadext.dll libtestloadext.so rm -f amalgamation-testfixture amalgamation-testfixture.exe rm -f fts3-testfixture fts3-testfixture.exe rm -f testfixture testfixture.exe rm -f threadtest3 threadtest3.exe rm -f sqlite3.c fts?amal.c tclsqlite3.c rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c | | | 616 617 618 619 620 621 622 623 | rm -f testloadext.dll libtestloadext.so rm -f amalgamation-testfixture amalgamation-testfixture.exe rm -f fts3-testfixture fts3-testfixture.exe rm -f testfixture testfixture.exe rm -f threadtest3 threadtest3.exe rm -f sqlite3.c fts?amal.c tclsqlite3.c rm -f sqlite3_analyzer sqlite3_analyzer.exe sqlite3_analyzer.c rm -f sqlite-*-output.vsix |
Changes to src/attach.c.
︙ | ︙ | |||
467 468 469 470 471 472 473 | for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ sqlite3ErrorMsg(pFix->pParse, "%s %T cannot reference objects in database %s", pFix->zType, pFix->pName, pItem->zDatabase); return 1; } | | | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | for(i=0, pItem=pList->a; i<pList->nSrc; i++, pItem++){ if( pItem->zDatabase && sqlite3StrICmp(pItem->zDatabase, zDb) ){ sqlite3ErrorMsg(pFix->pParse, "%s %T cannot reference objects in database %s", pFix->zType, pFix->pName, pItem->zDatabase); return 1; } sqlite3DbFree(pFix->pParse->db, pItem->zDatabase); pItem->zDatabase = 0; pItem->pSchema = pFix->pSchema; #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_TRIGGER) if( sqlite3FixSelect(pFix, pItem->pSelect) ) return 1; if( sqlite3FixExpr(pFix, pItem->pOn) ) return 1; #endif } |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
5740 5741 5742 5743 5744 5745 5746 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ | | | 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 | Pgno pgnoNew; /* Page number of pNew */ assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sqlite3PagerIswriteable(pParent->pDbPage) ); assert( pPage->nOverflow==1 ); /* This error condition is now caught prior to reaching this function */ if( pPage->nCell==0 ) return SQLITE_CORRUPT_BKPT; /* Allocate a new page. This page will become the right-sibling of ** pPage. Make the parent page writable, so that the new divider cell ** may be inserted. If both these operations are successful, proceed. */ rc = allocateBtreePage(pBt, &pNew, &pgnoNew, 0, 0); |
︙ | ︙ | |||
8022 8023 8024 8025 8026 8027 8028 | if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); | | | 8022 8023 8024 8025 8026 8027 8028 8029 8030 8031 8032 8033 8034 8035 8036 | if( !sCheck.aPgRef ){ *pnErr = 1; sqlite3BtreeLeave(p); return 0; } i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH); sCheck.errMsg.useMalloc = 2; /* Check the integrity of the freelist */ checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36]), "Main freelist: "); |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 | ** Note that if an error occurred, it might be the case that ** no VDBE code was generated. */ void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; db = pParse->db; if( db->mallocFailed ) return; if( pParse->nested ) return; if( pParse->nErr ) return; /* Begin by generating some termination code at the end of the ** vdbe program | > | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | ** Note that if an error occurred, it might be the case that ** no VDBE code was generated. */ void sqlite3FinishCoding(Parse *pParse){ sqlite3 *db; Vdbe *v; assert( pParse->pToplevel==0 ); db = pParse->db; if( db->mallocFailed ) return; if( pParse->nested ) return; if( pParse->nErr ) return; /* Begin by generating some termination code at the end of the ** vdbe program |
︙ | ︙ | |||
2686 2687 2688 2689 2690 2691 2692 | /* Figure out how many bytes of space are required to store explicitly ** specified collation sequence names. */ for(i=0; i<pList->nExpr; i++){ Expr *pExpr = pList->a[i].pExpr; if( pExpr ){ | | < < | | 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 | /* Figure out how many bytes of space are required to store explicitly ** specified collation sequence names. */ for(i=0; i<pList->nExpr; i++){ Expr *pExpr = pList->a[i].pExpr; if( pExpr ){ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr); if( pColl ){ nExtra += (1 + sqlite3Strlen30(pColl->zName)); } } } /* ** Allocate the index structure. |
︙ | ︙ | |||
2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 | ** same column more than once cannot be an error because that would ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ const char *zColName = pListItem->zName; Column *pTabCol; int requestedSortOrder; char *zColl; /* Collation sequence name */ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); pParse->checkSchema = 1; goto exit_create_index; } pIndex->aiColumn[i] = j; | > < < < < < | > > | | 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 | ** same column more than once cannot be an error because that would ** break backwards compatibility - it needs to be a warning. */ for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){ const char *zColName = pListItem->zName; Column *pTabCol; int requestedSortOrder; CollSeq *pColl; /* Collating sequence */ char *zColl; /* Collation sequence name */ for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){ if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break; } if( j>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "table %s has no column named %s", pTab->zName, zColName); pParse->checkSchema = 1; goto exit_create_index; } pIndex->aiColumn[i] = j; if( pListItem->pExpr && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0 ){ int nColl; zColl = pColl->zName; nColl = sqlite3Strlen30(zColl) + 1; assert( nExtra>=nColl ); memcpy(zExtra, zColl, nColl); zColl = zExtra; zExtra += nColl; nExtra -= nColl; }else{ |
︙ | ︙ | |||
3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 | ** If iDb<0 then code the OP_Goto only - don't set flag to verify the ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); if( pToplevel->cookieGoto==0 ){ Vdbe *v = sqlite3GetVdbe(pToplevel); if( v==0 ) return; /* This only happens if there was a prior error */ pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; } if( iDb>=0 ){ sqlite3 *db = pToplevel->db; | > > > > > > > > > | 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 | ** If iDb<0 then code the OP_Goto only - don't set flag to verify the ** schema on any databases. This can be used to position the OP_Goto ** early in the code, before we know if any database tables will be used. */ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Parse *pToplevel = sqlite3ParseToplevel(pParse); #ifndef SQLITE_OMIT_TRIGGER if( pToplevel!=pParse ){ /* This branch is taken if a trigger is currently being coded. In this ** case, set cookieGoto to a non-zero value to show that this function ** has been called. This is used by the sqlite3ExprCodeConstants() ** function. */ pParse->cookieGoto = -1; } #endif if( pToplevel->cookieGoto==0 ){ Vdbe *v = sqlite3GetVdbe(pToplevel); if( v==0 ) return; /* This only happens if there was a prior error */ pToplevel->cookieGoto = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0)+1; } if( iDb>=0 ){ sqlite3 *db = pToplevel->db; |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
108 109 110 111 112 113 114 115 116 117 118 119 120 121 | pFrom->a[0].pSelect = pDup; assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); }else{ sqlite3SelectDelete(db, pDup); } pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest); sqlite3SelectDelete(db, pDup); } #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ | > | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | pFrom->a[0].pSelect = pDup; assert( pFrom->a[0].pOn==0 ); assert( pFrom->a[0].pUsing==0 ); }else{ sqlite3SelectDelete(db, pDup); } pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0); if( pDup ) pDup->selFlags |= SF_Materialize; } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest); sqlite3SelectDelete(db, pDup); } #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
27 28 29 30 31 32 33 | ** ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ | > > | | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | ** ** CREATE TABLE t1(a); ** SELECT * FROM t1 WHERE a; ** SELECT a AS b FROM t1 WHERE b; ** SELECT * FROM t1 WHERE (select a from t1); */ char sqlite3ExprAffinity(Expr *pExpr){ int op; pExpr = sqlite3ExprSkipCollate(pExpr); op = pExpr->op; if( op==TK_SELECT ){ assert( pExpr->flags&EP_xIsSelect ); return sqlite3ExprAffinity(pExpr->x.pSelect->pEList->a[0].pExpr); } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); |
︙ | ︙ | |||
52 53 54 55 56 57 58 | assert( pExpr->pTab && j<pExpr->pTab->nCol ); return pExpr->pTab->aCol[j].affinity; } return pExpr->affinity; } /* | | | > > > > | > > | | | > > > > > > > > > > > > > > > > > > > > | < | > | | > > | < < < | < < | > > > > > | > > > > > > > | < < < < < < < < < < | < > | > | | < < | < | > > > > > > < | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | assert( pExpr->pTab && j<pExpr->pTab->nCol ); return pExpr->pTab->aCol[j].affinity; } return pExpr->affinity; } /* ** Set the collating sequence for expression pExpr to be the collating ** sequence named by pToken. Return a pointer to a new Expr node that ** implements the COLLATE operator. ** ** If a memory allocation error occurs, that fact is recorded in pParse->db ** and the pExpr parameter is returned unchanged. */ Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr *pExpr, Token *pCollName){ if( pCollName->n>0 ){ Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1); if( pNew ){ pNew->pLeft = pExpr; pNew->flags |= EP_Collate; pExpr = pNew; } } return pExpr; } Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, const char *zC){ Token s; assert( zC!=0 ); s.z = zC; s.n = sqlite3Strlen30(s.z); return sqlite3ExprAddCollateToken(pParse, pExpr, &s); } /* ** Skip over any TK_COLLATE and/or TK_AS operators at the root of ** an expression. */ Expr *sqlite3ExprSkipCollate(Expr *pExpr){ while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ pExpr = pExpr->pLeft; } return pExpr; } /* ** Return the collation sequence for the expression pExpr. If ** there is no defined collating sequence, return NULL. ** ** The collating sequence might be determined by a COLLATE operator ** or by the presence of a column with a defined collating sequence. ** COLLATE operators take first precedence. Left operands take ** precedence over right operands. */ CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){ sqlite3 *db = pParse->db; CollSeq *pColl = 0; Expr *p = pExpr; while( p ){ int op = p->op; if( op==TK_CAST || op==TK_UPLUS ){ p = p->pLeft; continue; } assert( op!=TK_REGISTER || p->op2!=TK_COLLATE ); if( op==TK_COLLATE ){ if( db->init.busy ){ /* Do not report errors when parsing while the schema */ pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0); }else{ pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken); } break; } if( p->pTab!=0 && (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER || op==TK_TRIGGER) ){ /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally ** a TK_COLUMN but was previously evaluated and cached in a register */ int j = p->iColumn; if( j>=0 ){ const char *zColl = p->pTab->aCol[j].zColl; pColl = sqlite3FindCollSeq(db, ENC(db), zColl, 0); } break; } if( p->flags & EP_Collate ){ if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ p = p->pRight; } }else{ break; } } if( sqlite3CheckCollSeq(pParse, pColl) ){ pColl = 0; } return pColl; } |
︙ | ︙ | |||
215 216 217 218 219 220 221 | CollSeq *sqlite3BinaryCompareCollSeq( Parse *pParse, Expr *pLeft, Expr *pRight ){ CollSeq *pColl; assert( pLeft ); | | < | | < | | 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 | CollSeq *sqlite3BinaryCompareCollSeq( Parse *pParse, Expr *pLeft, Expr *pRight ){ CollSeq *pColl; assert( pLeft ); if( pLeft->flags & EP_Collate ){ pColl = sqlite3ExprCollSeq(pParse, pLeft); }else if( pRight && (pRight->flags & EP_Collate)!=0 ){ pColl = sqlite3ExprCollSeq(pParse, pRight); }else{ pColl = sqlite3ExprCollSeq(pParse, pLeft); if( !pColl ){ pColl = sqlite3ExprCollSeq(pParse, pRight); } } return pColl; |
︙ | ︙ | |||
450 451 452 453 454 455 456 | if( pRoot==0 ){ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); sqlite3ExprDelete(db, pRight); }else{ if( pRight ){ pRoot->pRight = pRight; | < | < < < | < < | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | if( pRoot==0 ){ assert( db->mallocFailed ); sqlite3ExprDelete(db, pLeft); sqlite3ExprDelete(db, pRight); }else{ if( pRight ){ pRoot->pRight = pRight; pRoot->flags |= EP_Collate & pRight->flags; } if( pLeft ){ pRoot->pLeft = pLeft; pRoot->flags |= EP_Collate & pLeft->flags; } exprSetHeight(pRoot); } } /* ** Allocate a Expr node which joins as many as two subtrees. |
︙ | ︙ | |||
718 719 720 721 722 723 724 | if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( (p->flags2 & EP2_MallocedToken)==0 ); assert( (p->flags2 & EP2_Irreducible)==0 ); | | | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 | if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; }else{ assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasProperty(p, EP_FromJoin) ); assert( (p->flags2 & EP2_MallocedToken)==0 ); assert( (p->flags2 & EP2_Irreducible)==0 ); if( p->pLeft || p->pRight || p->x.pList ){ nSize = EXPR_REDUCEDSIZE | EP_Reduced; }else{ nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; } } return nSize; } |
︙ | ︙ | |||
935 936 937 938 939 940 941 942 943 944 945 946 947 948 | pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; pNewItem->isCorrelated = pOldItem->isCorrelated; pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); pNewItem->notIndexed = pOldItem->notIndexed; pNewItem->pIndex = pOldItem->pIndex; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; } | > | 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 | pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; pNewItem->isCorrelated = pOldItem->isCorrelated; pNewItem->viaCoroutine = pOldItem->viaCoroutine; pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); pNewItem->notIndexed = pOldItem->notIndexed; pNewItem->pIndex = pOldItem->pIndex; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; } |
︙ | ︙ | |||
2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 | testcase( regFree2==0 ); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); break; } case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } case TK_TRIGGER: { /* If the opcode is TK_TRIGGER, then the expression is a reference | > | 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 | testcase( regFree2==0 ); codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2); sqlite3VdbeAddOp3(v, OP_And, r3, r4, target); sqlite3ReleaseTempReg(pParse, r3); sqlite3ReleaseTempReg(pParse, r4); break; } case TK_COLLATE: case TK_UPLUS: { inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); break; } case TK_TRIGGER: { /* If the opcode is TK_TRIGGER, then the expression is a reference |
︙ | ︙ | |||
3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 | case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; case TK_AGG_FUNCTION: case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pFarg; /* List of function arguments */ if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; | > > > > > > | 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 | case TK_UMINUS: zUniOp = "UMINUS"; break; case TK_UPLUS: zUniOp = "UPLUS"; break; case TK_BITNOT: zUniOp = "BITNOT"; break; case TK_NOT: zUniOp = "NOT"; break; case TK_ISNULL: zUniOp = "ISNULL"; break; case TK_NOTNULL: zUniOp = "NOTNULL"; break; case TK_COLLATE: { sqlite3ExplainExpr(pOut, pExpr->pLeft); sqlite3ExplainPrintf(pOut,".COLLATE(%s)",pExpr->u.zToken); break; } case TK_AGG_FUNCTION: case TK_CONST_FUNC: case TK_FUNCTION: { ExprList *pFarg; /* List of function arguments */ if( ExprHasAnyProperty(pExpr, EP_TokenOnly) ){ pFarg = 0; |
︙ | ︙ | |||
3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 | static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ case TK_IN: case TK_REGISTER: { return WRC_Prune; } case TK_FUNCTION: case TK_AGG_FUNCTION: case TK_CONST_FUNC: { /* The arguments to a function have a fixed destination. ** Mark them this way to avoid generated unneeded OP_SCopy ** instructions. */ | > > > | 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 | static int evalConstExpr(Walker *pWalker, Expr *pExpr){ Parse *pParse = pWalker->pParse; switch( pExpr->op ){ case TK_IN: case TK_REGISTER: { return WRC_Prune; } case TK_COLLATE: { return WRC_Continue; } case TK_FUNCTION: case TK_AGG_FUNCTION: case TK_CONST_FUNC: { /* The arguments to a function have a fixed destination. ** Mark them this way to avoid generated unneeded OP_SCopy ** instructions. */ |
︙ | ︙ | |||
3349 3350 3351 3352 3353 3354 3355 | } } break; } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; | < | > | > > | 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 | } } break; } } if( isAppropriateForFactoring(pExpr) ){ int r1 = ++pParse->nMem; int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1); /* If r2!=r1, it means that register r1 is never used. That is harmless ** but suboptimal, so we want to know about the situation to fix it. ** Hence the following assert: */ assert( r2==r1 ); pExpr->op2 = pExpr->op; pExpr->op = TK_REGISTER; pExpr->iTable = r2; return WRC_Prune; } return WRC_Continue; } |
︙ | ︙ | |||
3768 3769 3770 3771 3772 3773 3774 | } assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 2; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; | | > > > > > > > > | < < | 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 | } assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 2; } if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2; if( pA->op!=pB->op ){ if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB)<2 ){ return 1; } if( pB->op==TK_COLLATE && sqlite3ExprCompare(pA, pB->pLeft)<2 ){ return 1; } return 2; } if( sqlite3ExprCompare(pA->pLeft, pB->pLeft) ) return 2; if( sqlite3ExprCompare(pA->pRight, pB->pRight) ) return 2; if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList) ) return 2; if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 2; if( ExprHasProperty(pA, EP_IntValue) ){ if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ return 2; } }else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){ if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2; if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){ return pA->op==TK_COLLATE ? 1 : 2; } } return 0; } /* ** Compare two ExprList objects. Return 0 if they are identical and ** non-zero if they differ in any way. ** |
︙ | ︙ | |||
4025 4026 4027 4028 4029 4030 4031 | } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(pExpr); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; | > | | > | | > | | 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 | } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); ExprSetIrreducible(pExpr); pExpr->iAgg = (i16)i; pExpr->pAggInfo = pAggInfo; return WRC_Prune; }else{ return WRC_Continue; } } } return WRC_Continue; } static int analyzeAggregatesInSelect(Walker *pWalker, Select *pSelect){ UNUSED_PARAMETER(pWalker); UNUSED_PARAMETER(pSelect); return WRC_Continue; } /* ** Analyze the pExpr expression looking for aggregate functions and ** for variables that need to be added to AggInfo object that pNC->pAggInfo ** points to. Additional entries are made on the AggInfo object as ** necessary. ** ** This routine should only be called after the expression has been ** analyzed by sqlite3ResolveExprNames(). */ void sqlite3ExprAnalyzeAggregates(NameContext *pNC, Expr *pExpr){ Walker w; memset(&w, 0, sizeof(w)); |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
507 508 509 510 511 512 513 514 515 516 517 518 | pLeft = sqlite3Expr(db, TK_REGISTER, 0); if( pLeft ){ /* Set the collation sequence and affinity of the LHS of each TK_EQ ** expression to the parent key column defaults. */ if( pIdx ){ Column *pCol; iCol = pIdx->aiColumn[i]; pCol = &pTab->aCol[iCol]; if( pTab->iPKey==iCol ) iCol = -1; pLeft->iTable = regData+iCol+1; pLeft->affinity = pCol->affinity; | > | > > | 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | pLeft = sqlite3Expr(db, TK_REGISTER, 0); if( pLeft ){ /* Set the collation sequence and affinity of the LHS of each TK_EQ ** expression to the parent key column defaults. */ if( pIdx ){ Column *pCol; const char *zColl; iCol = pIdx->aiColumn[i]; pCol = &pTab->aCol[iCol]; if( pTab->iPKey==iCol ) iCol = -1; pLeft->iTable = regData+iCol+1; pLeft->affinity = pCol->affinity; zColl = pCol->zColl; if( zColl==0 ) zColl = db->pDfltColl->zName; pLeft = sqlite3ExprAddCollateString(pParse, pLeft, zColl); }else{ pLeft->iTable = regData; pLeft->affinity = SQLITE_AFF_INTEGER; } } iCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom; assert( iCol>=0 ); |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
163 164 165 166 167 168 169 170 171 172 173 174 175 176 | double rVal = sqlite3_value_double(argv[0]); if( rVal<0 ) rVal = -rVal; sqlite3_result_double(context, rVal); break; } } } /* ** Implementation of the substr() function. ** ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. ** p1 is 1-indexed. So substr(x,1,1) returns the first character ** of x. If x is text, then we actually count UTF-8 characters. | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 | double rVal = sqlite3_value_double(argv[0]); if( rVal<0 ) rVal = -rVal; sqlite3_result_double(context, rVal); break; } } } /* ** Implementation of the instr() function. ** ** instr(haystack,needle) finds the first occurrence of needle ** in haystack and returns the number of previous characters plus 1, ** or 0 if needle does not occur within haystack. ** ** If both haystack and needle are BLOBs, then the result is one more than ** the number of bytes in haystack prior to the first occurrence of needle, ** or 0 if needle never occurs in haystack. */ static void instrFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *zHaystack; const unsigned char *zNeedle; int nHaystack; int nNeedle; int typeHaystack, typeNeedle; int N = 1; int isText; UNUSED_PARAMETER(argc); typeHaystack = sqlite3_value_type(argv[0]); typeNeedle = sqlite3_value_type(argv[1]); if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return; nHaystack = sqlite3_value_bytes(argv[0]); nNeedle = sqlite3_value_bytes(argv[1]); if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){ zHaystack = sqlite3_value_blob(argv[0]); zNeedle = sqlite3_value_blob(argv[1]); isText = 0; }else{ zHaystack = sqlite3_value_text(argv[0]); zNeedle = sqlite3_value_text(argv[1]); isText = 1; } while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){ N++; do{ nHaystack--; zHaystack++; }while( isText && (zHaystack[0]&0xc0)==0x80 ); } if( nNeedle>nHaystack ) N = 0; sqlite3_result_int(context, N); } /* ** Implementation of the substr() function. ** ** substr(x,p1,p2) returns p2 characters of x[] beginning with p1. ** p1 is 1-indexed. So substr(x,1,1) returns the first character ** of x. If x is text, then we actually count UTF-8 characters. |
︙ | ︙ | |||
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 | FUNCTION(min, 0, 0, 1, 0 ), AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), #endif | > | 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 | FUNCTION(min, 0, 0, 1, 0 ), AGGREGATE(min, 1, 0, 1, minmaxStep, minMaxFinalize ), FUNCTION(max, -1, 1, 1, minmaxFunc ), FUNCTION(max, 0, 1, 1, 0 ), AGGREGATE(max, 1, 1, 1, minmaxStep, minMaxFinalize ), FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF), FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH), FUNCTION(instr, 2, 0, 0, instrFunc ), FUNCTION(substr, 2, 0, 0, substrFunc ), FUNCTION(substr, 3, 0, 0, substrFunc ), FUNCTION(abs, 1, 0, 0, absFunc ), #ifndef SQLITE_OMIT_FLOATING_POINT FUNCTION(round, 1, 0, 0, roundFunc ), FUNCTION(round, 2, 0, 0, roundFunc ), #endif |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
171 172 173 174 175 176 177 178 179 180 181 182 183 184 | 0, /* isMallocInit */ 0, /* isPCacheInit */ 0, /* pInitMutex */ 0, /* nRefInitMutex */ 0, /* xLog */ 0, /* pLogArg */ 0, /* bLocaltimeFault */ }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. | > > > > | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | 0, /* isMallocInit */ 0, /* isPCacheInit */ 0, /* pInitMutex */ 0, /* nRefInitMutex */ 0, /* xLog */ 0, /* pLogArg */ 0, /* bLocaltimeFault */ #ifdef SQLITE_ENABLE_SQLLOG 0, /* xSqllog */ 0 /* pSqllogArg */ #endif }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. |
︙ | ︙ |
Changes to src/hash.c.
︙ | ︙ | |||
189 190 191 192 193 194 195 | pEntry->chain = elem->next; } pEntry->count--; assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; | | | 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | pEntry->chain = elem->next; } pEntry->count--; assert( pEntry->count>=0 ); } sqlite3_free( elem ); pH->count--; if( pH->count==0 ){ assert( pH->first==0 ); assert( pH->count==0 ); sqlite3HashClear(pH); } } /* Attempt to locate an element of the hash table pH with a key |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite3.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | Parse *p, /* Generate code into this VDBE */ int iCur, /* The cursor number of the table */ int iDb, /* The database index in sqlite3.aDb[] */ Table *pTab, /* The table to be opened */ int opcode /* OP_OpenRead or OP_OpenWrite */ ){ Vdbe *v; assert( !IsVirtual(pTab) ); v = sqlite3GetVdbe(p); assert( opcode==OP_OpenWrite || opcode==OP_OpenRead ); sqlite3TableLock(p, iDb, pTab->tnum, (opcode==OP_OpenWrite)?1:0, pTab->zName); sqlite3VdbeAddOp3(v, opcode, iCur, pTab->tnum, iDb); sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(pTab->nCol), P4_INT32); VdbeComment((v, "%s", pTab->zName)); } |
︙ | ︙ | |||
1270 1271 1272 1273 1274 1275 1276 | #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); | < < < | | | | | | | | | | | | | | < < | 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 | #ifndef SQLITE_OMIT_CHECK if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){ ExprList *pCheck = pTab->pCheck; pParse->ckBase = regData; onError = overrideError!=OE_Default ? overrideError : OE_Abort; for(i=0; i<pCheck->nExpr; i++){ int allOk = sqlite3VdbeMakeLabel(v); sqlite3ExprIfTrue(pParse, pCheck->a[i].pExpr, allOk, SQLITE_JUMPIFNULL); if( onError==OE_Ignore ){ sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest); }else{ char *zConsName = pCheck->a[i].zName; if( onError==OE_Replace ) onError = OE_Abort; /* IMP: R-15569-63625 */ if( zConsName ){ zConsName = sqlite3MPrintf(db, "constraint %s failed", zConsName); }else{ zConsName = 0; } sqlite3HaltConstraint(pParse, onError, zConsName, P4_DYNAMIC); } sqlite3VdbeResolveLabel(v, allOk); } } #endif /* !defined(SQLITE_OMIT_CHECK) */ /* If we have an INTEGER PRIMARY KEY, make sure the primary key ** of the new record does not previously exist. Except, if this ** is an UPDATE and the primary key is not changing, that is OK. |
︙ | ︙ |
Changes to src/journal.c.
︙ | ︙ | |||
223 224 225 226 227 228 229 230 231 232 233 234 235 236 | */ int sqlite3JournalCreate(sqlite3_file *p){ if( p->pMethods!=&JournalFileMethods ){ return SQLITE_OK; } return createFile((JournalFile *)p); } /* ** Return the number of bytes required to store a JournalFile that uses vfs ** pVfs to create the underlying on-disk files. */ int sqlite3JournalSize(sqlite3_vfs *pVfs){ return (pVfs->szOsFile+sizeof(JournalFile)); | > > > > > > > > > > | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | */ int sqlite3JournalCreate(sqlite3_file *p){ if( p->pMethods!=&JournalFileMethods ){ return SQLITE_OK; } return createFile((JournalFile *)p); } /* ** The file-handle passed as the only argument is guaranteed to be an open ** file. It may or may not be of class JournalFile. If the file is a ** JournalFile, and the underlying file on disk has not yet been opened, ** return 0. Otherwise, return 1. */ int sqlite3JournalExists(sqlite3_file *p){ return (p->pMethods!=&JournalFileMethods || ((JournalFile *)p)->pReal!=0); } /* ** Return the number of bytes required to store a JournalFile that uses vfs ** pVfs to create the underlying on-disk files. */ int sqlite3JournalSize(sqlite3_vfs *pVfs){ return (pVfs->szOsFile+sizeof(JournalFile)); |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
127 128 129 130 131 132 133 134 135 136 137 138 139 140 | /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end ** of this routine. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; /* Make sure the mutex subsystem is initialized. If unable to ** initialize the mutex subsystem, return early with the error. ** If the system is so sick that we are unable to allocate a mutex, ** there is not much SQLite is going to be able to do. ** ** The mutex subsystem must take care of serializing its own | > > > > > > > | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | /* If SQLite is already completely initialized, then this call ** to sqlite3_initialize() should be a no-op. But the initialization ** must be complete. So isInit must not be set until the very end ** of this routine. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_OK; #ifdef SQLITE_ENABLE_SQLLOG { extern void sqlite3_init_sqllog(void); sqlite3_init_sqllog(); } #endif /* Make sure the mutex subsystem is initialized. If unable to ** initialize the mutex subsystem, return early with the error. ** If the system is so sick that we are unable to allocate a mutex, ** there is not much SQLite is going to be able to do. ** ** The mutex subsystem must take care of serializing its own |
︙ | ︙ | |||
475 476 477 478 479 480 481 482 483 484 485 486 487 488 | break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } default: { rc = SQLITE_ERROR; break; } } va_end(ap); | > > > > > > > > > | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 | break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { sqlite3GlobalConfig.bUseCis = va_arg(ap, int); break; } #ifdef SQLITE_ENABLE_SQLLOG case SQLITE_CONFIG_SQLLOG: { typedef void(*SQLLOGFUNC_t)(void*, sqlite3*, const char*, int); sqlite3GlobalConfig.xSqllog = va_arg(ap, SQLLOGFUNC_t); sqlite3GlobalConfig.pSqllogArg = va_arg(ap, void *); break; } #endif default: { rc = SQLITE_ERROR; break; } } va_end(ap); |
︙ | ︙ | |||
814 815 816 817 818 819 820 821 822 823 824 825 826 827 | */ if( !forceZombie && connectionIsBusy(db) ){ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } /* Convert the connection into a zombie and then close it. */ db->magic = SQLITE_MAGIC_ZOMBIE; sqlite3LeaveMutexAndCloseZombie(db); return SQLITE_OK; } | > > > > > > > | 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 | */ if( !forceZombie && connectionIsBusy(db) ){ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); sqlite3_mutex_leave(db->mutex); return SQLITE_BUSY; } #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ /* Closing the handle. Fourth parameter is passed the value 2. */ sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2); } #endif /* Convert the connection into a zombie and then close it. */ db->magic = SQLITE_MAGIC_ZOMBIE; sqlite3LeaveMutexAndCloseZombie(db); return SQLITE_OK; } |
︙ | ︙ | |||
2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 | if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; return sqlite3ApiExit(0, rc); } /* ** Open a new database handle. */ int sqlite3_open( | > > > > > > > | 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 | if( rc==SQLITE_NOMEM ){ sqlite3_close(db); db = 0; }else if( rc!=SQLITE_OK ){ db->magic = SQLITE_MAGIC_SICK; } *ppDb = db; #ifdef SQLITE_ENABLE_SQLLOG if( sqlite3GlobalConfig.xSqllog ){ /* Opening a db handle. Fourth parameter is passed 0. */ void *pArg = sqlite3GlobalConfig.pSqllogArg; sqlite3GlobalConfig.xSqllog(pArg, db, zFilename, 0); } #endif return sqlite3ApiExit(0, rc); } /* ** Open a new database handle. */ int sqlite3_open( |
︙ | ︙ | |||
3015 3016 3017 3018 3019 3020 3021 | ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); | | | 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 | ** operation N should be 0. The idea is that a test program (like the ** SQL Logic Test or SLT test module) can run the same SQL multiple times ** with various optimizations disabled to verify that the same answer ** is obtained in every case. */ case SQLITE_TESTCTRL_OPTIMIZATIONS: { sqlite3 *db = va_arg(ap, sqlite3*); db->dbOptFlags = (u16)(va_arg(ap, int) & 0xffff); break; } #ifdef SQLITE_N_KEYWORD /* sqlite3_test_control(SQLITE_TESTCTRL_ISKEYWORD, const char *zWord) ** ** If zWord is a keyword recognized by the parser, then return the |
︙ | ︙ |
Changes to src/os_unix.c.
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), ** 2. No locking, ** 3. Dot-file locking, | > > > > > > > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | ** * Locking primitives for the proxy uber-locking-method. (MacOSX only) ** * Definitions of sqlite3_vfs objects for all locking methods ** plus implementations of sqlite3_os_init() and sqlite3_os_end(). */ #include "sqliteInt.h" #if SQLITE_OS_UNIX /* This file is used on unix only */ /* Use posix_fallocate() if it is available */ #if !defined(HAVE_POSIX_FALLOCATE) \ && (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L) # define HAVE_POSIX_FALLOCATE 1 #endif /* ** There are various methods for file locking used for concurrency ** control: ** ** 1. POSIX locking (the default), ** 2. No locking, ** 3. Dot-file locking, |
︙ | ︙ | |||
214 215 216 217 218 219 220 221 222 223 224 225 226 227 | unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS | > > > > | 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ int lastErrno; /* The unix errno from last I/O error */ void *lockingContext; /* Locking style specific state */ UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ const char *zPath; /* Name of the file */ unixShm *pShm; /* Shared memory segment information */ int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ #ifdef __QNXNTO__ int sectorSize; /* Device sector size */ int deviceCharacteristics; /* Precomputed device characteristics */ #endif #if SQLITE_ENABLE_LOCKING_STYLE int openFlags; /* The flags specified at open() */ #endif #if SQLITE_ENABLE_LOCKING_STYLE || defined(__APPLE__) unsigned fsFlags; /* cached details from statfs() */ #endif #if OS_VXWORKS |
︙ | ︙ | |||
3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 | }else if( (*pArg)==0 ){ pFile->ctrlFlags &= ~mask; }else{ pFile->ctrlFlags |= mask; } } /* ** Information and control of an open file handle. */ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ unixFile *pFile = (unixFile*)id; switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { | > > > | 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 | }else if( (*pArg)==0 ){ pFile->ctrlFlags &= ~mask; }else{ pFile->ctrlFlags |= mask; } } /* Forward declaration */ static int unixGetTempname(int nBuf, char *zBuf); /* ** Information and control of an open file handle. */ static int unixFileControl(sqlite3_file *id, int op, void *pArg){ unixFile *pFile = (unixFile*)id; switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { |
︙ | ︙ | |||
3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 | unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg); return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); return SQLITE_OK; } #ifdef SQLITE_DEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and ** it hence it is OK for the transaction change counter to be ** unchanged. */ case SQLITE_FCNTL_DB_UNCHANGED: { | > > > > > > > > | 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 | unixModeBit(pFile, UNIXFILE_PSOW, (int*)pArg); return SQLITE_OK; } case SQLITE_FCNTL_VFSNAME: { *(char**)pArg = sqlite3_mprintf("%s", pFile->pVfs->zName); return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname ); if( zTFile ){ unixGetTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; } return SQLITE_OK; } #ifdef SQLITE_DEBUG /* The pager calls this method to signal that it has done ** a rollback and that the database is therefore unchanged and ** it hence it is OK for the transaction change counter to be ** unchanged. */ case SQLITE_FCNTL_DB_UNCHANGED: { |
︙ | ︙ | |||
3634 3635 3636 3637 3638 3639 3640 | ** larger for some devices. ** ** SQLite code assumes this function cannot fail. It also assumes that ** if two files are created in the same file-system directory (i.e. ** a database and its journal file) that the sector size will be the ** same for both. */ | > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | < < > | 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 | ** larger for some devices. ** ** SQLite code assumes this function cannot fail. It also assumes that ** if two files are created in the same file-system directory (i.e. ** a database and its journal file) that the sector size will be the ** same for both. */ #ifndef __QNXNTO__ static int unixSectorSize(sqlite3_file *NotUsed){ UNUSED_PARAMETER(NotUsed); return SQLITE_DEFAULT_SECTOR_SIZE; } #endif /* ** The following version of unixSectorSize() is optimized for QNX. */ #ifdef __QNXNTO__ #include <sys/dcmd_blk.h> #include <sys/statvfs.h> static int unixSectorSize(sqlite3_file *id){ unixFile *pFile = (unixFile*)id; if( pFile->sectorSize == 0 ){ struct statvfs fsInfo; /* Set defaults for non-supported filesystems */ pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; pFile->deviceCharacteristics = 0; if( fstatvfs(pFile->h, &fsInfo) == -1 ) { return pFile->sectorSize; } if( !strcmp(fsInfo.f_basetype, "tmp") ) { pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = SQLITE_IOCAP_ATOMIC4K | /* All ram filesystem writes are atomic */ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until ** the write succeeds */ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else if( strstr(fsInfo.f_basetype, "etfs") ){ pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = /* etfs cluster size writes are atomic */ (pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) | SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until ** the write succeeds */ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else if( !strcmp(fsInfo.f_basetype, "qnx6") ){ pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = SQLITE_IOCAP_ATOMIC | /* All filesystem writes are atomic */ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until ** the write succeeds */ SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else if( !strcmp(fsInfo.f_basetype, "qnx4") ){ pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = /* full bitset of atomics from max sector size and smaller */ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 | SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else if( strstr(fsInfo.f_basetype, "dos") ){ pFile->sectorSize = fsInfo.f_bsize; pFile->deviceCharacteristics = /* full bitset of atomics from max sector size and smaller */ ((pFile->sectorSize / 512 * SQLITE_IOCAP_ATOMIC512) << 1) - 2 | SQLITE_IOCAP_SEQUENTIAL | /* The ram filesystem has no write behind ** so it is ordered */ 0; }else{ pFile->deviceCharacteristics = SQLITE_IOCAP_ATOMIC512 | /* blocks are atomic */ SQLITE_IOCAP_SAFE_APPEND | /* growing the file does not occur until ** the write succeeds */ 0; } } /* Last chance verification. If the sector size isn't a multiple of 512 ** then it isn't valid.*/ if( pFile->sectorSize % 512 != 0 ){ pFile->deviceCharacteristics = 0; pFile->sectorSize = SQLITE_DEFAULT_SECTOR_SIZE; } return pFile->sectorSize; } #endif /* __QNXNTO__ */ /* ** Return the device characteristics for the file. ** ** This VFS is set up to return SQLITE_IOCAP_POWERSAFE_OVERWRITE by default. ** However, that choice is contraversial since technically the underlying ** file system does not always provide powersafe overwrites. (In other ** words, after a power-loss event, parts of the file that were never ** written might end up being altered.) However, non-PSOW behavior is very, ** very rare. And asserting PSOW makes a large reduction in the amount ** of required I/O for journaling, since a lot of padding is eliminated. ** Hence, while POWERSAFE_OVERWRITE is on by default, there is a file-control ** available to turn it off and URI query parameter available to turn it off. */ static int unixDeviceCharacteristics(sqlite3_file *id){ unixFile *p = (unixFile*)id; int rc = 0; #ifdef __QNXNTO__ if( p->sectorSize==0 ) unixSectorSize(id); rc = p->deviceCharacteristics; #endif if( p->ctrlFlags & UNIXFILE_PSOW ){ rc |= SQLITE_IOCAP_POWERSAFE_OVERWRITE; } return rc; } #ifndef SQLITE_OMIT_WAL /* ** Object used to represent an shared memory buffer. |
︙ | ︙ | |||
4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 | /* The requested memory region does not exist. If bExtend is set to ** false, exit early. *pp will be set to NULL and SQLITE_OK returned. ** ** Alternatively, if bExtend is true, use ftruncate() to allocate ** the requested memory region. */ if( !bExtend ) goto shmpage_out; if( robust_ftruncate(pShmNode->h, nByte) ){ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate", pShmNode->zFilename); goto shmpage_out; } } } /* Map the requested memory region into this processes address space. */ apNew = (char **)sqlite3_realloc( pShmNode->apRegion, (iRegion+1)*sizeof(char *) ); | > > > > > > > > | 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 | /* The requested memory region does not exist. If bExtend is set to ** false, exit early. *pp will be set to NULL and SQLITE_OK returned. ** ** Alternatively, if bExtend is true, use ftruncate() to allocate ** the requested memory region. */ if( !bExtend ) goto shmpage_out; #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE if( osFallocate(pShmNode->h, sStat.st_size, nByte)!=0 ){ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "fallocate", pShmNode->zFilename); goto shmpage_out; } #else if( robust_ftruncate(pShmNode->h, nByte) ){ rc = unixLogError(SQLITE_IOERR_SHMSIZE, "ftruncate", pShmNode->zFilename); goto shmpage_out; } #endif } } /* Map the requested memory region into this processes address space. */ apNew = (char **)sqlite3_realloc( pShmNode->apRegion, (iRegion+1)*sizeof(char *) ); |
︙ | ︙ | |||
5280 5281 5282 5283 5284 5285 5286 | sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ const char *zPath, /* Name of file to be deleted */ int dirSync /* If true, fsync() directory after deleting file */ ){ int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); | | > > > | > > | 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 | sqlite3_vfs *NotUsed, /* VFS containing this as the xDelete method */ const char *zPath, /* Name of file to be deleted */ int dirSync /* If true, fsync() directory after deleting file */ ){ int rc = SQLITE_OK; UNUSED_PARAMETER(NotUsed); SimulateIOError(return SQLITE_IOERR_DELETE); if( osUnlink(zPath)==(-1) ){ if( errno==ENOENT ){ rc = SQLITE_IOERR_DELETE_NOENT; }else{ rc = unixLogError(SQLITE_IOERR_DELETE, "unlink", zPath); } return rc; } #ifndef SQLITE_DISABLE_DIRSYNC if( (dirSync & 1)!=0 ){ int fd; rc = osOpenDirectory(zPath, &fd); if( rc==SQLITE_OK ){ #if OS_VXWORKS |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
2188 2189 2190 2191 2192 2193 2194 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ #else if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ #endif if( retryIoerr(&nRetry, &lastErrno) ) continue; break; } | > | | 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 | if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, 0) ){ #else if( !osWriteFile(pFile->h, aRem, nRem, &nWrite, &overlapped) ){ #endif if( retryIoerr(&nRetry, &lastErrno) ) continue; break; } assert( nWrite==0 || nWrite<=(DWORD)nRem ); if( nWrite==0 || nWrite>(DWORD)nRem ){ lastErrno = osGetLastError(); break; } #if !SQLITE_OS_WINCE offset += nWrite; overlapped.Offset = (LONG)(offset & 0xffffffff); overlapped.OffsetHigh = (LONG)((offset>>32) & 0x7fffffff); |
︙ | ︙ | |||
2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 | }else if( (*pArg)==0 ){ pFile->ctrlFlags &= ~mask; }else{ pFile->ctrlFlags |= mask; } } /* ** Control and query of the open file handle. */ static int winFileControl(sqlite3_file *id, int op, void *pArg){ winFile *pFile = (winFile*)id; switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { | > > > | 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 | }else if( (*pArg)==0 ){ pFile->ctrlFlags &= ~mask; }else{ pFile->ctrlFlags |= mask; } } /* Forward declaration */ static int getTempname(int nBuf, char *zBuf); /* ** Control and query of the open file handle. */ static int winFileControl(sqlite3_file *id, int op, void *pArg){ winFile *pFile = (winFile*)id; switch( op ){ case SQLITE_FCNTL_LOCKSTATE: { |
︙ | ︙ | |||
2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 | } if( a[1]>0 ){ win32IoerrRetryDelay = a[1]; }else{ a[1] = win32IoerrRetryDelay; } return SQLITE_OK; } } return SQLITE_NOTFOUND; } /* ** Return the sector size in bytes of the underlying block device for | > > > > > > > > | 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 | } if( a[1]>0 ){ win32IoerrRetryDelay = a[1]; }else{ a[1] = win32IoerrRetryDelay; } return SQLITE_OK; } case SQLITE_FCNTL_TEMPFILENAME: { char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname ); if( zTFile ){ getTempname(pFile->pVfs->mxPathname, zTFile); *(char**)pArg = zTFile; } return SQLITE_OK; } } return SQLITE_NOTFOUND; } /* ** Return the sector size in bytes of the underlying block device for |
︙ | ︙ | |||
3883 3884 3885 3886 3887 3888 3889 | #if SQLITE_OS_WINRT WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, &sAttrData) ){ attr = sAttrData.dwFileAttributes; }else{ | > > > > | > > > > > | > | 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 | #if SQLITE_OS_WINRT WIN32_FILE_ATTRIBUTE_DATA sAttrData; memset(&sAttrData, 0, sizeof(sAttrData)); if ( osGetFileAttributesExW(zConverted, GetFileExInfoStandard, &sAttrData) ){ attr = sAttrData.dwFileAttributes; }else{ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ }else{ rc = SQLITE_ERROR; } break; } #else attr = osGetFileAttributesW(zConverted); #endif if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ }else{ rc = SQLITE_ERROR; } break; } if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ rc = SQLITE_ERROR; /* Files only. */ break; } if ( osDeleteFileW(zConverted) ){ |
︙ | ︙ | |||
3912 3913 3914 3915 3916 3917 3918 | } while(1); } #ifdef SQLITE_WIN32_HAS_ANSI else{ do { attr = osGetFileAttributesA(zConverted); if ( attr==INVALID_FILE_ATTRIBUTES ){ | > > > > | > | | 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 | } while(1); } #ifdef SQLITE_WIN32_HAS_ANSI else{ do { attr = osGetFileAttributesA(zConverted); if ( attr==INVALID_FILE_ATTRIBUTES ){ lastErrno = osGetLastError(); if( lastErrno==ERROR_FILE_NOT_FOUND || lastErrno==ERROR_PATH_NOT_FOUND ){ rc = SQLITE_IOERR_DELETE_NOENT; /* Already gone? */ }else{ rc = SQLITE_ERROR; } break; } if ( attr&FILE_ATTRIBUTE_DIRECTORY ){ rc = SQLITE_ERROR; /* Files only. */ break; } if ( osDeleteFileA(zConverted) ){ rc = SQLITE_OK; /* Deleted OK. */ break; } if ( !retryIoerr(&cnt, &lastErrno) ){ rc = SQLITE_ERROR; /* No more retries. */ break; } } while(1); } #endif if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){ rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename); }else{ logIoerr(cnt); } sqlite3_free(zConverted); OSTRACE(("DELETE \"%s\" %s\n", zFilename, (rc ? "failed" : "ok" ))); |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 | pPager->journalOff = 0; }else{ /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->journalMode==PAGER_JOURNALMODE_WAL ); sqlite3OsClose(pPager->jfd); | > | | 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 | pPager->journalOff = 0; }else{ /* This branch may be executed with Pager.journalMode==MEMORY if ** a hot-journal was just rolled back. In this case the journal ** file should be closed and deleted. If this connection writes to ** the database file, it will do so using an in-memory journal. */ int bDelete = (!pPager->tempFile && sqlite3JournalExists(pPager->jfd)); assert( pPager->journalMode==PAGER_JOURNALMODE_DELETE || pPager->journalMode==PAGER_JOURNALMODE_MEMORY || pPager->journalMode==PAGER_JOURNALMODE_WAL ); sqlite3OsClose(pPager->jfd); if( bDelete ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zJournal, 0); } } } #ifdef SQLITE_CHECK_PAGES sqlite3PcacheIterateDirty(pPager->pPCache, pager_set_pagehash); |
︙ | ︙ | |||
3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 | int isWal; /* True if WAL file exists */ Pgno nPage; /* Size of the database file */ rc = pagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); isWal = 0; }else{ rc = sqlite3OsAccess( pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal ); } if( rc==SQLITE_OK ){ | > | 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 | int isWal; /* True if WAL file exists */ Pgno nPage; /* Size of the database file */ rc = pagerPagecount(pPager, &nPage); if( rc ) return rc; if( nPage==0 ){ rc = sqlite3OsDelete(pPager->pVfs, pPager->zWal, 0); if( rc==SQLITE_IOERR_DELETE_NOENT ) rc = SQLITE_OK; isWal = 0; }else{ rc = sqlite3OsAccess( pPager->pVfs, pPager->zWal, SQLITE_ACCESS_EXISTS, &isWal ); } if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
3480 3481 3482 3483 3484 3485 3486 | pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; if( isOpen(pPager->fd) ){ void **ap = (void **)&pPager->xBusyHandler; assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); assert( ap[1]==pBusyHandlerArg ); | | | 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 | pPager->xBusyHandler = xBusyHandler; pPager->pBusyHandlerArg = pBusyHandlerArg; if( isOpen(pPager->fd) ){ void **ap = (void **)&pPager->xBusyHandler; assert( ((int(*)(void *))(ap[0]))==xBusyHandler ); assert( ap[1]==pBusyHandlerArg ); sqlite3OsFileControlHint(pPager->fd, SQLITE_FCNTL_BUSYHANDLER, (void *)ap); } } /* ** Change the page size used by the Pager object. The new page size ** is passed in *pPageSize. ** |
︙ | ︙ | |||
5881 5882 5883 5884 5885 5886 5887 | #else rc = pager_incr_changecounter(pPager, 0); #endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal | | < < | 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 | #else rc = pager_incr_changecounter(pPager, 0); #endif if( rc!=SQLITE_OK ) goto commit_phase_one_exit; /* If this transaction has made the database smaller, then all pages ** being discarded by the truncation must be written to the journal ** file. ** ** Before reading the pages with page numbers larger than the ** current value of Pager.dbSize, set dbSize back to the value ** that it took at the start of the transaction. Otherwise, the ** calls to sqlite3PagerGet() return zeroed pages instead of ** reading data from the database file. */ if( pPager->dbSize<pPager->dbOrigSize && pPager->journalMode!=PAGER_JOURNALMODE_OFF ){ Pgno i; /* Iterator variable */ const Pgno iSkip = PAGER_MJ_PGNO(pPager); /* Pending lock page */ const Pgno dbSize = pPager->dbSize; /* Database image size */ pPager->dbSize = pPager->dbOrigSize; for( i=dbSize+1; i<=pPager->dbOrigSize; i++ ){ if( !sqlite3BitvecTest(pPager->pInJournal, i) && i!=iSkip ){ PgHdr *pPage; /* Page to journal */ rc = sqlite3PagerGet(pPager, i, &pPage); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; rc = sqlite3PagerWrite(pPage); sqlite3PagerUnref(pPage); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; } } pPager->dbSize = dbSize; } /* Write the master journal name into the journal file. If a master ** journal file name has already been written to the journal file, ** or if zMaster is NULL (no master journal), then this call is a no-op. */ rc = writeMasterJournal(pPager, zMaster); if( rc!=SQLITE_OK ) goto commit_phase_one_exit; |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
811 812 813 814 815 816 817 | } expr(A) ::= VARIABLE(X). { spanExpr(&A, pParse, TK_VARIABLE, &X); sqlite3ExprAssignVarNumber(pParse, A.pExpr); spanSet(&A, &X, &X); } expr(A) ::= expr(E) COLLATE ids(C). { | | | 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 | } expr(A) ::= VARIABLE(X). { spanExpr(&A, pParse, TK_VARIABLE, &X); sqlite3ExprAssignVarNumber(pParse, A.pExpr); spanSet(&A, &X, &X); } expr(A) ::= expr(E) COLLATE ids(C). { A.pExpr = sqlite3ExprAddCollateToken(pParse, E.pExpr, &C); A.zStart = E.zStart; A.zEnd = &C.z[C.n]; } %ifndef SQLITE_OMIT_CAST expr(A) ::= CAST(X) LP expr(E) AS typetoken(T) RP(Y). { A.pExpr = sqlite3PExpr(pParse, TK_CAST, E.pExpr, 0, &T); spanSet(&A,&X,&Y); |
︙ | ︙ | |||
1136 1137 1138 1139 1140 1141 1142 | %destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);} %type idxlist_opt {ExprList*} %destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);} idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { | | < < < < | < < < < | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 | %destructor idxlist {sqlite3ExprListDelete(pParse->db, $$);} %type idxlist_opt {ExprList*} %destructor idxlist_opt {sqlite3ExprListDelete(pParse->db, $$);} idxlist_opt(A) ::= . {A = 0;} idxlist_opt(A) ::= LP idxlist(X) RP. {A = X;} idxlist(A) ::= idxlist(X) COMMA nm(Y) collate(C) sortorder(Z). { Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C); A = sqlite3ExprListAppend(pParse,X, p); sqlite3ExprListSetName(pParse,A,&Y,1); sqlite3ExprListCheckLength(pParse, A, "index"); if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; } idxlist(A) ::= nm(Y) collate(C) sortorder(Z). { Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &C); A = sqlite3ExprListAppend(pParse,0, p); sqlite3ExprListSetName(pParse, A, &Y, 1); sqlite3ExprListCheckLength(pParse, A, "index"); if( A ) A->a[A->nExpr-1].sortOrder = (u8)Z; } %type collate {Token} |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | ** Is equivalent to: ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 ** ** The result of random()%5 in the GROUP BY clause is probably different ** from the result in the result-set. We might fix this someday. Or ** then again, we might not... ** ** The nSubquery parameter specifies how many levels of subquery the ** alias is removed from the original expression. The usually value is ** zero but it might be more if the alias is contained within a subquery ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION ** structures must be increased by the nSubquery amount. */ | > > > > > > > > > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | ** Is equivalent to: ** ** SELECT random()%5 AS x, count(*) FROM tab GROUP BY random()%5 ** ** The result of random()%5 in the GROUP BY clause is probably different ** from the result in the result-set. We might fix this someday. Or ** then again, we might not... ** ** If the reference is followed by a COLLATE operator, then make sure ** the COLLATE operator is preserved. For example: ** ** SELECT a+b, c+d FROM t1 ORDER BY 1 COLLATE nocase; ** ** Should be transformed into: ** ** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase; ** ** The nSubquery parameter specifies how many levels of subquery the ** alias is removed from the original expression. The usually value is ** zero but it might be more if the alias is contained within a subquery ** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION ** structures must be increased by the nSubquery amount. */ |
︙ | ︙ | |||
87 88 89 90 91 92 93 | sqlite3 *db; /* The database connection */ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); assert( pOrig->flags & EP_Resolved ); db = pParse->db; | < | > > < < < < < < < < < < < < < | < | > > > > > > > > | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 | sqlite3 *db; /* The database connection */ assert( iCol>=0 && iCol<pEList->nExpr ); pOrig = pEList->a[iCol].pExpr; assert( pOrig!=0 ); assert( pOrig->flags & EP_Resolved ); db = pParse->db; pDup = sqlite3ExprDup(db, pOrig, 0); if( pDup==0 ) return; if( pOrig->op!=TK_COLUMN && zType[0]!='G' ){ incrAggFunctionDepth(pDup, nSubquery); pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0); if( pDup==0 ) return; if( pEList->a[iCol].iAlias==0 ){ pEList->a[iCol].iAlias = (u16)(++pParse->nAlias); } pDup->iTable = pEList->a[iCol].iAlias; } if( pExpr->op==TK_COLLATE ){ pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken); } /* Before calling sqlite3ExprDelete(), set the EP_Static flag. This ** prevents ExprDelete() from deleting the Expr structure itself, ** allowing it to be repopulated by the memcpy() on the following line. ** The pExpr->u.zToken might point into memory that will be freed by the ** sqlite3DbFree(db, pDup) on the last line of this block, so be sure to ** make a copy of the token before doing the sqlite3DbFree(). */ ExprSetProperty(pExpr, EP_Static); sqlite3ExprDelete(db, pExpr); memcpy(pExpr, pDup, sizeof(*pExpr)); if( !ExprHasProperty(pExpr, EP_IntValue) && pExpr->u.zToken!=0 ){ assert( (pExpr->flags & (EP_Reduced|EP_TokenOnly))==0 ); pExpr->u.zToken = sqlite3DbStrDup(db, pExpr->u.zToken); pExpr->flags2 |= EP2_MallocedToken; } sqlite3DbFree(db, pDup); } /* ** Return TRUE if the name zCol occurs anywhere in the USING clause. ** |
︙ | ︙ | |||
808 809 810 811 812 813 814 | moreToDo = 0; pEList = pSelect->pEList; assert( pEList!=0 ); for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; | | | | < | | < | | > > > > > > > > | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 | moreToDo = 0; pEList = pSelect->pEList; assert( pEList!=0 ); for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){ int iCol = -1; Expr *pE, *pDup; if( pItem->done ) continue; pE = sqlite3ExprSkipCollate(pItem->pExpr); if( sqlite3ExprIsInteger(pE, &iCol) ){ if( iCol<=0 || iCol>pEList->nExpr ){ resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr); return 1; } }else{ iCol = resolveAsName(pParse, pEList, pE); if( iCol==0 ){ pDup = sqlite3ExprDup(db, pE, 0); if( !db->mallocFailed ){ assert(pDup); iCol = resolveOrderByTermToExprList(pParse, pSelect, pDup); } sqlite3ExprDelete(db, pDup); } } if( iCol>0 ){ /* Convert the ORDER BY term into an integer column number iCol, ** taking care to preserve the COLLATE clause if it exists */ Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return 1; pNew->flags |= EP_IntValue; pNew->u.iValue = iCol; if( pItem->pExpr==pE ){ pItem->pExpr = pNew; }else{ assert( pItem->pExpr->op==TK_COLLATE ); assert( pItem->pExpr->pLeft==pE ); pItem->pExpr->pLeft = pNew; } sqlite3ExprDelete(db, pE); pItem->iOrderByCol = (u16)iCol; pItem->done = 1; }else{ moreToDo = 1; } } pSelect = pSelect->pNext; |
︙ | ︙ | |||
938 939 940 941 942 943 944 | /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ pItem->iOrderByCol = (u16)iCol; continue; } | | | | 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 | /* If an AS-name match is found, mark this ORDER BY column as being ** a copy of the iCol-th result-set column. The subsequent call to ** sqlite3ResolveOrderGroupBy() will convert the expression to a ** copy of the iCol-th result-set expression. */ pItem->iOrderByCol = (u16)iCol; continue; } if( sqlite3ExprIsInteger(sqlite3ExprSkipCollate(pE), &iCol) ){ /* The ORDER BY term is an integer constant. Again, set the column ** number so that sqlite3ResolveOrderGroupBy() will convert the ** order-by term to a copy of the result-set expression */ if( iCol<1 || iCol>0xffff ){ resolveOutOfRangeError(pParse, zType, i+1, nResult); return 1; } pItem->iOrderByCol = (u16)iCol; continue; } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
1331 1332 1333 1334 1335 1336 1337 | } *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ | | | 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 | } *pnCol = nCol; *paCol = aCol; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* Get an appropriate name for the column */ p = sqlite3ExprSkipCollate(pEList->a[i].pExpr); assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ zName = sqlite3DbStrDup(db, zName); }else{ Expr *pColExpr = p; /* The expression that is the result column name */ |
︙ | ︙ | |||
2329 2330 2331 2332 2333 2334 2335 | if( pKeyMerge ){ pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; pKeyMerge->nField = (u16)nOrderBy; pKeyMerge->enc = ENC(db); for(i=0; i<nOrderBy; i++){ CollSeq *pColl; Expr *pTerm = pOrderBy->a[i].pExpr; | | | | > | | 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 | if( pKeyMerge ){ pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy]; pKeyMerge->nField = (u16)nOrderBy; pKeyMerge->enc = ENC(db); for(i=0; i<nOrderBy; i++){ CollSeq *pColl; Expr *pTerm = pOrderBy->a[i].pExpr; if( pTerm->flags & EP_Collate ){ pColl = sqlite3ExprCollSeq(pParse, pTerm); }else{ pColl = multiSelectCollSeq(pParse, p, aPermute[i]); if( pColl==0 ) pColl = db->pDfltColl; pOrderBy->a[i].pExpr = sqlite3ExprAddCollateString(pParse, pTerm, pColl->zName); } pKeyMerge->aColl[i] = pColl; pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder; } } }else{ pKeyMerge = 0; |
︙ | ︙ | |||
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 | /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Release temporary registers */ if( regPrev ){ sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1); } | > | 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 | /* Implement the main merge loop */ sqlite3VdbeResolveLabel(v, labelCmpr); sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY); sqlite3VdbeAddOp4(v, OP_Compare, destA.iSdst, destB.iSdst, nOrderBy, (char*)pKeyMerge, P4_KEYINFO_HANDOFF); sqlite3VdbeChangeP5(v, OPFLAG_PERMUTE); sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB); /* Release temporary registers */ if( regPrev ){ sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1); } |
︙ | ︙ | |||
2604 2605 2606 2607 2608 2609 2610 | if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); | < < < | 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 | if( pExpr->iColumn<0 ){ pExpr->op = TK_NULL; }else{ Expr *pNew; assert( pEList!=0 && pExpr->iColumn<pEList->nExpr ); assert( pExpr->pLeft==0 && pExpr->pRight==0 ); pNew = sqlite3ExprDup(db, pEList->a[pExpr->iColumn].pExpr, 0); sqlite3ExprDelete(db, pExpr); pExpr = pNew; } }else{ pExpr->pLeft = substExpr(db, pExpr->pLeft, iTable, pEList); pExpr->pRight = substExpr(db, pExpr->pRight, iTable, pEList); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ |
︙ | ︙ | |||
3157 3158 3159 3160 3161 3162 3163 | sqlite3SelectDelete(db, pSub1); return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* | > | < < < > > | | | > > > > | > > > > | | < < | < < < | | | | > | | > | > > > > | | 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 | sqlite3SelectDelete(db, pSub1); return 1; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* ** Based on the contents of the AggInfo structure indicated by the first ** argument, this function checks if the following are true: ** ** * the query contains just a single aggregate function, ** * the aggregate function is either min() or max(), and ** * the argument to the aggregate function is a column value. ** ** If all of the above are true, then WHERE_ORDERBY_MIN or WHERE_ORDERBY_MAX ** is returned as appropriate. Also, *ppMinMax is set to point to the ** list of arguments passed to the aggregate before returning. ** ** Or, if the conditions above are not met, *ppMinMax is set to 0 and ** WHERE_ORDERBY_NORMAL is returned. */ static u8 minMaxQuery(AggInfo *pAggInfo, ExprList **ppMinMax){ int eRet = WHERE_ORDERBY_NORMAL; /* Return value */ *ppMinMax = 0; if( pAggInfo->nFunc==1 ){ Expr *pExpr = pAggInfo->aFunc[0].pExpr; /* Aggregate function */ ExprList *pEList = pExpr->x.pList; /* Arguments to agg function */ assert( pExpr->op==TK_AGG_FUNCTION ); if( pEList && pEList->nExpr==1 && pEList->a[0].pExpr->op==TK_AGG_COLUMN ){ const char *zFunc = pExpr->u.zToken; if( sqlite3StrICmp(zFunc, "min")==0 ){ eRet = WHERE_ORDERBY_MIN; *ppMinMax = pEList; }else if( sqlite3StrICmp(zFunc, "max")==0 ){ eRet = WHERE_ORDERBY_MAX; *ppMinMax = pEList; } } } assert( *ppMinMax==0 || (*ppMinMax)->nExpr==1 ); return eRet; } /* ** The select statement passed as the first argument is an aggregate query. ** The second argment is the associated aggregate-info object. This ** function tests if the SELECT is of the form: ** |
︙ | ︙ | |||
3905 3906 3907 3908 3909 3910 3911 3912 | for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub = pItem->pSelect; int isAggSub; if( pSub==0 ) continue; if( pItem->addrFillSub ){ | > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 | for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub = pItem->pSelect; int isAggSub; if( pSub==0 ) continue; /* Sometimes the code for a subquery will be generated more than ** once, if the subquery is part of the WHERE clause in a LEFT JOIN, ** for example. In that case, do not regenerate the code to manifest ** a view or the co-routine to implement a view. The first instance ** is sufficient, though the subroutine to manifest the view does need ** to be invoked again. */ if( pItem->addrFillSub ){ if( pItem->viaCoroutine==0 ){ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); } continue; } /* Increment Parse.nHeight by the height of the largest expression ** tree refered to by this, the parent select. The child select ** may contain expression trees of at most ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit ** more conservative than necessary, but much easier than enforcing ** an exact limit. */ pParse->nHeight += sqlite3SelectExprHeight(p); isAggSub = (pSub->selFlags & SF_Aggregate)!=0; if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ /* This subquery can be absorbed into its parent. */ if( isAggSub ){ isAgg = 1; p->selFlags |= SF_Aggregate; } i = -1; }else if( pTabList->nSrc==1 && (p->selFlags & SF_Materialize)==0 && OptimizationEnabled(db, SQLITE_SubqCoroutine) ){ /* Implement a co-routine that will return a single row of the result ** set on each invocation. */ int addrTop; int addrEof; pItem->regReturn = ++pParse->nMem; addrEof = ++pParse->nMem; /* Before coding the OP_Goto to jump to the start of the main routine, ** ensure that the jump to the verify-schema routine has already ** been coded. Otherwise, the verify-schema would likely be coded as ** part of the co-routine. If the main routine then accessed the ** database before invoking the co-routine for the first time (for ** example to initialize a LIMIT register from a sub-select), it would ** be doing so without having verified the schema version and obtained ** the required db locks. See ticket d6b36be38. */ sqlite3CodeVerifySchema(pParse, -1); sqlite3VdbeAddOp0(v, OP_Goto); addrTop = sqlite3VdbeAddOp1(v, OP_OpenPseudo, pItem->iCursor); sqlite3VdbeChangeP5(v, 1); VdbeComment((v, "coroutine for %s", pItem->pTab->zName)); pItem->addrFillSub = addrTop; sqlite3VdbeAddOp2(v, OP_Integer, 0, addrEof); sqlite3VdbeChangeP5(v, 1); sqlite3SelectDestInit(&dest, SRT_Coroutine, pItem->regReturn); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; pItem->viaCoroutine = 1; sqlite3VdbeChangeP2(v, addrTop, dest.iSdst); sqlite3VdbeChangeP3(v, addrTop, dest.nSdst); sqlite3VdbeAddOp2(v, OP_Integer, 1, addrEof); sqlite3VdbeAddOp1(v, OP_Yield, pItem->regReturn); VdbeComment((v, "end %s", pItem->pTab->zName)); sqlite3VdbeJumpHere(v, addrTop-1); sqlite3ClearTempRegCache(pParse); }else{ /* Generate a subroutine that will fill an ephemeral table with ** the content of this subquery. pItem->addrFillSub will point ** to the address of the generated subroutine. pItem->regReturn ** is a register allocated to hold the subroutine return address */ int topAddr; |
︙ | ︙ | |||
4477 4478 4479 4480 4481 4482 4483 | ** ** + The optimizer code in where.c (the thing that decides which ** index or indices to use) should place a different priority on ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList *pMinMax = 0; | > > > > > | > > > < < | | 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 | ** ** + The optimizer code in where.c (the thing that decides which ** index or indices to use) should place a different priority on ** satisfying the 'ORDER BY' clause than it does in other cases. ** Refer to code and comments in where.c for details. */ ExprList *pMinMax = 0; u8 flag = WHERE_ORDERBY_NORMAL; assert( p->pGroupBy==0 ); assert( flag==0 ); if( p->pHaving==0 ){ flag = minMaxQuery(&sAggInfo, &pMinMax); } assert( flag==0 || (pMinMax!=0 && pMinMax->nExpr==1) ); if( flag ){ pMinMax = sqlite3ExprListDup(db, pMinMax, 0); pDel = pMinMax; if( pMinMax && !db->mallocFailed ){ pMinMax->a[0].sortOrder = flag!=WHERE_ORDERBY_MIN ?1:0; pMinMax->a[0].pExpr->op = TK_COLUMN; } } |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
537 538 539 540 541 542 543 544 545 546 547 548 549 550 | static void output_c_string(FILE *out, const char *z){ unsigned int c; fputc('"', out); while( (c = *(z++))!=0 ){ if( c=='\\' ){ fputc(c, out); fputc(c, out); }else if( c=='\t' ){ fputc('\\', out); fputc('t', out); }else if( c=='\n' ){ fputc('\\', out); fputc('n', out); }else if( c=='\r' ){ | > > > | 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 | static void output_c_string(FILE *out, const char *z){ unsigned int c; fputc('"', out); while( (c = *(z++))!=0 ){ if( c=='\\' ){ fputc(c, out); fputc(c, out); }else if( c=='"' ){ fputc('\\', out); fputc('"', out); }else if( c=='\t' ){ fputc('\\', out); fputc('t', out); }else if( c=='\n' ){ fputc('\\', out); fputc('n', out); }else if( c=='\r' ){ |
︙ | ︙ | |||
792 793 794 795 796 797 798 | fprintf(p->out,"</TR>\n"); break; } case MODE_Tcl: { if( p->cnt++==0 && p->showHeader ){ for(i=0; i<nArg; i++){ output_c_string(p->out,azCol[i] ? azCol[i] : ""); | | | | 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 | fprintf(p->out,"</TR>\n"); break; } case MODE_Tcl: { if( p->cnt++==0 && p->showHeader ){ for(i=0; i<nArg; i++){ output_c_string(p->out,azCol[i] ? azCol[i] : ""); if(i<nArg-1) fprintf(p->out, "%s", p->separator); } fprintf(p->out,"\n"); } if( azArg==0 ) break; for(i=0; i<nArg; i++){ output_c_string(p->out, azArg[i] ? azArg[i] : p->nullvalue); if(i<nArg-1) fprintf(p->out, "%s", p->separator); } fprintf(p->out,"\n"); break; } case MODE_Csv: { if( p->cnt++==0 && p->showHeader ){ for(i=0; i<nArg; i++){ |
︙ | ︙ | |||
2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 | p->mode = MODE_Column; }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){ p->mode = MODE_List; }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){ p->mode = MODE_Tcl; }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){ p->mode = MODE_Csv; sqlite3_snprintf(sizeof(p->separator), p->separator, ","); }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){ | > | 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 | p->mode = MODE_Column; }else if( n2==4 && strncmp(azArg[1],"list",n2)==0 ){ p->mode = MODE_List; }else if( n2==4 && strncmp(azArg[1],"html",n2)==0 ){ p->mode = MODE_Html; }else if( n2==3 && strncmp(azArg[1],"tcl",n2)==0 ){ p->mode = MODE_Tcl; sqlite3_snprintf(sizeof(p->separator), p->separator, " "); }else if( n2==3 && strncmp(azArg[1],"csv",n2)==0 ){ p->mode = MODE_Csv; sqlite3_snprintf(sizeof(p->separator), p->separator, ","); }else if( n2==4 && strncmp(azArg[1],"tabs",n2)==0 ){ p->mode = MODE_List; sqlite3_snprintf(sizeof(p->separator), p->separator, "\t"); }else if( n2==6 && strncmp(azArg[1],"insert",n2)==0 ){ |
︙ | ︙ | |||
2707 2708 2709 2710 2711 2712 2713 | if( zSql ){ if( !_all_whitespace(zSql) ){ fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); } free(zSql); } free(zLine); | | | 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 | if( zSql ){ if( !_all_whitespace(zSql) ){ fprintf(stderr, "Error: incomplete SQL: %s\n", zSql); } free(zSql); } free(zLine); return errCnt>0; } /* ** Return a pathname which is the user's home directory. A ** 0 return indicates an error of some kind. */ static char *find_home_dir(void){ |
︙ | ︙ | |||
2820 2821 2822 2823 2824 2825 2826 | /* ** Show available command line options */ static const char zOptions[] = " -bail stop after hitting an error\n" " -batch force batch I/O\n" " -column set output mode to 'column'\n" | | | > > > | | | 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 | /* ** Show available command line options */ static const char zOptions[] = " -bail stop after hitting an error\n" " -batch force batch I/O\n" " -column set output mode to 'column'\n" " -cmd COMMAND run \"COMMAND\" before reading stdin\n" " -csv set output mode to 'csv'\n" " -echo print commands before execution\n" " -init FILENAME read/process named file\n" " -[no]header turn headers on or off\n" #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) " -heap SIZE Size of heap for memsys3 or memsys5\n" #endif " -help show this message\n" " -html set output mode to HTML\n" " -interactive force interactive I/O\n" " -line set output mode to 'line'\n" " -list set output mode to 'list'\n" #ifdef SQLITE_ENABLE_MULTIPLEX " -multiplex enable the multiplexor VFS\n" #endif " -nullvalue TEXT set text string for NULL values. Default ''\n" " -separator SEP set output field separator. Default: '|'\n" " -stats print memory stats before each finalize\n" " -version show SQLite version\n" " -vfs NAME use NAME as the default VFS\n" #ifdef SQLITE_ENABLE_VFSTRACE " -vfstrace enable tracing of all VFS calls\n" #endif ; |
︙ | ︙ | |||
2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881 2882 | data->showHeader = 0; sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); } int main(int argc, char **argv){ char *zErrMsg = 0; struct callback_data data; const char *zInitFile = 0; char *zFirstCmd = 0; int i; | > > > > > > > > > > > > > | 2876 2877 2878 2879 2880 2881 2882 2883 2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 | data->showHeader = 0; sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); } /* ** Get the argument to an --option. Throw an error and die if no argument ** is available. */ static char *cmdline_option_value(int argc, char **argv, int i){ if( i==argc ){ fprintf(stderr, "%s: Error: missing argument to %s\n", argv[0], argv[argc-1]); exit(1); } return argv[i]; } int main(int argc, char **argv){ char *zErrMsg = 0; struct callback_data data; const char *zInitFile = 0; char *zFirstCmd = 0; int i; |
︙ | ︙ | |||
2899 2900 2901 2902 2903 2904 2905 | #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ | | < > > > > > > > > > > > > > | < | > | | | | < | | 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 | #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ for(i=1; i<argc; i++){ char *z; z = argv[i]; if( z[0]!='-' ){ if( data.zDbFilename==0 ){ data.zDbFilename = z; continue; } if( zFirstCmd==0 ){ zFirstCmd = z; continue; } fprintf(stderr,"%s: Error: too many options: \"%s\"\n", Argv0, argv[i]); fprintf(stderr,"Use -help for a list of options.\n"); return 1; } if( z[1]=='-' ) z++; if( strcmp(z,"-separator")==0 || strcmp(z,"-nullvalue")==0 || strcmp(z,"-cmd")==0 ){ (void)cmdline_option_value(argc, argv, ++i); }else if( strcmp(z,"-init")==0 ){ zInitFile = cmdline_option_value(argc, argv, ++i); }else if( strcmp(z,"-batch")==0 ){ /* Need to check for batch mode here to so we can avoid printing ** informational messages (like from process_sqliterc) before ** we do the actual processing of arguments later in a second pass. */ stdin_is_interactive = 0; }else if( strcmp(z,"-heap")==0 ){ #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) int j, c; const char *zSize; sqlite3_int64 szHeap; zSize = cmdline_option_value(argc, argv, ++i); szHeap = atoi(zSize); for(j=0; (c = zSize[j])!=0; j++){ if( c=='M' ){ szHeap *= 1000000; break; } if( c=='K' ){ szHeap *= 1000; break; } if( c=='G' ){ szHeap *= 1000000000; break; } } if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; |
︙ | ︙ | |||
2951 2952 2953 2954 2955 2956 2957 | #endif #ifdef SQLITE_ENABLE_MULTIPLEX }else if( strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiple_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }else if( strcmp(z,"-vfs")==0 ){ | | < | < < < < < < < < | < > < < < < < < < | 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 | #endif #ifdef SQLITE_ENABLE_MULTIPLEX }else if( strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiple_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }else if( strcmp(z,"-vfs")==0 ){ sqlite3_vfs *pVfs = sqlite3_vfs_find(cmdline_option_value(argc,argv,++i)); if( pVfs ){ sqlite3_vfs_register(pVfs, 1); }else{ fprintf(stderr, "no such VFS: \"%s\"\n", argv[i]); exit(1); } } } if( data.zDbFilename==0 ){ #ifndef SQLITE_OMIT_MEMORYDB data.zDbFilename = ":memory:"; #else fprintf(stderr,"%s: Error: no database filename specified\n", Argv0); return 1; #endif } data.out = stdout; /* Go ahead and open the database file if it already exists. If the ** file does not exist, delay opening it. This prevents empty database ** files from being created if a user mistypes the database name argument ** to the sqlite command-line tool. */ if( access(data.zDbFilename, 0)==0 ){ |
︙ | ︙ | |||
3009 3010 3011 3012 3013 3014 3015 | } /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization ** file is processed so that the command-line arguments will override ** settings in the initialization file. */ | | > < < < < < < < < > < < < < < < < | | 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 | } /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization ** file is processed so that the command-line arguments will override ** settings in the initialization file. */ for(i=1; i<argc; i++){ char *z = argv[i]; if( z[0]!='-' ) continue; if( z[1]=='-' ){ z++; } if( strcmp(z,"-init")==0 ){ i++; }else if( strcmp(z,"-html")==0 ){ data.mode = MODE_Html; }else if( strcmp(z,"-list")==0 ){ data.mode = MODE_List; }else if( strcmp(z,"-line")==0 ){ data.mode = MODE_Line; }else if( strcmp(z,"-column")==0 ){ data.mode = MODE_Column; }else if( strcmp(z,"-csv")==0 ){ data.mode = MODE_Csv; memcpy(data.separator,",",2); }else if( strcmp(z,"-separator")==0 ){ sqlite3_snprintf(sizeof(data.separator), data.separator, "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-nullvalue")==0 ){ sqlite3_snprintf(sizeof(data.nullvalue), data.nullvalue, "%s",cmdline_option_value(argc,argv,++i)); }else if( strcmp(z,"-header")==0 ){ data.showHeader = 1; }else if( strcmp(z,"-noheader")==0 ){ data.showHeader = 0; }else if( strcmp(z,"-echo")==0 ){ data.echoOn = 1; }else if( strcmp(z,"-stats")==0 ){ |
︙ | ︙ | |||
3078 3079 3080 3081 3082 3083 3084 | }else if( strcmp(z,"-multiplex")==0 ){ i++; #endif }else if( strcmp(z,"-help")==0 ){ usage(1); }else if( strcmp(z,"-cmd")==0 ){ if( i==argc-1 ) break; | < | | 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 | }else if( strcmp(z,"-multiplex")==0 ){ i++; #endif }else if( strcmp(z,"-help")==0 ){ usage(1); }else if( strcmp(z,"-cmd")==0 ){ if( i==argc-1 ) break; z = cmdline_option_value(argc,argv,++i); if( z[0]=='.' ){ rc = do_meta_command(z, &data); if( rc && bail_on_error ) return rc; }else{ open_db(&data); rc = shell_exec(data.db, z, shell_callback, &data, &zErrMsg); if( zErrMsg!=0 ){ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
465 466 467 468 469 470 471 472 473 474 475 476 477 478 | #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) | > | 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 | #define SQLITE_IOERR_CLOSE (SQLITE_IOERR | (16<<8)) #define SQLITE_IOERR_DIR_CLOSE (SQLITE_IOERR | (17<<8)) #define SQLITE_IOERR_SHMOPEN (SQLITE_IOERR | (18<<8)) #define SQLITE_IOERR_SHMSIZE (SQLITE_IOERR | (19<<8)) #define SQLITE_IOERR_SHMLOCK (SQLITE_IOERR | (20<<8)) #define SQLITE_IOERR_SHMMAP (SQLITE_IOERR | (21<<8)) #define SQLITE_IOERR_SEEK (SQLITE_IOERR | (22<<8)) #define SQLITE_IOERR_DELETE_NOENT (SQLITE_IOERR | (23<<8)) #define SQLITE_LOCKED_SHAREDCACHE (SQLITE_LOCKED | (1<<8)) #define SQLITE_BUSY_RECOVERY (SQLITE_BUSY | (1<<8)) #define SQLITE_CANTOPEN_NOTEMPDIR (SQLITE_CANTOPEN | (1<<8)) #define SQLITE_CANTOPEN_ISDIR (SQLITE_CANTOPEN | (2<<8)) #define SQLITE_CANTOPEN_FULLPATH (SQLITE_CANTOPEN | (3<<8)) #define SQLITE_CORRUPT_VTAB (SQLITE_CORRUPT | (1<<8)) #define SQLITE_READONLY_RECOVERY (SQLITE_READONLY | (1<<8)) |
︙ | ︙ | |||
847 848 849 850 851 852 853 | ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. | < > > > > > > > > > > > | 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 | ** VFS has handled the PRAGMA itself and the parser generates a no-op ** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns ** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means ** that the VFS encountered an error while handling the [PRAGMA] and the ** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA] ** file control occurs at the beginning of pragma statement analysis and so ** it is able to override built-in [PRAGMA] statements. ** ** <li>[[SQLITE_FCNTL_BUSYHANDLER]] ** ^This file-control may be invoked by SQLite on the database file handle ** shortly after it is opened in order to provide a custom VFS with access ** to the connections busy-handler callback. The argument is of type (void **) ** - an array of two (void *) values. The first (void *) actually points ** to a function of type (int (*)(void *)). In order to invoke the connections ** busy-handler, this function should be invoked with the second (void *) in ** the array as the only argument. If it returns non-zero, then the operation ** should be retried. If it returns zero, the custom VFS should abandon the ** current operation. ** ** <li>[[SQLITE_FCNTL_TEMPFILENAME]] ** ^Application can invoke this file-control to have SQLite generate a ** temporary filename using the same algorithm that is followed to generate ** temporary filenames for TEMP tables and other internal uses. The ** argument should be a char** which will be filled with the filename ** written into memory obtained from [sqlite3_malloc()]. The caller should ** invoke [sqlite3_free()] on the result to avoid a memory leak. ** ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_GET_LOCKPROXYFILE 2 #define SQLITE_SET_LOCKPROXYFILE 3 #define SQLITE_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 #define SQLITE_FCNTL_CHUNK_SIZE 6 #define SQLITE_FCNTL_FILE_POINTER 7 #define SQLITE_FCNTL_SYNC_OMITTED 8 #define SQLITE_FCNTL_WIN32_AV_RETRY 9 #define SQLITE_FCNTL_PERSIST_WAL 10 #define SQLITE_FCNTL_OVERWRITE 11 #define SQLITE_FCNTL_VFSNAME 12 #define SQLITE_FCNTL_POWERSAFE_OVERWRITE 13 #define SQLITE_FCNTL_PRAGMA 14 #define SQLITE_FCNTL_BUSYHANDLER 15 #define SQLITE_FCNTL_TEMPFILENAME 16 /* ** CAPI3REF: Mutex Handle ** ** The mutex module within SQLite defines [sqlite3_mutex] to be an ** abstract type for a mutex object. The SQLite core never looks ** at the internal representation of an [sqlite3_mutex]. It only |
︙ | ︙ | |||
1572 1573 1574 1575 1576 1577 1578 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN | | > > > > > > > > > > > > > > > > | 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 | ** connection is opened. If it is globally disabled, filenames are ** only interpreted as URIs if the SQLITE_OPEN_URI flag is set when the ** database connection is opened. By default, URI handling is globally ** disabled. The default value may be changed by compiling with the ** [SQLITE_USE_URI] symbol defined. ** ** [[SQLITE_CONFIG_COVERING_INDEX_SCAN]] <dt>SQLITE_CONFIG_COVERING_INDEX_SCAN ** <dd> This option takes a single integer argument which is interpreted as ** a boolean in order to enable or disable the use of covering indices for ** full table scans in the query optimizer. The default setting is determined ** by the [SQLITE_ALLOW_COVERING_INDEX_SCAN] compile-time option, or is "on" ** if that compile-time option is omitted. ** The ability to disable the use of covering indices for full table scans ** is because some incorrectly coded legacy applications might malfunction ** malfunction when the optimization is enabled. Providing the ability to ** disable the optimization allows the older, buggy application code to work ** without change even with newer versions of SQLite. ** ** [[SQLITE_CONFIG_PCACHE]] [[SQLITE_CONFIG_GETPCACHE]] ** <dt>SQLITE_CONFIG_PCACHE and SQLITE_CONFIG_GETPCACHE ** <dd> These options are obsolete and should not be used by new code. ** They are retained for backwards compatibility but are now no-ops. ** </dl> ** ** [[SQLITE_CONFIG_SQLLOG]] ** <dt>SQLITE_CONFIG_SQLLOG ** <dd>This option is only available if sqlite is compiled with the ** SQLITE_ENABLE_SQLLOG pre-processor macro defined. The first argument should ** be a pointer to a function of type void(*)(void*,sqlite3*,const char*, int). ** The second should be of type (void*). The callback is invoked by the library ** in three separate circumstances, identified by the value passed as the ** fourth parameter. If the fourth parameter is 0, then the database connection ** passed as the second argument has just been opened. The third argument ** points to a buffer containing the name of the main database file. If the ** fourth parameter is 1, then the SQL statement that the third parameter ** points to has just been executed. Or, if the fourth parameter is 2, then ** the connection being passed as the second parameter is being closed. The ** third parameter is passed NULL In this case. ** </dl> */ #define SQLITE_CONFIG_SINGLETHREAD 1 /* nil */ #define SQLITE_CONFIG_MULTITHREAD 2 /* nil */ #define SQLITE_CONFIG_SERIALIZED 3 /* nil */ #define SQLITE_CONFIG_MALLOC 4 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_GETMALLOC 5 /* sqlite3_mem_methods* */ #define SQLITE_CONFIG_SCRATCH 6 /* void*, int sz, int N */ |
︙ | ︙ | |||
1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** | > | 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 | #define SQLITE_CONFIG_PCACHE 14 /* no-op */ #define SQLITE_CONFIG_GETPCACHE 15 /* no-op */ #define SQLITE_CONFIG_LOG 16 /* xFunc, void* */ #define SQLITE_CONFIG_URI 17 /* int */ #define SQLITE_CONFIG_PCACHE2 18 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_GETPCACHE2 19 /* sqlite3_pcache_methods2* */ #define SQLITE_CONFIG_COVERING_INDEX_SCAN 20 /* int */ #define SQLITE_CONFIG_SQLLOG 21 /* xSqllog, void* */ /* ** CAPI3REF: Database Connection Configuration Options ** ** These constants are the available integer configuration options that ** can be passed as the second argument to the [sqlite3_db_config()] interface. ** |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
823 824 825 826 827 828 829 | Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ | | | 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 | Db *aDb; /* All backends */ int nDb; /* Number of backends currently in use */ int flags; /* Miscellaneous flags. See below */ i64 lastRowid; /* ROWID of most recent insert (see above) */ unsigned int openFlags; /* Flags passed to sqlite3_vfs.xOpen() */ int errCode; /* Most recent error code (SQLITE_*) */ int errMask; /* & result codes with this before returning */ u16 dbOptFlags; /* Flags to enable/disable optimizations */ u8 autoCommit; /* The auto-commit flag. */ u8 temp_store; /* 1: file 2: memory 0: default */ u8 mallocFailed; /* True if we have seen a malloc failure */ u8 dfltLockMode; /* Default locking-mode for attached dbs */ signed char nextAutovac; /* Autovac setting after VACUUM if >=0 */ u8 suppressErr; /* Do not issue error messages if true */ u8 vtabOnConflict; /* Value to return for s3_vtab_on_conflict() */ |
︙ | ︙ | |||
968 969 970 971 972 973 974 | #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ | > | | 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 | #define SQLITE_ColumnCache 0x0002 /* Column cache */ #define SQLITE_GroupByOrder 0x0004 /* GROUPBY cover of ORDERBY */ #define SQLITE_FactorOutConst 0x0008 /* Constant factoring */ #define SQLITE_IdxRealAsInt 0x0010 /* Store REAL as INT in indices */ #define SQLITE_DistinctOpt 0x0020 /* DISTINCT using indexes */ #define SQLITE_CoverIdxScan 0x0040 /* Covering index scans */ #define SQLITE_OrderByIdxJoin 0x0080 /* ORDER BY of joins via index */ #define SQLITE_SubqCoroutine 0x0100 /* Evaluate subqueries as coroutines */ #define SQLITE_AllOpts 0xffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #ifndef SQLITE_OMIT_BUILTIN_TEST #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
︙ | ︙ | |||
1145 1146 1147 1148 1149 1150 1151 | #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** | < < < < < < < < < < < < | | 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 | #define COLFLAG_HIDDEN 0x0002 /* A hidden column in a virtual table */ /* ** A "Collating Sequence" is defined by an instance of the following ** structure. Conceptually, a collating sequence consists of a name and ** a comparison routine that defines the order of that sequence. ** ** If CollSeq.xCmp is NULL, it means that the ** collating sequence is undefined. Indices built on an undefined ** collating sequence may not be read or written. */ struct CollSeq { char *zName; /* Name of the collating sequence, UTF-8 encoded */ u8 enc; /* Text encoding handled by xCmp() */ void *pUser; /* First argument to xCmp() */ |
︙ | ︙ | |||
1685 1686 1687 1688 1689 1690 1691 | Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ } x; | < | 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 | Expr *pLeft; /* Left subnode */ Expr *pRight; /* Right subnode */ union { ExprList *pList; /* Function arguments or in "<expr> IN (<expr-list)" */ Select *pSelect; /* Used for sub-selects and "<expr> IN (<select>)" */ } x; /* If the EP_Reduced flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to ** access them will result in a segfault or malfunction. *********************************************************************/ #if SQLITE_MAX_EXPR_DEPTH>0 |
︙ | ︙ | |||
1721 1722 1723 1724 1725 1726 1727 | #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ | | | 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 | #define EP_Agg 0x0002 /* Contains one or more aggregate functions */ #define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */ #define EP_Error 0x0008 /* Expression contains one or more errors */ #define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */ #define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */ #define EP_DblQuoted 0x0040 /* token.z was originally in "..." */ #define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */ #define EP_Collate 0x0100 /* Tree contains a TK_COLLATE opeartor */ #define EP_FixedDest 0x0200 /* Result needed in a specific register */ #define EP_IntValue 0x0400 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x0800 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Hint 0x1000 /* Not used */ #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ #define EP_TokenOnly 0x4000 /* Expr struct is EXPR_TOKENONLYSIZE bytes only */ #define EP_Static 0x8000 /* Held in memory not obtained from malloc() */ |
︙ | ︙ | |||
1874 1875 1876 1877 1878 1879 1880 | char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ int addrFillSub; /* Address of subroutine to manifest a subquery */ int regReturn; /* Register holding return address of addrFillSub */ u8 jointype; /* Type of join between this able and the previous */ | | | > | 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 | char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ int addrFillSub; /* Address of subroutine to manifest a subquery */ int regReturn; /* Register holding return address of addrFillSub */ u8 jointype; /* Type of join between this able and the previous */ unsigned notIndexed :1; /* True if there is a NOT INDEXED clause */ unsigned isCorrelated :1; /* True if sub-query is correlated */ unsigned viaCoroutine :1; /* Implemented as a co-routine */ #ifndef SQLITE_OMIT_EXPLAIN u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ #endif int iCursor; /* The VDBE cursor number used to access this table */ Expr *pOn; /* The ON clause of a join */ IdList *pUsing; /* The USING clause of a join */ Bitmask colUsed; /* Bit N (1<<N) set if column N of pTab is used */ |
︙ | ︙ | |||
1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 | struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; /* The following field is really not part of the current level. But ** we need a place to cache virtual table index information for each ** virtual table in the FROM clause and the WhereLevel structure is ** a convenient place since there is one WhereLevel for each FROM clause ** element. */ | > | 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 | struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when plan.wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; double rOptCost; /* "Optimal" cost for this level */ /* The following field is really not part of the current level. But ** we need a place to cache virtual table index information for each ** virtual table in the FROM clause and the WhereLevel structure is ** a convenient place since there is one WhereLevel for each FROM clause ** element. */ |
︙ | ︙ | |||
2099 2100 2101 2102 2103 2104 2105 | Expr *pOffset; /* OFFSET expression. NULL means not used. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ | | | | | | | | | > | 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 | Expr *pOffset; /* OFFSET expression. NULL means not used. */ }; /* ** Allowed values for Select.selFlags. The "SF" prefix stands for ** "Select Flag". */ #define SF_Distinct 0x0001 /* Output should be DISTINCT */ #define SF_Resolved 0x0002 /* Identifiers have been resolved */ #define SF_Aggregate 0x0004 /* Contains aggregate functions */ #define SF_UsesEphemeral 0x0008 /* Uses the OpenEphemeral opcode */ #define SF_Expanded 0x0010 /* sqlite3SelectExpand() called on this */ #define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */ #define SF_UseSorter 0x0040 /* Sort using a sorter */ #define SF_Values 0x0080 /* Synthesized from VALUES clause */ #define SF_Materialize 0x0100 /* Force materialization of views */ /* ** The results of a select can be distributed in several ways. The ** "SRT" prefix means "SELECT Result Type". */ #define SRT_Union 1 /* Store result as keys in an index */ |
︙ | ︙ | |||
2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the | > | 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 | #define OPFLAG_APPEND 0x08 /* This is likely to be an append */ #define OPFLAG_USESEEKRESULT 0x10 /* Try to avoid a seek in BtreeInsert() */ #define OPFLAG_CLEARCACHE 0x20 /* Clear pseudo-table cache in OP_Column */ #define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */ #define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */ #define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */ #define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */ #define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */ /* * Each trigger present in the database schema is stored as an instance of * struct Trigger. * * Pointers to instances of struct Trigger are stored in two ways. * 1. In the "trigHash" hash table (part of the sqlite3* that represents the |
︙ | ︙ | |||
2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 | int isMallocInit; /* True after malloc is initialized */ int isPCacheInit; /* True after malloc is initialized */ sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ int nRefInitMutex; /* Number of users of pInitMutex */ void (*xLog)(void*,int,const char*); /* Function for logging */ void *pLogArg; /* First argument to xLog() */ int bLocaltimeFault; /* True to fail localtime() calls */ }; /* ** Context pointer passed down through the tree-walk. */ struct Walker { int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ | > > > > | 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 | int isMallocInit; /* True after malloc is initialized */ int isPCacheInit; /* True after malloc is initialized */ sqlite3_mutex *pInitMutex; /* Mutex used by sqlite3_initialize() */ int nRefInitMutex; /* Number of users of pInitMutex */ void (*xLog)(void*,int,const char*); /* Function for logging */ void *pLogArg; /* First argument to xLog() */ int bLocaltimeFault; /* True to fail localtime() calls */ #ifdef SQLITE_ENABLE_SQLLOG void(*xSqllog)(void*,sqlite3*,const char*, int); void *pSqllogArg; #endif }; /* ** Context pointer passed down through the tree-walk. */ struct Walker { int (*xExprCallback)(Walker*, Expr*); /* Callback for expressions */ |
︙ | ︙ | |||
3022 3023 3024 3025 3026 3027 3028 | u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); const char *sqlite3ErrStr(int); int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); | | > | | 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 | u8 sqlite3HexToInt(int h); int sqlite3TwoPartName(Parse *, Token *, Token *, Token **); const char *sqlite3ErrStr(int); int sqlite3ReadSchema(Parse *pParse); CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int); CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName); CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr); Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, Token*); Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*); Expr *sqlite3ExprSkipCollate(Expr*); int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckObjectName(Parse *, const char *); void sqlite3VdbeSetChanges(sqlite3 *, int); int sqlite3AddInt64(i64*,i64); int sqlite3SubInt64(i64*,i64); int sqlite3MulInt64(i64*,i64); int sqlite3AbsInt32(int); |
︙ | ︙ | |||
3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 | #define IN_INDEX_INDEX 3 int sqlite3FindInIndex(Parse *, Expr *, int*); #ifdef SQLITE_ENABLE_ATOMIC_WRITE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); int sqlite3JournalSize(sqlite3_vfs *); int sqlite3JournalCreate(sqlite3_file *); #else #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) #endif void sqlite3MemJournalOpen(sqlite3_file *); int sqlite3MemJournalSize(void); int sqlite3IsMemJournal(sqlite3_file *); #if SQLITE_MAX_EXPR_DEPTH>0 | > > | 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 | #define IN_INDEX_INDEX 3 int sqlite3FindInIndex(Parse *, Expr *, int*); #ifdef SQLITE_ENABLE_ATOMIC_WRITE int sqlite3JournalOpen(sqlite3_vfs *, const char *, sqlite3_file *, int, int); int sqlite3JournalSize(sqlite3_vfs *); int sqlite3JournalCreate(sqlite3_file *); int sqlite3JournalExists(sqlite3_file *p); #else #define sqlite3JournalSize(pVfs) ((pVfs)->szOsFile) #define sqlite3JournalExists(p) 1 #endif void sqlite3MemJournalOpen(sqlite3_file *); int sqlite3MemJournalSize(void); int sqlite3IsMemJournal(sqlite3_file *); #if SQLITE_MAX_EXPR_DEPTH>0 |
︙ | ︙ |
Changes to src/status.c.
︙ | ︙ | |||
204 205 206 207 208 209 210 | */ case SQLITE_DBSTATUS_STMT_USED: { struct Vdbe *pVdbe; /* Used to iterate through VMs */ int nByte = 0; /* Used to accumulate return value */ db->pnBytesFreed = &nByte; for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ | | > | 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 | */ case SQLITE_DBSTATUS_STMT_USED: { struct Vdbe *pVdbe; /* Used to iterate through VMs */ int nByte = 0; /* Used to accumulate return value */ db->pnBytesFreed = &nByte; for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){ sqlite3VdbeClearObject(db, pVdbe); sqlite3DbFree(db, pVdbe); } db->pnBytesFreed = 0; *pHighwater = 0; *pCurrent = nByte; break; |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 | } sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName); Tcl_AppendResult(interp, zVfsName, (char*)0); sqlite3_free(zVfsName); return TCL_OK; } /* ** tclcmd: sqlite3_vfs_list ** ** Return a tcl list containing the names of all registered vfs's. */ static int vfs_list( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 | } sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName); Tcl_AppendResult(interp, zVfsName, (char*)0); sqlite3_free(zVfsName); return TCL_OK; } /* ** tclcmd: file_control_tempfilename DB ?AUXDB? ** ** Return a string that is a temporary filename */ static int file_control_tempfilename( ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int objc, /* Number of arguments */ Tcl_Obj *CONST objv[] /* Command arguments */ ){ sqlite3 *db; const char *zDbName = "main"; char *zTName = 0; if( objc!=2 && objc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ return TCL_ERROR; } if( objc==3 ){ zDbName = Tcl_GetString(objv[2]); } sqlite3_file_control(db, zDbName, SQLITE_FCNTL_TEMPFILENAME, (void*)&zTName); Tcl_AppendResult(interp, zTName, (char*)0); sqlite3_free(zTName); return TCL_OK; } /* ** tclcmd: sqlite3_vfs_list ** ** Return a tcl list containing the names of all registered vfs's. */ static int vfs_list( |
︙ | ︙ | |||
6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 | { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, { "file_control_chunksize_test", file_control_chunksize_test, 0 }, { "file_control_sizehint_test", file_control_sizehint_test, 0 }, { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_persist_wal", file_control_persist_wal, 0 }, { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, { "file_control_vfsname", file_control_vfsname, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 }, /* Functions from os.h */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, | > | 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 | { "file_control_lockproxy_test", file_control_lockproxy_test, 0 }, { "file_control_chunksize_test", file_control_chunksize_test, 0 }, { "file_control_sizehint_test", file_control_sizehint_test, 0 }, { "file_control_win32_av_retry", file_control_win32_av_retry, 0 }, { "file_control_persist_wal", file_control_persist_wal, 0 }, { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0}, { "file_control_vfsname", file_control_vfsname, 0 }, { "file_control_tempfilename", file_control_tempfilename, 0 }, { "sqlite3_vfs_list", vfs_list, 0 }, { "sqlite3_create_function_v2", test_create_function_v2, 0 }, /* Functions from os.h */ #ifndef SQLITE_OMIT_UTF16 { "add_test_collate", test_collate, 0 }, { "add_test_collate_needed", test_collate_needed, 0 }, |
︙ | ︙ |
Changes to src/test6.c.
︙ | ︙ | |||
308 309 310 311 312 313 314 | u8 *zGarbage; int iFirst = (int)(pWrite->iOffset/g.iSectorSize); int iLast = (int)((pWrite->iOffset+pWrite->nBuf-1)/g.iSectorSize); assert(pWrite->zBuf); #ifdef TRACE_CRASHTEST | | | | 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 | u8 *zGarbage; int iFirst = (int)(pWrite->iOffset/g.iSectorSize); int iLast = (int)((pWrite->iOffset+pWrite->nBuf-1)/g.iSectorSize); assert(pWrite->zBuf); #ifdef TRACE_CRASHTEST printf("Trashing %d sectors @ %lld (sector %d) (%s)\n", 1+iLast-iFirst, pWrite->iOffset, iFirst, pWrite->pFile->zName ); #endif zGarbage = crash_malloc(g.iSectorSize); if( zGarbage ){ sqlite3_int64 i; for(i=iFirst; rc==SQLITE_OK && i<=iLast; i++){ |
︙ | ︙ | |||
624 625 626 627 628 629 630 631 632 | pWrapper->nData = (4096 + pWrapper->iSize); pWrapper->zData = crash_malloc(pWrapper->nData); if( pWrapper->zData ){ /* os_unix.c contains an assert() that fails if the caller attempts ** to read data from the 512-byte locking region of a file opened ** with the SQLITE_OPEN_MAIN_DB flag. This region of a database file ** never contains valid data anyhow. So avoid doing such a read here. */ const int isDb = (flags&SQLITE_OPEN_MAIN_DB); | > > > | < < | < | < | > > | | 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 | pWrapper->nData = (4096 + pWrapper->iSize); pWrapper->zData = crash_malloc(pWrapper->nData); if( pWrapper->zData ){ /* os_unix.c contains an assert() that fails if the caller attempts ** to read data from the 512-byte locking region of a file opened ** with the SQLITE_OPEN_MAIN_DB flag. This region of a database file ** never contains valid data anyhow. So avoid doing such a read here. ** ** UPDATE: It also contains an assert() verifying that each call ** to the xRead() method reads less than 128KB of data. */ const int isDb = (flags&SQLITE_OPEN_MAIN_DB); i64 iOff; memset(pWrapper->zData, 0, pWrapper->nData); for(iOff=0; iOff<pWrapper->iSize; iOff += 512){ int nRead = pWrapper->iSize - (int)iOff; if( nRead>512 ) nRead = 512; if( isDb && iOff==PENDING_BYTE ) continue; rc = sqlite3OsRead(pReal, &pWrapper->zData[iOff], nRead, iOff); } }else{ rc = SQLITE_NOMEM; } } if( rc!=SQLITE_OK && pWrapper->pMethod ){ sqlite3OsClose(pFile); |
︙ | ︙ |
Changes to src/test_intarray.h.
︙ | ︙ | |||
72 73 74 75 76 77 78 79 80 81 82 83 84 85 | ** virtual table is dropped. Since the virtual tables are created in the ** TEMP database, they are automatically dropped when the database connection ** closes so the application does not normally need to take any special ** action to free the intarray objects. */ #include "sqlite3.h" /* ** An sqlite3_intarray is an abstract type to stores an instance of ** an integer array. */ typedef struct sqlite3_intarray sqlite3_intarray; /* | > > > > > > > | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | ** virtual table is dropped. Since the virtual tables are created in the ** TEMP database, they are automatically dropped when the database connection ** closes so the application does not normally need to take any special ** action to free the intarray objects. */ #include "sqlite3.h" /* ** Make sure we can call this stuff from C++. */ #ifdef __cplusplus extern "C" { #endif /* ** An sqlite3_intarray is an abstract type to stores an instance of ** an integer array. */ typedef struct sqlite3_intarray sqlite3_intarray; /* |
︙ | ︙ | |||
108 109 110 111 112 113 114 | */ int sqlite3_intarray_bind( sqlite3_intarray *pIntArray, /* The intarray object to bind to */ int nElements, /* Number of elements in the intarray */ sqlite3_int64 *aElements, /* Content of the intarray */ void (*xFree)(void*) /* How to dispose of the intarray when done */ ); | > > > > | 115 116 117 118 119 120 121 122 123 124 125 | */ int sqlite3_intarray_bind( sqlite3_intarray *pIntArray, /* The intarray object to bind to */ int nElements, /* Number of elements in the intarray */ sqlite3_int64 *aElements, /* Content of the intarray */ void (*xFree)(void*) /* How to dispose of the intarray when done */ ); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif |
Changes to src/test_malloc.c.
︙ | ︙ | |||
716 717 718 719 720 721 722 | if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); return TCL_ERROR; } #ifdef SQLITE_MEMDEBUG { const char *zTitle; | < > | 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 | if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "TITLE"); return TCL_ERROR; } #ifdef SQLITE_MEMDEBUG { const char *zTitle; extern int sqlite3MemdebugSettitle(const char*); zTitle = Tcl_GetString(objv[1]); sqlite3MemdebugSettitle(zTitle); } #endif return TCL_OK; } #define MALLOC_LOG_FRAMES 10 |
︙ | ︙ |
Changes to src/test_multiplex.h.
︙ | ︙ | |||
42 43 44 45 46 47 48 49 50 51 52 53 54 55 | ** This file control is used to set the maximum number of chunks ** allowed to be used for a mutliplex file set. */ #define MULTIPLEX_CTRL_ENABLE 214014 #define MULTIPLEX_CTRL_SET_CHUNK_SIZE 214015 #define MULTIPLEX_CTRL_SET_MAX_CHUNKS 214016 /* ** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize() ** ** Use the VFS named zOrigVfsName as the VFS that does the actual work. ** Use the default if zOrigVfsName==NULL. ** ** The multiplex VFS shim is named "multiplex". It will become the default | > > > > | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | ** This file control is used to set the maximum number of chunks ** allowed to be used for a mutliplex file set. */ #define MULTIPLEX_CTRL_ENABLE 214014 #define MULTIPLEX_CTRL_SET_CHUNK_SIZE 214015 #define MULTIPLEX_CTRL_SET_MAX_CHUNKS 214016 #ifdef __cplusplus extern "C" { #endif /* ** CAPI: Initialize the multiplex VFS shim - sqlite3_multiplex_initialize() ** ** Use the VFS named zOrigVfsName as the VFS that does the actual work. ** Use the default if zOrigVfsName==NULL. ** ** The multiplex VFS shim is named "multiplex". It will become the default |
︙ | ︙ | |||
83 84 85 86 87 88 89 90 91 | ** All SQLite database connections must be closed before calling this ** routine. ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ extern int sqlite3_multiplex_shutdown(void); #endif | > > > > | 87 88 89 90 91 92 93 94 95 96 97 98 99 | ** All SQLite database connections must be closed before calling this ** routine. ** ** THIS ROUTINE IS NOT THREADSAFE. Call this routine exactly once while ** shutting down in order to free all remaining multiplex groups. */ extern int sqlite3_multiplex_shutdown(void); #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif |
Changes to src/test_quota.c.
︙ | ︙ | |||
1175 1176 1177 1178 1179 1180 1181 | pGroup->iSize += szNew - pFile->iSize; quotaLeave(); } #if SQLITE_OS_UNIX rc = ftruncate(fileno(p->f), szNew); #endif #if SQLITE_OS_WIN | > > > > > | > | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 | pGroup->iSize += szNew - pFile->iSize; quotaLeave(); } #if SQLITE_OS_UNIX rc = ftruncate(fileno(p->f), szNew); #endif #if SQLITE_OS_WIN # if defined(__MINGW32__) && defined(SQLITE_TEST) /* _chsize_s() is missing from MingW (as of 2012-11-06). Use ** _chsize() as a work-around for testing purposes. */ rc = _chsize(_fileno(p->f), (long)szNew); # else rc = _chsize_s(_fileno(p->f), szNew); # endif #endif if( pFile && rc==0 ){ quotaGroup *pGroup = pFile->pGroup; quotaEnter(); pGroup->iSize += szNew - pFile->iSize; pFile->iSize = szNew; quotaLeave(); |
︙ | ︙ |
Added src/test_sqllog.c.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 | /* ** 2012 November 26 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** ** OVERVIEW ** ** This file contains experimental code used to record data from live ** SQLite applications that may be useful for offline analysis. Specifically: ** ** 1) The initial contents of all database files opened by the ** application, and ** ** 2) All SQL statements executed by the application. ** ** USAGE ** ** To use this module, SQLite must be compiled with the SQLITE_ENABLE_SQLLOG ** pre-processor symbol defined and this file linked into the application ** somehow. ** ** At runtime, logging is enabled by setting environment variable ** SQLITE_SQLLOG_DIR to the name of a directory in which to store logged ** data. The directory must already exist. ** ** Usually, if the application opens the same database file more than once ** (either by attaching it or by using more than one database handle), only ** a single copy is made. This behaviour may be overridden (so that a ** separate copy is taken each time the database file is opened or attached) ** by setting the environment variable SQLITE_SQLLOG_REUSE_FILES to 0. ** ** OUTPUT: ** ** The SQLITE_SQLLOG_DIR is populated with three types of files: ** ** sqllog_N.db - Copies of database files. N may be any integer. ** ** sqllog_N.sql - A list of SQL statements executed by a single ** connection. N may be any integer. ** ** sqllog.idx - An index mapping from integer N to a database ** file name - indicating the full path of the ** database from which sqllog_N.db was copied. ** ** ERROR HANDLING: ** ** This module attempts to make a best effort to continue logging if an ** IO or other error is encountered. For example, if a log file cannot ** be opened logs are not collected for that connection, but other ** logging proceeds as expected. Errors are logged by calling sqlite3_log(). */ #include "sqlite3.h" #include "stdio.h" #include "stdlib.h" #include "string.h" #include "assert.h" #include "sys/types.h" #include "unistd.h" static int getProcessId(void){ #if SQLITE_OS_WIN return (int)_getpid(); #else return (int)getpid(); #endif } #define ENVIRONMENT_VARIABLE1_NAME "SQLITE_SQLLOG_DIR" #define ENVIRONMENT_VARIABLE2_NAME "SQLITE_SQLLOG_REUSE_FILES" /* Assume that all database and database file names are shorted than this. */ #define SQLLOG_NAMESZ 512 /* Maximum number of simultaneous database connections the process may ** open (if any more are opened an error is logged using sqlite3_log() ** and processing is halted). */ #define MAX_CONNECTIONS 256 struct SLConn { int isErr; /* True if an error has occurred */ sqlite3 *db; /* Connection handle */ int iLog; /* First integer value used in file names */ FILE *fd; /* File descriptor for log file */ }; struct SLGlobal { /* Protected by MUTEX_STATIC_MASTER */ sqlite3_mutex *mutex; /* Recursive mutex */ int nConn; /* Size of aConn[] array */ /* Protected by SLGlobal.mutex */ int bReuse; /* True to avoid extra copies of db files */ char zPrefix[SQLLOG_NAMESZ]; /* Prefix for all created files */ char zIdx[SQLLOG_NAMESZ]; /* Full path to *.idx file */ int iNextLog; /* Used to allocate file names */ int iNextDb; /* Used to allocate database file names */ int bRec; /* True if testSqllog() is called rec. */ int iClock; /* Clock value */ struct SLConn aConn[MAX_CONNECTIONS]; } sqllogglobal; /* ** Return true if c is an ASCII whitespace character. */ static int sqllog_isspace(char c){ return (c==' ' || c=='\t' || c=='\n' || c=='\v' || c=='\f' || c=='\r'); } /* ** The first argument points to a nul-terminated string containing an SQL ** command. Before returning, this function sets *pz to point to the start ** of the first token in this command, and *pn to the number of bytes in ** the token. This is used to check if the SQL command is an "ATTACH" or ** not. */ static void sqllogTokenize(const char *z, const char **pz, int *pn){ const char *p = z; int n; /* Skip past any whitespace */ while( sqllog_isspace(*p) ){ p++; } /* Figure out how long the first token is */ *pz = p; n = 0; while( (p[n]>='a' && p[n]<='z') || (p[n]>='A' && p[n]<='Z') ) n++; *pn = n; } /* ** Check if the logs directory already contains a copy of database file ** zFile. If so, return a pointer to the full path of the copy. Otherwise, ** return NULL. ** ** If a non-NULL value is returned, then the caller must arrange to ** eventually free it using sqlite3_free(). */ static char *sqllogFindFile(const char *zFile){ char *zRet = 0; FILE *fd = 0; /* Open the index file for reading */ fd = fopen(sqllogglobal.zIdx, "r"); if( fd==0 ){ sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error in fopen()"); return 0; } /* Loop through each entry in the index file. If zFile is not NULL and the ** entry is a match, then set zRet to point to the filename of the existing ** copy and break out of the loop. */ while( feof(fd)==0 ){ char zLine[SQLLOG_NAMESZ*2+5]; if( fgets(zLine, sizeof(zLine), fd) ){ int n; char *z; zLine[sizeof(zLine)-1] = '\0'; z = zLine; while( *z>='0' && *z<='9' ) z++; while( *z==' ' ) z++; n = strlen(z); while( n>0 && sqllog_isspace(z[n-1]) ) n--; if( n==strlen(zFile) && 0==memcmp(zFile, z, n) ){ char zBuf[16]; memset(zBuf, 0, sizeof(zBuf)); z = zLine; while( *z>='0' && *z<='9' ){ zBuf[z-zLine] = *z; z++; } zRet = sqlite3_mprintf("%s_%s.db", sqllogglobal.zPrefix, zBuf); break; } } } if( ferror(fd) ){ sqlite3_log(SQLITE_IOERR, "sqllogFindFile(): error reading index file"); } fclose(fd); return zRet; } static int sqllogFindAttached( struct SLConn *p, /* Database connection */ const char *zSearch, /* Name to search for (or NULL) */ char *zName, /* OUT: Name of attached database */ char *zFile /* OUT: Name of attached file */ ){ sqlite3_stmt *pStmt; int rc; /* The "PRAGMA database_list" command returns a list of databases in the ** order that they were attached. So a newly attached database is ** described by the last row returned. */ assert( sqllogglobal.bRec==0 ); sqllogglobal.bRec = 1; rc = sqlite3_prepare_v2(p->db, "PRAGMA database_list", -1, &pStmt, 0); if( rc==SQLITE_OK ){ while( SQLITE_ROW==sqlite3_step(pStmt) ){ const char *zVal1; int nVal1; const char *zVal2; int nVal2; zVal1 = (const char*)sqlite3_column_text(pStmt, 1); nVal1 = sqlite3_column_bytes(pStmt, 1); memcpy(zName, zVal1, nVal1+1); zVal2 = (const char*)sqlite3_column_text(pStmt, 2); nVal2 = sqlite3_column_bytes(pStmt, 2); memcpy(zFile, zVal2, nVal2+1); if( zSearch && strlen(zSearch)==nVal1 && 0==sqlite3_strnicmp(zSearch, zVal1, nVal1) ){ break; } } rc = sqlite3_finalize(pStmt); } sqllogglobal.bRec = 0; if( rc!=SQLITE_OK ){ sqlite3_log(rc, "sqllogFindAttached(): error in \"PRAGMA database_list\""); } return rc; } /* ** Parameter zSearch is the name of a database attached to the database ** connection associated with the first argument. This function creates ** a backup of this database in the logs directory. ** ** The name used for the backup file is automatically generated. Call ** it zFile. ** ** If the bLog parameter is true, then a statement of the following form ** is written to the log file associated with *p: ** ** ATTACH 'zFile' AS 'zName'; ** ** Otherwise, if bLog is false, a comment is added to the log file: ** ** -- Main database file is 'zFile' ** ** The SLGlobal.mutex mutex is always held when this function is called. */ static void sqllogCopydb(struct SLConn *p, const char *zSearch, int bLog){ char zName[SQLLOG_NAMESZ]; /* Attached database name */ char zFile[SQLLOG_NAMESZ]; /* Database file name */ char *zFree; char *zInit = 0; int rc; rc = sqllogFindAttached(p, zSearch, zName, zFile); if( rc!=SQLITE_OK ) return; if( zFile[0]=='\0' ){ zInit = sqlite3_mprintf(""); }else{ if( sqllogglobal.bReuse ){ zInit = sqllogFindFile(zFile); }else{ zInit = 0; } if( zInit==0 ){ int rc; sqlite3 *copy = 0; int iDb; /* Generate a file-name to use for the copy of this database */ iDb = sqllogglobal.iNextDb++; zInit = sqlite3_mprintf("%s_%d.db", sqllogglobal.zPrefix, iDb); /* Create the backup */ assert( sqllogglobal.bRec==0 ); sqllogglobal.bRec = 1; rc = sqlite3_open(zInit, ©); if( rc==SQLITE_OK ){ sqlite3_backup *pBak; sqlite3_exec(copy, "PRAGMA synchronous = 0", 0, 0, 0); pBak = sqlite3_backup_init(copy, "main", p->db, zName); if( pBak ){ sqlite3_backup_step(pBak, -1); rc = sqlite3_backup_finish(pBak); }else{ rc = sqlite3_errcode(copy); } sqlite3_close(copy); } sqllogglobal.bRec = 0; if( rc==SQLITE_OK ){ /* Write an entry into the database index file */ FILE *fd = fopen(sqllogglobal.zIdx, "a"); if( fd ){ fprintf(fd, "%d %s\n", iDb, zFile); fclose(fd); } }else{ sqlite3_log(rc, "sqllogCopydb(): error backing up database"); } } } if( bLog ){ zFree = sqlite3_mprintf("ATTACH '%q' AS '%q'; -- clock=%d\n", zInit, zName, sqllogglobal.iClock++ ); }else{ zFree = sqlite3_mprintf("-- Main database is '%q'\n", zInit); } fprintf(p->fd, "%s", zFree); sqlite3_free(zFree); sqlite3_free(zInit); } /* ** If it is not already open, open the log file for connection *p. ** ** The SLGlobal.mutex mutex is always held when this function is called. */ static void sqllogOpenlog(struct SLConn *p){ /* If the log file has not yet been opened, open it now. */ if( p->fd==0 ){ char *zLog; /* If it is still NULL, have global.zPrefix point to a copy of ** environment variable $ENVIRONMENT_VARIABLE1_NAME. */ if( sqllogglobal.zPrefix[0]==0 ){ FILE *fd; char *zVar = getenv(ENVIRONMENT_VARIABLE1_NAME); if( zVar==0 || strlen(zVar)+10>=(sizeof(sqllogglobal.zPrefix)) ) return; sprintf(sqllogglobal.zPrefix, "%s/sqllog_%d", zVar, getProcessId()); sprintf(sqllogglobal.zIdx, "%s.idx", sqllogglobal.zPrefix); if( getenv(ENVIRONMENT_VARIABLE2_NAME) ){ sqllogglobal.bReuse = atoi(getenv(ENVIRONMENT_VARIABLE2_NAME)); } fd = fopen(sqllogglobal.zIdx, "w"); if( fd ) fclose(fd); } /* Open the log file */ zLog = sqlite3_mprintf("%s_%d.sql", sqllogglobal.zPrefix, p->iLog); p->fd = fopen(zLog, "w"); sqlite3_free(zLog); if( p->fd==0 ){ sqlite3_log(SQLITE_IOERR, "sqllogOpenlog(): Failed to open log file"); } } } /* ** This function is called if the SQLLOG callback is invoked to report ** execution of an SQL statement. Parameter p is the connection the statement ** was executed by and parameter zSql is the text of the statement itself. */ static void testSqllogStmt(struct SLConn *p, const char *zSql){ const char *zFirst; /* Pointer to first token in zSql */ int nFirst; /* Size of token zFirst in bytes */ sqllogTokenize(zSql, &zFirst, &nFirst); if( nFirst!=6 || 0!=sqlite3_strnicmp("ATTACH", zFirst, 6) ){ /* Not an ATTACH statement. Write this directly to the log. */ fprintf(p->fd, "%s; -- clock=%d\n", zSql, sqllogglobal.iClock++); }else{ /* This is an ATTACH statement. Copy the database. */ sqllogCopydb(p, 0, 1); } } /* ** The SQLITE_CONFIG_SQLLOG callback registered by sqlite3_init_sqllog(). */ static void testSqllog(void *pCtx, sqlite3 *db, const char *zSql, int eType){ struct SLConn *p = 0; sqlite3_mutex *master = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER); assert( eType==0 || eType==1 || eType==2 ); assert( (eType==2)==(zSql==0) ); /* This is a database open command. */ if( eType==0 ){ sqlite3_mutex_enter(master); if( sqllogglobal.mutex==0 ){ sqllogglobal.mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_RECURSIVE); } p = &sqllogglobal.aConn[sqllogglobal.nConn++]; p->fd = 0; p->db = db; p->iLog = sqllogglobal.iNextLog++; sqlite3_mutex_leave(master); /* Open the log and take a copy of the main database file */ sqlite3_mutex_enter(sqllogglobal.mutex); if( sqllogglobal.bRec==0 ){ sqllogOpenlog(p); if( p->fd ) sqllogCopydb(p, "main", 0); } sqlite3_mutex_leave(sqllogglobal.mutex); } else{ int i; for(i=0; i<sqllogglobal.nConn; i++){ p = &sqllogglobal.aConn[i]; if( p->db==db ) break; } if( i==sqllogglobal.nConn ) return; /* A database handle close command */ if( eType==2 ){ sqlite3_mutex_enter(master); if( p->fd ) fclose(p->fd); p->db = 0; p->fd = 0; sqllogglobal.nConn--; if( sqllogglobal.nConn==0 ){ sqlite3_mutex_free(sqllogglobal.mutex); sqllogglobal.mutex = 0; }else{ int nShift = &sqllogglobal.aConn[sqllogglobal.nConn] - p; if( nShift>0 ){ memmove(p, &p[1], nShift*sizeof(struct SLConn)); } } sqlite3_mutex_leave(master); /* An ordinary SQL command. */ }else if( p->fd ){ sqlite3_mutex_enter(sqllogglobal.mutex); if( sqllogglobal.bRec==0 ){ testSqllogStmt(p, zSql); } sqlite3_mutex_leave(sqllogglobal.mutex); } } } /* ** This function is called either before sqlite3_initialized() or by it. ** It checks if the SQLITE_SQLLOG_DIR variable is defined, and if so ** registers an SQLITE_CONFIG_SQLLOG callback to record the applications ** database activity. */ void sqlite3_init_sqllog(void){ if( getenv(ENVIRONMENT_VARIABLE1_NAME) ){ if( SQLITE_OK==sqlite3_config(SQLITE_CONFIG_SQLLOG, testSqllog, 0) ){ memset(&sqllogglobal, 0, sizeof(sqllogglobal)); sqllogglobal.bReuse = 1; } } } |
Changes to src/test_vfstrace.c.
︙ | ︙ | |||
471 472 473 474 475 476 477 478 479 480 481 482 483 484 | } case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break; case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break; case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break; case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break; case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; case 0xca093fa0: zOp = "DB_UNCHANGED"; break; case SQLITE_FCNTL_PRAGMA: { const char *const* a = (const char*const*)pArg; sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]); zOp = zBuf; break; } | > | 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 | } case SQLITE_FCNTL_FILE_POINTER: zOp = "FILE_POINTER"; break; case SQLITE_FCNTL_SYNC_OMITTED: zOp = "SYNC_OMITTED"; break; case SQLITE_FCNTL_WIN32_AV_RETRY: zOp = "WIN32_AV_RETRY"; break; case SQLITE_FCNTL_PERSIST_WAL: zOp = "PERSIST_WAL"; break; case SQLITE_FCNTL_OVERWRITE: zOp = "OVERWRITE"; break; case SQLITE_FCNTL_VFSNAME: zOp = "VFSNAME"; break; case SQLITE_FCNTL_TEMPFILENAME: zOp = "TEMPFILENAME"; break; case 0xca093fa0: zOp = "DB_UNCHANGED"; break; case SQLITE_FCNTL_PRAGMA: { const char *const* a = (const char*const*)pArg; sqlite3_snprintf(sizeof(zBuf), zBuf, "PRAGMA,[%s,%s]",a[1],a[2]); zOp = zBuf; break; } |
︙ | ︙ | |||
492 493 494 495 496 497 498 | pInfo->zVfsName, p->zFName, zOp); rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); vfstrace_print_errcode(pInfo, " -> %s\n", rc); if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z", pInfo->zVfsName, *(char**)pArg); } | > | | 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | pInfo->zVfsName, p->zFName, zOp); rc = p->pReal->pMethods->xFileControl(p->pReal, op, pArg); vfstrace_print_errcode(pInfo, " -> %s\n", rc); if( op==SQLITE_FCNTL_VFSNAME && rc==SQLITE_OK ){ *(char**)pArg = sqlite3_mprintf("vfstrace.%s/%z", pInfo->zVfsName, *(char**)pArg); } if( (op==SQLITE_FCNTL_PRAGMA || op==SQLITE_FCNTL_TEMPFILENAME) && rc==SQLITE_OK && *(char**)pArg ){ vfstrace_printf(pInfo, "%s.xFileControl(%s,%s) returns %s", pInfo->zVfsName, p->zFName, zOp, *(char**)pArg); } return rc; } /* |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
724 725 726 727 728 729 730 731 732 733 734 735 736 737 | ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); ** END; ** ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), | > > > > > > > > > | 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 | ** INSERT OR REPLACE INTO t2 VALUES(new.a, new.b); ** END; ** ** INSERT INTO t1 ... ; -- insert into t2 uses REPLACE policy ** INSERT OR IGNORE INTO t1 ... ; -- insert into t2 uses IGNORE policy */ pParse->eOrconf = (orconf==OE_Default)?pStep->orconf:(u8)orconf; /* Clear the cookieGoto flag. When coding triggers, the cookieGoto ** variable is used as a flag to indicate to sqlite3ExprCodeConstants() ** that it is not safe to refactor constants (this happens after the ** start of the first loop in the SQL statement is coded - at that ** point code may be conditionally executed, so it is no longer safe to ** initialize constant register values). */ assert( pParse->cookieGoto==0 || pParse->cookieGoto==-1 ); pParse->cookieGoto = 0; switch( pStep->op ){ case TK_UPDATE: { sqlite3Update(pParse, targetSrcList(pParse, pStep), sqlite3ExprListDup(db, pStep->pExprList, 0), sqlite3ExprDup(db, pStep->pWhere, 0), |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
418 419 420 421 422 423 424 | #endif #ifdef SQLITE_DEBUG /* ** Print the value of a register for tracing purposes: */ static void memTracePrint(FILE *out, Mem *p){ | | > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 | #endif #ifdef SQLITE_DEBUG /* ** Print the value of a register for tracing purposes: */ static void memTracePrint(FILE *out, Mem *p){ if( p->flags & MEM_Invalid ){ fprintf(out, " undefined"); }else if( p->flags & MEM_Null ){ fprintf(out, " NULL"); }else if( (p->flags & (MEM_Int|MEM_Str))==(MEM_Int|MEM_Str) ){ fprintf(out, " si:%lld", p->u.i); }else if( p->flags & MEM_Int ){ fprintf(out, " i:%lld", p->u.i); #ifndef SQLITE_OMIT_FLOATING_POINT }else if( p->flags & MEM_Real ){ |
︙ | ︙ | |||
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 | n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); while( 1 ){ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); if( (n--)==0 ) break; pOut++; pIn1++; } break; } | > > > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 | n = pOp->p3; pIn1 = &aMem[pOp->p1]; pOut = &aMem[pOp->p2]; assert( pOut!=pIn1 ); while( 1 ){ sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem); Deephemeralize(pOut); #ifdef SQLITE_DEBUG pOut->pScopyFrom = 0; #endif REGISTER_TRACE(pOp->p2+pOp->p3-n, pOut); if( (n--)==0 ) break; pOut++; pIn1++; } break; } |
︙ | ︙ | |||
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 | ** If either operand is NULL, the result is NULL. */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ pIn1 = &aMem[pOp->p1]; applyNumericAffinity(pIn1); pIn2 = &aMem[pOp->p2]; applyNumericAffinity(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ iA = pIn1->u.i; iB = pIn2->u.i; switch( pOp->opcode ){ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; case OP_Divide: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; iB /= iA; break; } default: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 ) iA = 1; iB %= iA; break; } } pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); }else{ fp_math: rA = sqlite3VdbeRealValue(pIn1); rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ case OP_Add: rB += rA; break; case OP_Subtract: rB -= rA; break; case OP_Multiply: rB *= rA; break; | > > > | 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 | ** If either operand is NULL, the result is NULL. */ case OP_Add: /* same as TK_PLUS, in1, in2, out3 */ case OP_Subtract: /* same as TK_MINUS, in1, in2, out3 */ case OP_Multiply: /* same as TK_STAR, in1, in2, out3 */ case OP_Divide: /* same as TK_SLASH, in1, in2, out3 */ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */ char bIntint; /* Started out as two integer operands */ int flags; /* Combined MEM_* flags from both inputs */ i64 iA; /* Integer value of left operand */ i64 iB; /* Integer value of right operand */ double rA; /* Real value of left operand */ double rB; /* Real value of right operand */ pIn1 = &aMem[pOp->p1]; applyNumericAffinity(pIn1); pIn2 = &aMem[pOp->p2]; applyNumericAffinity(pIn2); pOut = &aMem[pOp->p3]; flags = pIn1->flags | pIn2->flags; if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null; if( (pIn1->flags & pIn2->flags & MEM_Int)==MEM_Int ){ iA = pIn1->u.i; iB = pIn2->u.i; bIntint = 1; switch( pOp->opcode ){ case OP_Add: if( sqlite3AddInt64(&iB,iA) ) goto fp_math; break; case OP_Subtract: if( sqlite3SubInt64(&iB,iA) ) goto fp_math; break; case OP_Multiply: if( sqlite3MulInt64(&iB,iA) ) goto fp_math; break; case OP_Divide: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 && iB==SMALLEST_INT64 ) goto fp_math; iB /= iA; break; } default: { if( iA==0 ) goto arithmetic_result_is_null; if( iA==-1 ) iA = 1; iB %= iA; break; } } pOut->u.i = iB; MemSetTypeFlag(pOut, MEM_Int); }else{ bIntint = 0; fp_math: rA = sqlite3VdbeRealValue(pIn1); rB = sqlite3VdbeRealValue(pIn2); switch( pOp->opcode ){ case OP_Add: rB += rA; break; case OP_Subtract: rB -= rA; break; case OP_Multiply: rB *= rA; break; |
︙ | ︙ | |||
1328 1329 1330 1331 1332 1333 1334 | MemSetTypeFlag(pOut, MEM_Int); #else if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); | | | 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 | MemSetTypeFlag(pOut, MEM_Int); #else if( sqlite3IsNaN(rB) ){ goto arithmetic_result_is_null; } pOut->r = rB; MemSetTypeFlag(pOut, MEM_Real); if( (flags & MEM_Real)==0 && !bIntint ){ sqlite3VdbeIntegerAffinity(pOut); } #endif } break; arithmetic_result_is_null: |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 | } /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array ** of integers in P4. ** | | | | | > > > > > > | 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 | } /* Opcode: Permutation * * * P4 * ** ** Set the permutation used by the OP_Compare operator to be the array ** of integers in P4. ** ** The permutation is only valid until the next OP_Compare that has ** the OPFLAG_PERMUTE bit set in P5. Typically the OP_Permutation should ** occur immediately prior to the OP_Compare. */ case OP_Permutation: { assert( pOp->p4type==P4_INTARRAY ); assert( pOp->p4.ai ); aPermute = pOp->p4.ai; break; } /* Opcode: Compare P1 P2 P3 P4 P5 ** ** Compare two vectors of registers in reg(P1)..reg(P1+P3-1) (call this ** vector "A") and in reg(P2)..reg(P2+P3-1) ("B"). Save the result of ** the comparison for use by the next OP_Jump instruct. ** ** If P5 has the OPFLAG_PERMUTE bit set, then the order of comparison is ** determined by the most recent OP_Permutation operator. If the ** OPFLAG_PERMUTE bit is clear, then register are compared in sequential ** order. ** ** P4 is a KeyInfo structure that defines collating sequences and sort ** orders for the comparison. The permutation applies to registers ** only. The KeyInfo elements are used sequentially. ** ** The comparison is a sort comparison, so NULLs compare equal, ** NULLs are less than numbers, numbers are less than strings, ** and strings are less than blobs. */ case OP_Compare: { int n; int i; int p1; int p2; const KeyInfo *pKeyInfo; int idx; CollSeq *pColl; /* Collating sequence to use on this term */ int bRev; /* True for DESCENDING sort order */ if( (pOp->p5 & OPFLAG_PERMUTE)==0 ) aPermute = 0; n = pOp->p3; pKeyInfo = pOp->p4.pKeyInfo; assert( n>0 ); assert( pKeyInfo!=0 ); p1 = pOp->p1; p2 = pOp->p2; #if SQLITE_DEBUG |
︙ | ︙ | |||
2061 2062 2063 2064 2065 2066 2067 | break; } /* Opcode: Once P1 P2 * * * ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, ** set the flag and fall through to the next instruction. | < < | 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 | break; } /* Opcode: Once P1 P2 * * * ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, ** set the flag and fall through to the next instruction. */ case OP_Once: { /* jump */ assert( pOp->p1<p->nOnceFlag ); if( p->aOnceFlag[pOp->p1] ){ pc = pOp->p2-1; }else{ p->aOnceFlag[pOp->p1] = 1; |
︙ | ︙ | |||
2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 | }else{ assert( sqlite3BtreeCursorIsValid(pCrsr) ); VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &payloadSize); assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ } }else if( ALWAYS(pC->pseudoTableReg>0) ){ pReg = &aMem[pC->pseudoTableReg]; assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); payloadSize = pReg->n; zRec = pReg->z; pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; assert( payloadSize==0 || zRec!=0 ); }else{ | > > > > > | 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 | }else{ assert( sqlite3BtreeCursorIsValid(pCrsr) ); VVA_ONLY(rc =) sqlite3BtreeDataSize(pCrsr, &payloadSize); assert( rc==SQLITE_OK ); /* DataSize() cannot fail */ } }else if( ALWAYS(pC->pseudoTableReg>0) ){ pReg = &aMem[pC->pseudoTableReg]; if( pC->multiPseudo ){ sqlite3VdbeMemShallowCopy(pDest, pReg+p2, MEM_Ephem); Deephemeralize(pDest); goto op_column_out; } assert( pReg->flags & MEM_Blob ); assert( memIsValid(pReg) ); payloadSize = pReg->n; zRec = pReg->z; pC->cacheStatus = (pOp->p5&OPFLAG_CLEARCACHE) ? CACHE_STALE : p->cacheCtr; assert( payloadSize==0 || zRec!=0 ); }else{ |
︙ | ︙ | |||
3291 3292 3293 3294 3295 3296 3297 | } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); pCx->isIndex = !pCx->isTable; break; } | | | 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 | } } pCx->isOrdered = (pOp->p5!=BTREE_UNORDERED); pCx->isIndex = !pCx->isTable; break; } /* Opcode: SorterOpen P1 P2 * P4 * ** ** This opcode works like OP_OpenEphemeral except that it opens ** a transient index that is specifically designed to sort large ** tables using an external merge-sort algorithm. */ case OP_SorterOpen: { VdbeCursor *pCx; |
︙ | ︙ | |||
3314 3315 3316 3317 3318 3319 3320 | #else pOp->opcode = OP_OpenEphemeral; pc--; #endif break; } | | | | > > | 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 | #else pOp->opcode = OP_OpenEphemeral; pc--; #endif break; } /* Opcode: OpenPseudo P1 P2 P3 * P5 ** ** Open a new cursor that points to a fake table that contains a single ** row of data. The content of that one row in the content of memory ** register P2 when P5==0. In other words, cursor P1 becomes an alias for the ** MEM_Blob content contained in register P2. When P5==1, then the ** row is represented by P3 consecutive registers beginning with P2. ** ** A pseudo-table created by this opcode is used to hold a single ** row output from the sorter so that the row can be decomposed into ** individual columns using the OP_Column opcode. The OP_Column opcode ** is the only cursor opcode that works with a pseudo-table. ** ** P3 is the number of fields in the records that will be stored by ** the pseudo-table. */ case OP_OpenPseudo: { VdbeCursor *pCx; assert( pOp->p1>=0 ); pCx = allocateCursor(p, pOp->p1, pOp->p3, -1, 0); if( pCx==0 ) goto no_mem; pCx->nullRow = 1; pCx->pseudoTableReg = pOp->p2; pCx->isTable = 1; pCx->isIndex = 0; pCx->multiPseudo = pOp->p5; break; } /* Opcode: Close P1 * * * * ** ** Close a cursor previously opened as P1. If P1 is not ** currently open, this instruction is a no-op. |
︙ | ︙ | |||
4303 4304 4305 4306 4307 4308 4309 | i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); | | | 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 | i64 v; sqlite3_vtab *pVtab; const sqlite3_module *pModule; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->pseudoTableReg==0 || pC->nullRow ); if( pC->nullRow ){ pOut->flags = MEM_Null; break; }else if( pC->deferredMoveto ){ v = pC->movetoTarget; #ifndef SQLITE_OMIT_VIRTUALTABLE }else if( pC->pVtabCursor ){ |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
184 185 186 187 188 189 190 | void sqlite3VdbeChangeToNoop(Vdbe*, int addr); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeRunOnlyOnce(Vdbe*); void sqlite3VdbeDelete(Vdbe*); | | | 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | void sqlite3VdbeChangeToNoop(Vdbe*, int addr); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeRunOnlyOnce(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeClearObject(sqlite3*,Vdbe*); void sqlite3VdbeMakeReady(Vdbe*,Parse*); int sqlite3VdbeFinalize(Vdbe*); void sqlite3VdbeResolveLabel(Vdbe*, int); int sqlite3VdbeCurrentAddr(Vdbe*); #ifdef SQLITE_DEBUG int sqlite3VdbeAssertMayAbort(Vdbe *, int); void sqlite3VdbeTrace(Vdbe*,FILE*); |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
59 60 61 62 63 64 65 66 67 68 69 70 71 72 | Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ Bool isSorter; /* True if a new-style sorter */ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ i64 lastRowid; /* Last rowid from a Next or NextIdx operation */ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ | > | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Bool nullRow; /* True if pointing to a row with no data */ Bool deferredMoveto; /* A call to sqlite3BtreeMoveto() is needed */ Bool isTable; /* True if a table requiring integer keys */ Bool isIndex; /* True if an index containing keys only - no data */ Bool isOrdered; /* True if the underlying table is BTREE_UNORDERED */ Bool isSorter; /* True if a new-style sorter */ Bool multiPseudo; /* Multi-register pseudo-cursor */ sqlite3_vtab_cursor *pVtabCursor; /* The cursor for a virtual table */ const sqlite3_module *pModule; /* Module for cursor pVtabCursor */ i64 seqCount; /* Sequence counter */ i64 movetoTarget; /* Argument to the deferred sqlite3BtreeMoveto() */ i64 lastRowid; /* Last rowid from a Next or NextIdx operation */ VdbeSorter *pSorter; /* Sorter object for OP_SorterOpen cursors */ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
49 50 51 52 53 54 55 | /* ** Remember the SQL string for a prepared statement. */ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ assert( isPrepareV2==1 || isPrepareV2==0 ); if( p==0 ) return; | | | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | /* ** Remember the SQL string for a prepared statement. */ void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepareV2){ assert( isPrepareV2==1 || isPrepareV2==0 ); if( p==0 ) return; #if defined(SQLITE_OMIT_TRACE) && !defined(SQLITE_ENABLE_SQLLOG) if( !isPrepareV2 ) return; #endif assert( p->zSql==0 ); p->zSql = sqlite3DbStrNDup(p->db, z, n); p->isPrepareV2 = (u8)isPrepareV2; } |
︙ | ︙ | |||
719 720 721 722 723 724 725 726 727 728 729 730 731 732 | } assert( p->nOp>0 ); assert( addr<p->nOp ); if( addr<0 ){ addr = p->nOp - 1; } pOp = &p->aOp[addr]; freeP4(db, pOp->p4type, pOp->p4.p); pOp->p4.p = 0; if( n==P4_INT32 ){ /* Note: this cast is safe, because the origin data point was an int ** that was cast to a (const char *). */ pOp->p4.i = SQLITE_PTR_TO_INT(zP4); pOp->p4type = P4_INT32; | > | 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 | } assert( p->nOp>0 ); assert( addr<p->nOp ); if( addr<0 ){ addr = p->nOp - 1; } pOp = &p->aOp[addr]; assert( pOp->p4type==P4_NOTUSED || pOp->p4type==P4_INT32 ); freeP4(db, pOp->p4type, pOp->p4.p); pOp->p4.p = 0; if( n==P4_INT32 ){ /* Note: this cast is safe, because the origin data point was an int ** that was cast to a (const char *). */ pOp->p4.i = SQLITE_PTR_TO_INT(zP4); pOp->p4type = P4_INT32; |
︙ | ︙ | |||
861 862 863 864 865 866 867 | int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = sqlite3Strlen30(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; | | | | | | | | | | | | | < < < < | 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 | int i, j; KeyInfo *pKeyInfo = pOp->p4.pKeyInfo; assert( pKeyInfo->aSortOrder!=0 ); sqlite3_snprintf(nTemp, zTemp, "keyinfo(%d", pKeyInfo->nField); i = sqlite3Strlen30(zTemp); for(j=0; j<pKeyInfo->nField; j++){ CollSeq *pColl = pKeyInfo->aColl[j]; const char *zColl = pColl ? pColl->zName : "nil"; int n = sqlite3Strlen30(zColl); if( i+n>nTemp-6 ){ memcpy(&zTemp[i],",...",4); break; } zTemp[i++] = ','; if( pKeyInfo->aSortOrder[j] ){ zTemp[i++] = '-'; } memcpy(&zTemp[i], zColl, n+1); i += n; } zTemp[i++] = ')'; zTemp[i] = 0; assert( i<nTemp ); break; } case P4_COLLSEQ: { |
︙ | ︙ | |||
2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 | db->errCode = rc; }else{ sqlite3Error(db, rc, 0); } return rc; } /* ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. ** ** After this routine is run, the VDBE should be ready to be executed ** again. ** | > > > > > > > > > > > > > > > > > > > > > | 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 | db->errCode = rc; }else{ sqlite3Error(db, rc, 0); } return rc; } #ifdef SQLITE_ENABLE_SQLLOG /* ** If an SQLITE_CONFIG_SQLLOG hook is registered and the VM has been run, ** invoke it. */ static void vdbeInvokeSqllog(Vdbe *v){ if( sqlite3GlobalConfig.xSqllog && v->rc==SQLITE_OK && v->zSql && v->pc>=0 ){ char *zExpanded = sqlite3VdbeExpandSql(v, v->zSql); assert( v->db->init.busy==0 ); if( zExpanded ){ sqlite3GlobalConfig.xSqllog( sqlite3GlobalConfig.pSqllogArg, v->db, zExpanded, 1 ); sqlite3DbFree(v->db, zExpanded); } } } #else # define vdbeInvokeSqllog(x) #endif /* ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. ** ** After this routine is run, the VDBE should be ready to be executed ** again. ** |
︙ | ︙ | |||
2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 | /* If the VDBE has be run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But ** if the VDBE has just been set to run but has not actually executed any ** instructions yet, leave the main database error information unchanged. */ if( p->pc>=0 ){ sqlite3VdbeTransferError(p); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; if( p->runOnlyOnce ) p->expired = 1; }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was | > | 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 | /* If the VDBE has be run even partially, then transfer the error code ** and error message from the VDBE into the main database structure. But ** if the VDBE has just been set to run but has not actually executed any ** instructions yet, leave the main database error information unchanged. */ if( p->pc>=0 ){ vdbeInvokeSqllog(p); sqlite3VdbeTransferError(p); sqlite3DbFree(db, p->zErrMsg); p->zErrMsg = 0; if( p->runOnlyOnce ) p->expired = 1; }else if( p->rc && p->expired ){ /* The expired flag was set on the VDBE before the first call ** to sqlite3_step(). For consistency (since sqlite3_step() was |
︙ | ︙ | |||
2430 2431 2432 2433 2434 2435 2436 | } pAux->pAux = 0; } } } /* | | > > | | | < > | | 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 | } pAux->pAux = 0; } } } /* ** Free all memory associated with the Vdbe passed as the second argument, ** except for object itself, which is preserved. ** ** The difference between this function and sqlite3VdbeDelete() is that ** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with ** the database connection and frees the object itself. */ void sqlite3VdbeClearObject(sqlite3 *db, Vdbe *p){ SubProgram *pSub, *pNext; int i; assert( p->db==0 || p->db==db ); releaseMemArray(p->aVar, p->nVar); releaseMemArray(p->aColName, p->nResColumn*COLNAME_N); for(pSub=p->pProgram; pSub; pSub=pNext){ pNext = pSub->pNext; vdbeFreeOpArray(db, pSub->aOp, pSub->nOp); sqlite3DbFree(db, pSub); } for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aLabel); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); #if defined(SQLITE_ENABLE_TREE_EXPLAIN) sqlite3_free(p->zExplain); sqlite3DbFree(db, p->pExplain); #endif } /* ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; if( NEVER(p==0) ) return; db = p->db; assert( sqlite3_mutex_held(db->mutex) ); sqlite3VdbeClearObject(db, p); if( p->pPrev ){ p->pPrev->pNext = p->pNext; }else{ assert( db->pVdbe==p ); db->pVdbe = p->pNext; } if( p->pNext ){ p->pNext->pPrev = p->pPrev; } p->magic = VDBE_MAGIC_DEAD; p->db = 0; sqlite3DbFree(db, p); } /* ** Make sure the cursor p is ready to read or write the row to which it ** was last positioned. Return an error code if an OOM fault or I/O error ** prevents us from positioning the cursor to its correct position. ** |
︙ | ︙ |
Changes to src/vdbesort.c.
︙ | ︙ | |||
191 192 193 194 195 196 197 | ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ iBuf = p->iReadOff % p->nBuffer; if( iBuf==0 ){ int nRead; /* Bytes to read from disk */ int rc; /* sqlite3OsRead() return code */ /* Determine how many bytes of data to read. */ | | | > > > | 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | ** than p->nBuffer bytes remaining in the PMA, read all remaining data. */ iBuf = p->iReadOff % p->nBuffer; if( iBuf==0 ){ int nRead; /* Bytes to read from disk */ int rc; /* sqlite3OsRead() return code */ /* Determine how many bytes of data to read. */ if( (p->iEof - p->iReadOff) > (i64)p->nBuffer ){ nRead = p->nBuffer; }else{ nRead = (int)(p->iEof - p->iReadOff); } assert( nRead>0 ); /* Read data from the file. Return early if an error occurs. */ rc = sqlite3OsRead(p->pFile, p->aBuffer, nRead, p->iReadOff); assert( rc!=SQLITE_IOERR_SHORT_READ ); if( rc!=SQLITE_OK ) return rc; } |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
491 492 493 494 495 496 497 | if( !pVTable ){ sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM; } pVTable->db = db; pVTable->pMod = pMod; | < < | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 | if( !pVTable ){ sqlite3DbFree(db, zModuleName); return SQLITE_NOMEM; } pVTable->db = db; pVTable->pMod = pMod; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pTab->azModuleArg[1] = db->aDb[iDb].zName; /* Invoke the virtual table constructor */ assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; pPriorCtx = db->pVtabCtx; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); db->pVtabCtx = pPriorCtx; if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); }else { *pzErr = sqlite3MPrintf(db, "%s", zErr); sqlite3_free(zErr); |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
559 560 561 562 563 564 565 | */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** | > | | | | | > > > > > | | < > | > | > > | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 | */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** ** If left/right precendence rules come into play when determining the ** collating ** side of the comparison, it remains associated with the same side after ** the commutation. So "Y collate NOCASE op X" becomes ** "X op Y". This is because any collation sequence on ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_Collate flag ** is not commuted. */ static void exprCommute(Parse *pParse, Expr *pExpr){ u16 expRight = (pExpr->pRight->flags & EP_Collate); u16 expLeft = (pExpr->pLeft->flags & EP_Collate); assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); if( expRight==expLeft ){ /* Either X and Y both have COLLATE operator or neither do */ if( expRight ){ /* Both X and Y have COLLATE operators. Make sure X is always ** used by clearing the EP_Collate flag from Y. */ pExpr->pRight->flags &= ~EP_Collate; }else if( sqlite3ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ /* Neither X nor Y have COLLATE operators, but X has a non-default ** collating sequence. So add the EP_Collate marker on X to cause ** it to be searched first. */ pExpr->pLeft->flags |= EP_Collate; } } SWAP(Expr*,pExpr->pRight,pExpr->pLeft); if( pExpr->op>=TK_GT ){ assert( TK_LT==TK_GT+2 ); assert( TK_GE==TK_LE+2 ); assert( TK_GT>TK_EQ ); assert( TK_GT<TK_LE ); assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); |
︙ | ︙ | |||
652 653 654 655 656 657 658 | /* Figure out the collation sequence required from an index for ** it to be useful for optimising expression pX. Store this ** value in variable pColl. */ assert(pX->pLeft); pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); | | | | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | /* Figure out the collation sequence required from an index for ** it to be useful for optimising expression pX. Store this ** value in variable pColl. */ assert(pX->pLeft); pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); if( pColl==0 ) pColl = pParse->db->pDfltColl; for(j=0; pIdx->aiColumn[j]!=iColumn; j++){ if( NEVER(j>=pIdx->nColumn) ) return 0; } if( sqlite3StrICmp(pColl->zName, pIdx->azColl[j]) ) continue; } return pTerm; } } } return 0; } |
︙ | ︙ | |||
1175 1176 1177 1178 1179 1180 1181 | sqlite3 *db = pParse->db; /* Database connection */ if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; pMaskSet = pWC->pMaskSet; | | | 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 | sqlite3 *db = pParse->db; /* Database connection */ if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; pMaskSet = pWC->pMaskSet; pExpr = sqlite3ExprSkipCollate(pTerm->pExpr); prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect); }else{ |
︙ | ︙ | |||
1202 1203 1204 1205 1206 1207 1208 | ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ | | | | 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 | ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) && (pTerm->prereqRight & prereqLeft)==0 ){ Expr *pLeft = sqlite3ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite3ExprSkipCollate(pExpr->pRight); if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op); } if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; |
︙ | ︙ | |||
1231 1232 1233 1234 1235 1236 1237 | pTerm->nChild = 1; pTerm->wtFlags |= TERM_COPIED; }else{ pDup = pExpr; pNew = pTerm; } exprCommute(pParse, pDup); | | | 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 | pTerm->nChild = 1; pTerm->wtFlags |= TERM_COPIED; }else{ pDup = pExpr; pNew = pTerm; } exprCommute(pParse, pDup); pLeft = sqlite3ExprSkipCollate(pDup->pLeft); pNew->leftCursor = pLeft->iTable; pNew->u.leftColumn = pLeft->iColumn; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = operatorMask(pDup->op); } |
︙ | ︙ | |||
1310 1311 1312 1313 1314 1315 1316 | ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; | | | 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; Token sCollSeqName; /* Name of collating sequence */ pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite3ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; /* Last character before the first wildcard */ pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1]; c = *pC; |
︙ | ︙ | |||
1332 1333 1334 1335 1336 1337 1338 | if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ c = sqlite3UpperToLower[c]; } *pC = c + 1; } | | > > | | > | | | 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 | if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ c = sqlite3UpperToLower[c]; } *pC = c + 1; } sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; sCollSeqName.n = 6; pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName), pStr1, 0); idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName), pStr2, 0); idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; if( isComplete ){ pWC->a[idxNew1].iParent = idxTerm; pWC->a[idxNew2].iParent = idxTerm; |
︙ | ︙ | |||
1459 1460 1461 1462 1463 1464 1465 | Index *pIdx, /* Index to match column of */ int iCol /* Column of index to match */ ){ int i; const char *zColl = pIdx->azColl[iCol]; for(i=0; i<pList->nExpr; i++){ | | | | 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 | Index *pIdx, /* Index to match column of */ int iCol /* Column of index to match */ ){ int i; const char *zColl = pIdx->azColl[iCol]; for(i=0; i<pList->nExpr; i++){ Expr *p = sqlite3ExprSkipCollate(pList->a[i].pExpr); if( p->op==TK_COLUMN && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase ){ CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr); if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){ return i; } } } return -1; |
︙ | ︙ | |||
1511 1512 1513 1514 1515 1516 1517 | ** can be ignored. If it does not, and the column does not belong to the ** same table as index pIdx, return early. Finally, if there is no ** matching "col=X" expression and the column is on the same table as pIdx, ** set the corresponding bit in variable mask. */ for(i=0; i<pDistinct->nExpr; i++){ WhereTerm *pTerm; | | | 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 | ** can be ignored. If it does not, and the column does not belong to the ** same table as index pIdx, return early. Finally, if there is no ** matching "col=X" expression and the column is on the same table as pIdx, ** set the corresponding bit in variable mask. */ for(i=0; i<pDistinct->nExpr; i++){ WhereTerm *pTerm; Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); if( p->op!=TK_COLUMN ) return 0; pTerm = findTerm(pWC, p->iTable, p->iColumn, ~(Bitmask)0, WO_EQ, 0); if( pTerm ){ Expr *pX = pTerm->pExpr; CollSeq *p1 = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); CollSeq *p2 = sqlite3ExprCollSeq(pParse, p); if( p1==p2 ) continue; |
︙ | ︙ | |||
1563 1564 1565 1566 1567 1568 1569 | pTab = pTabList->a[0].pTab; /* If any of the expressions is an IPK column on table iBase, then return ** true. Note: The (p->iTable==iBase) part of this test may be false if the ** current SELECT is a correlated sub-query. */ for(i=0; i<pDistinct->nExpr; i++){ | | | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 | pTab = pTabList->a[0].pTab; /* If any of the expressions is an IPK column on table iBase, then return ** true. Note: The (p->iTable==iBase) part of this test may be false if the ** current SELECT is a correlated sub-query. */ for(i=0; i<pDistinct->nExpr; i++){ Expr *p = sqlite3ExprSkipCollate(pDistinct->a[i].pExpr); if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; } /* Loop through all indices on the table, checking each to see if it makes ** the DISTINCT qualifier redundant. It does so if: ** ** 1. The index is itself UNIQUE, and |
︙ | ︙ | |||
1811 1812 1813 1814 1815 1816 1817 | /* There is no point in building an automatic index for a single scan */ return; } if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){ /* Automatic indices are disabled at run-time */ return; } | | > > > > > > | 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 | /* There is no point in building an automatic index for a single scan */ return; } if( (pParse->db->flags & SQLITE_AutoIndex)==0 ){ /* Automatic indices are disabled at run-time */ return; } if( (p->cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0 && (p->cost.plan.wsFlags & WHERE_COVER_SCAN)==0 ){ /* We already have some kind of index in use for this query. */ return; } if( pSrc->viaCoroutine ){ /* Cannot index a co-routine */ return; } if( pSrc->notIndexed ){ /* The NOT INDEXED clause appears in the SQL. */ return; } if( pSrc->isCorrelated ){ /* The source is a correlated sub-query. No point in indexing it. */ |
︙ | ︙ | |||
2871 2872 2873 2874 2875 2876 2877 | int isMatch; /* ORDER BY term matches the index term */ const char *zColl; /* Name of collating sequence for i-th index term */ WhereTerm *pConstraint; /* A constraint in the WHERE clause */ /* If the next term of the ORDER BY clause refers to anything other than ** a column in the "base" table, then this index will not be of any ** further use in handling the ORDER BY. */ | | | 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 | int isMatch; /* ORDER BY term matches the index term */ const char *zColl; /* Name of collating sequence for i-th index term */ WhereTerm *pConstraint; /* A constraint in the WHERE clause */ /* If the next term of the ORDER BY clause refers to anything other than ** a column in the "base" table, then this index will not be of any ** further use in handling the ORDER BY. */ pOBExpr = sqlite3ExprSkipCollate(pOBItem->pExpr); if( pOBExpr->op!=TK_COLUMN || pOBExpr->iTable!=base ){ break; } /* Find column number and collating sequence for the next entry ** in the index */ if( pIdx->zName && i<pIdx->nColumn ){ |
︙ | ︙ | |||
2897 2898 2899 2900 2901 2902 2903 | } /* Check to see if the column number and collating sequence of the ** index match the column number and collating sequence of the ORDER BY ** clause entry. Set isMatch to 1 if they both match. */ if( pOBExpr->iColumn==iColumn ){ if( zColl ){ | | | 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 | } /* Check to see if the column number and collating sequence of the ** index match the column number and collating sequence of the ORDER BY ** clause entry. Set isMatch to 1 if they both match. */ if( pOBExpr->iColumn==iColumn ){ if( zColl ){ pColl = sqlite3ExprCollSeq(pParse, pOBItem->pExpr); if( !pColl ) pColl = db->pDfltColl; isMatch = sqlite3StrICmp(pColl->zName, zColl)==0; }else{ isMatch = 1; } }else{ isMatch = 0; |
︙ | ︙ | |||
3020 3021 3022 3023 3024 3025 3026 | ** ** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in ** the SQL statement, then this function only considers plans using the ** named index. If no such plan is found, then the returned cost is ** SQLITE_BIG_DBL. If a plan is found that uses the named index, ** then the cost is calculated in the usual way. ** | | > > > > > | 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 | ** ** If there was an INDEXED BY clause (pSrc->pIndex) attached to the table in ** the SQL statement, then this function only considers plans using the ** named index. If no such plan is found, then the returned cost is ** SQLITE_BIG_DBL. If a plan is found that uses the named index, ** then the cost is calculated in the usual way. ** ** If a NOT INDEXED clause was attached to the table ** in the SELECT statement, then no indexes are considered. However, the ** selected plan may still take advantage of the built-in rowid primary key ** index. */ static void bestBtreeIndex(WhereBestIdx *p){ Parse *pParse = p->pParse; /* The parsing context */ WhereClause *pWC = p->pWC; /* The WHERE clause */ struct SrcList_item *pSrc = p->pSrc; /* The FROM clause term to search */ int iCur = pSrc->iCursor; /* The cursor of the table to be accessed */ Index *pProbe; /* An index we are evaluating */ Index *pIdx; /* Copy of pProbe, or zero for IPK index */ int eqTermMask; /* Current mask of valid equality operators */ int idxEqTermMask; /* Index mask of valid equality operators */ Index sPk; /* A fake index object for the primary key */ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ int wsFlagMask; /* Allowed flags in p->cost.plan.wsFlag */ int nPriorSat; /* ORDER BY terms satisfied by outer loops */ int nOrderBy; /* Number of ORDER BY terms */ char bSortInit; /* Initializer for bSort in inner loop */ char bDistInit; /* Initializer for bDist in inner loop */ /* Initialize the cost to a worst-case value */ memset(&p->cost, 0, sizeof(p->cost)); p->cost.rCost = SQLITE_BIG_DBL; /* If the pSrc table is the right table of a LEFT JOIN then we may not ** use an index to satisfy IS NULL constraints on that table. This is |
︙ | ︙ | |||
3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 | pProbe = &sPk; wsFlagMask = ~( WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE ); eqTermMask = WO_EQ|WO_IN; pIdx = 0; } /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; WhereCost pc; /* Cost of using pProbe */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ | > > > > > > > > > > > | 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 | pProbe = &sPk; wsFlagMask = ~( WHERE_COLUMN_IN|WHERE_COLUMN_EQ|WHERE_COLUMN_NULL|WHERE_COLUMN_RANGE ); eqTermMask = WO_EQ|WO_IN; pIdx = 0; } nOrderBy = p->pOrderBy ? p->pOrderBy->nExpr : 0; if( p->i ){ nPriorSat = p->aLevel[p->i-1].plan.nOBSat; bSortInit = nPriorSat<nOrderBy; bDistInit = 0; }else{ nPriorSat = 0; bSortInit = nOrderBy>0; bDistInit = p->pDistinct!=0; } /* Loop over all indices looking for the best one to use */ for(; pProbe; pIdx=pProbe=pProbe->pNext){ const tRowcnt * const aiRowEst = pProbe->aiRowEst; WhereCost pc; /* Cost of using pProbe */ double log10N = (double)1; /* base-10 logarithm of nRow (inexact) */ |
︙ | ︙ | |||
3164 3165 3166 3167 3168 3169 3170 | ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ | | | | < < < < < < < < | < < < | 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 | ** SELECT a, b FROM tbl WHERE a = 1; ** SELECT a, b, c FROM tbl WHERE a = 1; */ int bInEst = 0; /* True if "x IN (SELECT...)" seen */ int nInMul = 1; /* Number of distinct equalities to lookup */ double rangeDiv = (double)1; /* Estimated reduction in search space */ int nBound = 0; /* Number of range constraints seen */ char bSort = bSortInit; /* True if external sort required */ char bDist = bDistInit; /* True if index cannot help with DISTINCT */ char bLookup = 0; /* True if not a covering index */ WhereTerm *pTerm; /* A single term of the WHERE clause */ #ifdef SQLITE_ENABLE_STAT3 WhereTerm *pFirstTerm = 0; /* First term matching the index */ #endif WHERETRACE(( " %s(%s):\n", pSrc->pTab->zName, (pIdx ? pIdx->zName : "ipk") )); memset(&pc, 0, sizeof(pc)); pc.plan.nOBSat = nPriorSat; /* Determine the values of pc.plan.nEq and nInMul */ for(pc.plan.nEq=0; pc.plan.nEq<pProbe->nColumn; pc.plan.nEq++){ int j = pProbe->aiColumn[pc.plan.nEq]; pTerm = findTerm(pWC, iCur, j, p->notReady, eqTermMask, pIdx); if( pTerm==0 ) break; pc.plan.wsFlags |= (WHERE_COLUMN_EQ|WHERE_ROWID_EQ); |
︙ | ︙ | |||
4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 | ** row of the left table of the join. */ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 0: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ | > > > > > > > > > > | 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 | ** row of the left table of the join. */ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } /* Special case of a FROM clause subquery implemented as a co-routine */ if( pTabItem->viaCoroutine ){ int regYield = pTabItem->regReturn; sqlite3VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield); pLevel->p2 = sqlite3VdbeAddOp1(v, OP_Yield, regYield); VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName)); sqlite3VdbeAddOp2(v, OP_If, regYield+1, addrBrk); pLevel->op = OP_Goto; }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 0: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ |
︙ | ︙ | |||
5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 | assert( sWBI.pSrc->pIndex==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } /* Conditions under which this table becomes the best so far: ** ** (1) The table must not depend on other tables that have not ** yet run. (In other words, it must not depend on tables ** in inner loops.) ** | > > > > > > > > > > > > > | | < < < | 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 | assert( sWBI.pSrc->pIndex==0 || (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 || sWBI.cost.plan.u.pIdx==sWBI.pSrc->pIndex ); if( isOptimal && (sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)==0 ){ notIndexed |= m; } if( isOptimal ){ pWInfo->a[j].rOptCost = sWBI.cost.rCost; }else if( iFrom<nTabList-1 ){ /* If two or more tables have nearly the same outer loop cost, ** very different inner loop (optimal) cost, we want to choose ** for the outer loop that table which benefits the least from ** being in the inner loop. The following code scales the ** outer loop cost estimate to accomplish that. */ WHERETRACE((" scaling cost from %.1f to %.1f\n", sWBI.cost.rCost, sWBI.cost.rCost/pWInfo->a[j].rOptCost)); sWBI.cost.rCost /= pWInfo->a[j].rOptCost; } /* Conditions under which this table becomes the best so far: ** ** (1) The table must not depend on other tables that have not ** yet run. (In other words, it must not depend on tables ** in inner loops.) ** ** (2) (This rule was removed on 2012-11-09. The scaling of the ** cost using the optimal scan cost made this rule obsolete.) ** ** (3) All tables have an INDEXED BY clause or this table lacks an ** INDEXED BY clause or this table uses the specific ** index specified by its INDEXED BY clause. This rule ensures ** that a best-so-far is always selected even if an impossible ** combination of INDEXED BY clauses are given. The error ** will be detected and relayed back to the application later. ** The NEVER() comes about because rule (2) above prevents ** An indexable full-table-scan from reaching rule (3). ** ** (4) The plan cost must be lower than prior plans, where "cost" ** is defined by the compareCost() function above. */ if( (sWBI.cost.used&sWBI.notValid)==0 /* (1) */ && (nUnconstrained==0 || sWBI.pSrc->pIndex==0 /* (3) */ || NEVER((sWBI.cost.plan.wsFlags & WHERE_NOT_FULLSCAN)!=0)) && (bestJ<0 || compareCost(&sWBI.cost, &bestPlan)) /* (4) */ ){ WHERETRACE((" === table %d (%s) is best so far\n" " cost=%.1f, nRow=%.1f, nOBSat=%d, wsFlags=%08x\n", j, sWBI.pSrc->pTab->zName, |
︙ | ︙ | |||
5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 | /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else #endif if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); testcase( pTab->nCol==BMS-1 ); | > > | 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 | /* Do nothing */ }else #ifndef SQLITE_OMIT_VIRTUALTABLE if( (pLevel->plan.wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite3GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite3VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else if( IsVirtual(pTab) ){ /* noop */ }else #endif if( (pLevel->plan.wsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); testcase( pTab->nCol==BMS-1 ); |
︙ | ︙ |
Changes to test/aggnested.test.
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 | REPLACE INTO t2 VALUES(2,99,999,9999); SELECT (SELECT GROUP_CONCAT(CASE WHEN a1=1 THEN'A' ELSE 'B' END) FROM t2), t1.* FROM t1; } } {A,B,B 3 33 333 3333} db2 close finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 | REPLACE INTO t2 VALUES(2,99,999,9999); SELECT (SELECT GROUP_CONCAT(CASE WHEN a1=1 THEN'A' ELSE 'B' END) FROM t2), t1.* FROM t1; } } {A,B,B 3 33 333 3333} db2 close ##################### Test cases for ticket [bfbf38e5e9956ac69f] ############ # # This first test case is the original problem report: do_test aggnested-3.0 { db eval { CREATE TABLE AAA ( aaa_id INTEGER PRIMARY KEY AUTOINCREMENT ); CREATE TABLE RRR ( rrr_id INTEGER PRIMARY KEY AUTOINCREMENT, rrr_date INTEGER NOT NULL, rrr_aaa INTEGER ); CREATE TABLE TTT ( ttt_id INTEGER PRIMARY KEY AUTOINCREMENT, target_aaa INTEGER NOT NULL, source_aaa INTEGER NOT NULL ); insert into AAA (aaa_id) values (2); insert into TTT (ttt_id, target_aaa, source_aaa) values (4469, 2, 2); insert into TTT (ttt_id, target_aaa, source_aaa) values (4476, 2, 1); insert into RRR (rrr_id, rrr_date, rrr_aaa) values (0, 0, NULL); insert into RRR (rrr_id, rrr_date, rrr_aaa) values (2, 4312, 2); SELECT i.aaa_id, (SELECT sum(CASE WHEN (t.source_aaa == i.aaa_id) THEN 1 ELSE 0 END) FROM TTT t ) AS segfault FROM (SELECT curr.rrr_aaa as aaa_id FROM RRR curr -- you also can comment out the next line -- it causes segfault to happen after one row is outputted INNER JOIN AAA a ON (curr.rrr_aaa = aaa_id) LEFT JOIN RRR r ON (r.rrr_id <> 0 AND r.rrr_date < curr.rrr_date) GROUP BY curr.rrr_id HAVING r.rrr_date IS NULL ) i; } } {2 1} # Further variants of the test case, as found in the ticket # do_test aggnested-3.1 { db eval { DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; CREATE TABLE t1 ( id1 INTEGER PRIMARY KEY AUTOINCREMENT, value1 INTEGER ); INSERT INTO t1 VALUES(4469,2),(4476,1); CREATE TABLE t2 ( id2 INTEGER PRIMARY KEY AUTOINCREMENT, value2 INTEGER ); INSERT INTO t2 VALUES(0,1),(2,2); SELECT (SELECT sum(value2==xyz) FROM t2) FROM (SELECT curr.value1 as xyz FROM t1 AS curr LEFT JOIN t1 AS other GROUP BY curr.id1); } } {1 1} do_test aggnested-3.2 { db eval { DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; CREATE TABLE t1 ( id1 INTEGER, value1 INTEGER, x1 INTEGER ); INSERT INTO t1 VALUES(4469,2,98),(4469,1,99),(4469,3,97); CREATE TABLE t2 ( value2 INTEGER ); INSERT INTO t2 VALUES(1); SELECT (SELECT sum(value2==xyz) FROM t2) FROM (SELECT value1 as xyz, max(x1) AS pqr FROM t1 GROUP BY id1); } } {0} do_test aggnested-3.3 { db eval { DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; CREATE TABLE t1(id1, value1); INSERT INTO t1 VALUES(4469,2),(4469,1); CREATE TABLE t2 (value2); INSERT INTO t2 VALUES(1); SELECT (SELECT sum(value2=value1) FROM t2), max(value1) FROM t1 GROUP BY id1; } } {0 2} # A batch of queries all doing approximately the same operation involving # two nested aggregate queries. # do_test aggnested-3.11 { db eval { DROP TABLE IF EXISTS t1; DROP TABLE IF EXISTS t2; CREATE TABLE t1(id1, value1); INSERT INTO t1 VALUES(4469,12),(4469,11),(4470,34); CREATE INDEX t1id1 ON t1(id1); CREATE TABLE t2 (value2); INSERT INTO t2 VALUES(12),(34),(34); INSERT INTO t2 SELECT value2 FROM t2; SELECT max(value1), (SELECT count(*) FROM t2 WHERE value2=max(value1)) FROM t1 GROUP BY id1; } } {12 2 34 4} do_test aggnested-3.12 { db eval { SELECT max(value1), (SELECT count(*) FROM t2 WHERE value2=value1) FROM t1 GROUP BY id1; } } {12 2 34 4} do_test aggnested-3.13 { db eval { SELECT value1, (SELECT sum(value2=value1) FROM t2) FROM t1; } } {12 2 11 0 34 4} do_test aggnested-3.14 { db eval { SELECT value1, (SELECT sum(value2=value1) FROM t2) FROM t1 WHERE value1 IN (SELECT max(value1) FROM t1 GROUP BY id1); } } {12 2 34 4} do_test aggnested-3.15 { # FIXME: If case 3.16 works, then this case really ought to work too... catchsql { SELECT max(value1), (SELECT sum(value2=max(value1)) FROM t2) FROM t1 GROUP BY id1; } } {1 {misuse of aggregate function max()}} do_test aggnested-3.16 { db eval { SELECT max(value1), (SELECT sum(value2=value1) FROM t2) FROM t1 GROUP BY id1; } } {12 2 34 4} finish_test |
Changes to test/backup4.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 | # Test that if the source is zero bytes, the destination database # consists of a single page only. # do_execsql_test 2.1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } | < | | 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | # Test that if the source is zero bytes, the destination database # consists of a single page only. # do_execsql_test 2.1 { CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } do_test 2.2 { file size test.db } [expr $AUTOVACUUM ? 4096 : 3072] do_test 2.3 { sqlite3 db1 test.db2 db1 backup test.db db1 close file size test.db } {1024} |
︙ | ︙ | |||
86 87 88 89 90 91 92 | # of a single page. # do_execsql_test 3.1 { PRAGMA page_size = 4096; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } | < | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | # of a single page. # do_execsql_test 3.1 { PRAGMA page_size = 4096; CREATE TABLE t1(a, b); CREATE INDEX i1 ON t1(a, b); } do_test 3.2 { file size test.db } [expr $AUTOVACUUM ? 16384 : 12288] do_test 3.3 { sqlite3 db1 test.db2 db1 backup test.db db1 close file size test.db } {1024} do_test 3.4 { file size test.db2 } 0 finish_test |
Changes to test/collate1.test.
︙ | ︙ | |||
71 72 73 74 75 76 77 78 79 80 81 82 83 84 | } {} do_test collate1-1.1 { execsql { SELECT c2 FROM collate1t1 ORDER BY 1; } } {{} 0x119 0x2D} do_test collate1-1.2 { execsql { SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex; } } {{} 0x2D 0x119} do_test collate1-1.3 { execsql { SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex DESC; | > | 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | } {} do_test collate1-1.1 { execsql { SELECT c2 FROM collate1t1 ORDER BY 1; } } {{} 0x119 0x2D} do_test collate1-1.2 { breakpoint execsql { SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex; } } {{} 0x2D 0x119} do_test collate1-1.3 { execsql { SELECT c2 FROM collate1t1 ORDER BY 1 COLLATE hex DESC; |
︙ | ︙ |
Changes to test/crash7.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # #*********************************************************************** # # $Id: crash7.test,v 1.1 2008/04/03 14:36:26 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !crashtest { finish_test return } proc signature {} { | > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # # $Id: crash7.test,v 1.1 2008/04/03 14:36:26 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix crash7 ifcapable !crashtest { finish_test return } proc signature {} { |
︙ | ︙ | |||
74 75 76 77 78 79 80 81 82 | " } {1 {child process exited abnormally}} sqlite3 db test.db integrity_check crash7-1.$ii.integrity } } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 | " } {1 {child process exited abnormally}} sqlite3 db test.db integrity_check crash7-1.$ii.integrity } } db close forcedelete test.db sqlite3 db test.db do_execsql_test 2.0 { CREATE TABLE t1(a, b, UNIQUE(a, b)); INSERT INTO t1 VALUES(randomblob(100), randomblob(100)); INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; INSERT INTO t1 SELECT randomblob(100), randomblob(100) FROM t1; DELETE FROM t1 WHERE rowid%2; } db_save_and_close for {set i 0} {$i < 20} {incr i} { db_restore_and_reopen do_test 2.[expr $i+1].1 { crashsql -file test.db -seed $i {VACUUM} } {1 {child process exited abnormally}} do_execsql_test 2.[expr $i+1].2 { PRAGMA integrity_check } {ok} } finish_test |
Changes to test/distinct.test.
︙ | ︙ | |||
164 165 166 167 168 169 170 | 2 "b, a FROM t1" {} {B A b a} 3 "a, b, c FROM t1" {hash} {a b c A B C} 4 "a, b, c FROM t1 ORDER BY a, b, c" {btree} {A B C a b c} 5 "b FROM t1 WHERE a = 'a'" {} {b} 6 "b FROM t1" {hash} {b B} 7 "a FROM t1" {} {A a} 8 "b COLLATE nocase FROM t1" {} {b} | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | 2 "b, a FROM t1" {} {B A b a} 3 "a, b, c FROM t1" {hash} {a b c A B C} 4 "a, b, c FROM t1 ORDER BY a, b, c" {btree} {A B C a b c} 5 "b FROM t1 WHERE a = 'a'" {} {b} 6 "b FROM t1" {hash} {b B} 7 "a FROM t1" {} {A a} 8 "b COLLATE nocase FROM t1" {} {b} 9 "b COLLATE nocase FROM t1 ORDER BY b COLLATE nocase" {} {b} } { do_execsql_test 2.$tn.1 "SELECT DISTINCT $sql" $res do_temptables_test 2.$tn.2 "SELECT DISTINCT $sql" $temptables } do_execsql_test 2.A { SELECT (SELECT DISTINCT o.a FROM t1 AS i) FROM t1 AS o ORDER BY rowid; |
︙ | ︙ |
Changes to test/e_insert.test.
︙ | ︙ | |||
137 138 139 140 141 142 143 | 82 "INSERT OR IGNORE INTO a1 (b, a) VALUES(1, 2),(3,4)" {} 83 "REPLACE INTO a1 (b, a) VALUES(1, 2),(3,4)" {} 84 "REPLACE INTO main.a1 (b, a) VALUES(1, 2),(3,4)" {} } delete_all_data | | | | > > | > | | | | | | > | > | | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | 82 "INSERT OR IGNORE INTO a1 (b, a) VALUES(1, 2),(3,4)" {} 83 "REPLACE INTO a1 (b, a) VALUES(1, 2),(3,4)" {} 84 "REPLACE INTO main.a1 (b, a) VALUES(1, 2),(3,4)" {} } delete_all_data # EVIDENCE-OF: R-21490-41092 The first form (with the "VALUES" keyword) # creates one or more new rows in an existing table. # do_insert_tests e_insert-1.1 { 0 "SELECT count(*) FROM a2" {0} 1a "INSERT INTO a2 VALUES(1, 2, 3)" {} 1b "SELECT count(*) FROM a2" {1} 2a "INSERT INTO a2(a, b) VALUES(1, 2)" {} 2b "SELECT count(*) FROM a2" {2} 3a "INSERT INTO a2(a) VALUES(3),(4)" {} 3b "SELECT count(*) FROM a2" {4} } # EVIDENCE-OF: R-53616-44976 If no column-list is specified then the # number of values inserted into each row must be the same as the number # of columns in the table. # # A test in the block above verifies that if the VALUES list has the # correct number of columns (for table a2, 3 columns) works. So these # tests just show that other values cause an error. # do_insert_tests e_insert-1.2 -error { table %s has %d columns but %d values were supplied } { 1 "INSERT INTO a2 VALUES(1)" {a2 3 1} 2 "INSERT INTO a2 VALUES(1,2)" {a2 3 2} 3 "INSERT INTO a2 VALUES(1,2,3,4)" {a2 3 4} 4 "INSERT INTO a2 VALUES(1,2,3,4,5)" {a2 3 5} } # EVIDENCE-OF: R-34231-22576 In this case the result of evaluating the # left-most expression in each term of the VALUES list is inserted into # the left-most column of the each new row, and forth for each # subsequent expression. # delete_all_data do_insert_tests e_insert-1.3 { 1a "INSERT INTO a2 VALUES(1, 2, 3)" {} 1b "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {1 2 3} 2a "INSERT INTO a2 VALUES('abc', NULL, 3*3+1)" {} 2b "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {abc {} 10} 3a "INSERT INTO a2 VALUES((SELECT count(*) FROM a2), 'x', 'y')" {} 3b "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {2 x y} } # EVIDENCE-OF: R-44710-64652 If a column-list is specified, then the # number of values in each term of the VALUS list must match the number # of specified columns. # do_insert_tests e_insert-1.4 -error { %d values for %d columns } { 1 "INSERT INTO a2(a, b, c) VALUES(1)" {1 3} 2 "INSERT INTO a2(a, b, c) VALUES(1,2)" {2 3} 3 "INSERT INTO a2(a, b, c) VALUES(1,2,3,4)" {4 3} |
︙ | ︙ |
Changes to test/e_uri.test.
︙ | ︙ | |||
257 258 259 260 261 262 263 | 7 {file:test.db?mode=memory} {not an error} 8 {file:test.db?mode=MEMORY} {no such access mode: MEMORY} " { do_test 7.$tn { open_uri_error $uri } $error } | | | | 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 | 7 {file:test.db?mode=memory} {not an error} 8 {file:test.db?mode=MEMORY} {no such access mode: MEMORY} " { do_test 7.$tn { open_uri_error $uri } $error } # EVIDENCE-OF: R-43036-46756 If "ro" is specified, then the database is # opened for read-only access, just as if the SQLITE_OPEN_READONLY flag # had been set in the third argument to sqlite3_open_v2(). # # EVIDENCE-OF: R-40137-26050 If the mode option is set to "rw", then the # database is opened for read-write (but not create) access, as if # SQLITE_OPEN_READWRITE (but not SQLITE_OPEN_CREATE) had been set. # # EVIDENCE-OF: R-26845-32976 Value "rwc" is equivalent to setting both # SQLITE_OPEN_READWRITE and SQLITE_OPEN_CREATE. |
︙ | ︙ |
Changes to test/filectrl.test.
︙ | ︙ | |||
32 33 34 35 36 37 38 39 40 41 | file_control_lasterrno_test db } {} do_test filectrl-1.5 { db close sqlite3 db test_control_lockproxy.db file_control_lockproxy_test db [get_pwd] } {} db close forcedelete .test_control_lockproxy.db-conch test.proxy finish_test | > > > > > > | 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | file_control_lasterrno_test db } {} do_test filectrl-1.5 { db close sqlite3 db test_control_lockproxy.db file_control_lockproxy_test db [get_pwd] } {} do_test filectrl-1.6 { sqlite3 db test.db set fn [file_control_tempfilename db] puts -nonewline \[$fn\] set fn } {/etilqs_/} db close forcedelete .test_control_lockproxy.db-conch test.proxy finish_test |
Changes to test/fts3conf.test.
︙ | ︙ | |||
132 133 134 135 136 137 138 139 | INSERT INTO t1(docid, x) VALUES(1, 'a b c'); REPLACE INTO t1(docid, x) VALUES('zero', 'd e f'); } {1 {datatype mismatch}} do_execsql_test 2.2.2 { COMMIT } do_execsql_test 2.2.3 { SELECT * FROM t1 } {{a b c} {a b c}} fts3_integrity 2.2.4 db t1 finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | INSERT INTO t1(docid, x) VALUES(1, 'a b c'); REPLACE INTO t1(docid, x) VALUES('zero', 'd e f'); } {1 {datatype mismatch}} do_execsql_test 2.2.2 { COMMIT } do_execsql_test 2.2.3 { SELECT * FROM t1 } {{a b c} {a b c}} fts3_integrity 2.2.4 db t1 do_execsql_test 3.1 { CREATE VIRTUAL TABLE t3 USING fts4; REPLACE INTO t3(docid, content) VALUES (1, 'one two'); SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one' } {X'0100000002000000'} do_execsql_test 3.2 { REPLACE INTO t3(docid, content) VALUES (2, 'one two three four'); SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'four' } {X'0200000003000000'} do_execsql_test 3.3 { REPLACE INTO t3(docid, content) VALUES (1, 'one two three four five six'); SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six' } {X'0200000005000000'} do_execsql_test 3.4 { UPDATE OR REPLACE t3 SET docid = 2 WHERE docid=1; SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six' } {X'0100000006000000'} do_execsql_test 3.5 { UPDATE OR REPLACE t3 SET docid = 3 WHERE docid=2; SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'six' } {X'0100000006000000'} do_execsql_test 3.6 { REPLACE INTO t3(docid, content) VALUES (3, 'one two'); SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one' } {X'0100000002000000'} do_execsql_test 3.7 { REPLACE INTO t3(docid, content) VALUES (NULL, 'one two three four'); REPLACE INTO t3(docid, content) VALUES (NULL, 'one two three four five six'); SELECT docid FROM t3; } {3 4 5} do_execsql_test 3.8 { UPDATE OR REPLACE t3 SET docid = 5, content='three four' WHERE docid = 4; SELECT quote(matchinfo(t3, 'na')) FROM t3 WHERE t3 MATCH 'one' } {X'0200000002000000'} finish_test |
Changes to test/fts3matchinfo.test.
︙ | ︙ | |||
402 403 404 405 406 407 408 409 410 411 | SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {1 {database disk image is malformed}} do_execsql_test 8.4.3.1 { UPDATE t11_stat SET value = NULL; } do_catchsql_test 8.5.3.2 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {1 {database disk image is malformed}} finish_test | > > > > > > > > > > > > > > > > > > > | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {1 {database disk image is malformed}} do_execsql_test 8.4.3.1 { UPDATE t11_stat SET value = NULL; } do_catchsql_test 8.5.3.2 { SELECT mit(matchinfo(t11, 'nxa')) FROM t11 WHERE t11 MATCH 'a*' } {1 {database disk image is malformed}} #------------------------------------------------------------------------- do_execsql_test 8.1 { CREATE VIRTUAL TABLE t12 USING fts4; INSERT INTO t12 VALUES('a b c d'); SELECT mit(matchinfo(t12, 'x')) FROM t12 WHERE t12 MATCH 'a NEAR/1 d OR a'; } {{0 0 0 0 0 0 1 1 1}} do_execsql_test 8.2 { INSERT INTO t12 VALUES('a d c d'); SELECT mit(matchinfo(t12, 'x')) FROM t12 WHERE t12 MATCH 'a NEAR/1 d OR a'; } { {0 1 1 0 1 1 1 2 2} {1 1 1 1 1 1 1 2 2} } do_execsql_test 8.3 { INSERT INTO t12 VALUES('a d d a'); SELECT mit(matchinfo(t12, 'x')) FROM t12 WHERE t12 MATCH 'a NEAR/1 d OR a'; } { {0 3 2 0 3 2 1 4 3} {1 3 2 1 3 2 1 4 3} {2 3 2 2 3 2 2 4 3} } finish_test |
Added test/instr.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | # 2012 October 24 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the built-in INSTR() functions. # set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table to work with. # do_test instr-1.1 { db eval {SELECT instr('abcdefg','a');} } {1} do_test instr-1.2 { db eval {SELECT instr('abcdefg','b');} } {2} do_test instr-1.3 { db eval {SELECT instr('abcdefg','c');} } {3} do_test instr-1.4 { db eval {SELECT instr('abcdefg','d');} } {4} do_test instr-1.5 { db eval {SELECT instr('abcdefg','e');} } {5} do_test instr-1.6 { db eval {SELECT instr('abcdefg','f');} } {6} do_test instr-1.7 { db eval {SELECT instr('abcdefg','g');} } {7} do_test instr-1.8 { db eval {SELECT instr('abcdefg','h');} } {0} do_test instr-1.9 { db eval {SELECT instr('abcdefg','abcdefg');} } {1} do_test instr-1.10 { db eval {SELECT instr('abcdefg','abcdefgh');} } {0} do_test instr-1.11 { db eval {SELECT instr('abcdefg','bcdefg');} } {2} do_test instr-1.12 { db eval {SELECT instr('abcdefg','bcdefgh');} } {0} do_test instr-1.13 { db eval {SELECT instr('abcdefg','cdefg');} } {3} do_test instr-1.14 { db eval {SELECT instr('abcdefg','cdefgh');} } {0} do_test instr-1.15 { db eval {SELECT instr('abcdefg','defg');} } {4} do_test instr-1.16 { db eval {SELECT instr('abcdefg','defgh');} } {0} do_test instr-1.17 { db eval {SELECT instr('abcdefg','efg');} } {5} do_test instr-1.18 { db eval {SELECT instr('abcdefg','efgh');} } {0} do_test instr-1.19 { db eval {SELECT instr('abcdefg','fg');} } {6} do_test instr-1.20 { db eval {SELECT instr('abcdefg','fgh');} } {0} do_test instr-1.21 { db eval {SELECT coalesce(instr('abcdefg',NULL),'nil');} } {nil} do_test instr-1.22 { db eval {SELECT coalesce(instr(NULL,'x'),'nil');} } {nil} do_test instr-1.23 { db eval {SELECT instr(12345,34);} } {3} do_test instr-1.24 { db eval {SELECT instr(123456.78,34);} } {3} do_test instr-1.25 { db eval {SELECT instr(123456.78,x'3334');} } {3} do_test instr-1.26 { db eval {SELECT instr('äbcdefg','efg');} } {5} do_test instr-1.27 { db eval {SELECT instr('€xyzzy','xyz');} } {2} do_test instr-1.28 { db eval {SELECT instr('abc€xyzzy','xyz');} } {5} do_test instr-1.29 { db eval {SELECT instr('abc€xyzzy','€xyz');} } {4} do_test instr-1.30 { db eval {SELECT instr('abc€xyzzy','c€xyz');} } {3} do_test instr-1.31 { db eval {SELECT instr(x'0102030405',x'01');} } {1} do_test instr-1.32 { db eval {SELECT instr(x'0102030405',x'02');} } {2} do_test instr-1.33 { db eval {SELECT instr(x'0102030405',x'03');} } {3} do_test instr-1.34 { db eval {SELECT instr(x'0102030405',x'04');} } {4} do_test instr-1.35 { db eval {SELECT instr(x'0102030405',x'05');} } {5} do_test instr-1.36 { db eval {SELECT instr(x'0102030405',x'06');} } {0} do_test instr-1.37 { db eval {SELECT instr(x'0102030405',x'0102030405');} } {1} do_test instr-1.38 { db eval {SELECT instr(x'0102030405',x'02030405');} } {2} do_test instr-1.39 { db eval {SELECT instr(x'0102030405',x'030405');} } {3} do_test instr-1.40 { db eval {SELECT instr(x'0102030405',x'0405');} } {4} do_test instr-1.41 { db eval {SELECT instr(x'0102030405',x'0506');} } {0} do_test instr-1.42 { db eval {SELECT instr(x'0102030405',x'');} } {1} do_test instr-1.43 { db eval {SELECT instr(x'',x'');} } {1} do_test instr-1.44 { db eval {SELECT instr('','');} } {1} do_test instr-1.45 { db eval {SELECT instr('abcdefg','');} } {1} unset -nocomplain longstr set longstr abcdefghijklmonpqrstuvwxyz append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr append longstr $longstr # puts [string length $longstr] append longstr Xabcde do_test instr-1.46 { db eval {SELECT instr($longstr,'X');} } {106497} do_test instr-1.47 { db eval {SELECT instr($longstr,'Y');} } {0} do_test instr-1.48 { db eval {SELECT instr($longstr,'Xa');} } {106497} do_test instr-1.49 { db eval {SELECT instr($longstr,'zXa');} } {106496} set longstr [string map {a ä} $longstr] do_test instr-1.50 { db eval {SELECT instr($longstr,'X');} } {106497} do_test instr-1.51 { db eval {SELECT instr($longstr,'Y');} } {0} do_test instr-1.52 { db eval {SELECT instr($longstr,'Xä');} } {106497} do_test instr-1.53 { db eval {SELECT instr($longstr,'zXä');} } {106496} do_test instr-1.54 { db eval {SELECT instr(x'78c3a4e282ac79','x');} } {1} do_test instr-1.55 { db eval {SELECT instr(x'78c3a4e282ac79','y');} } {4} do_test instr-1.56 { db eval {SELECT instr(x'78c3a4e282ac79',x'79');} } {7} do_test instr-1.57 { db eval {SELECT instr('xä€y',x'79');} } {4} finish_test |
Changes to test/interrupt.test.
︙ | ︙ | |||
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | for {set i 1} {$i<$max_count-5} {incr i 1} { do_test interrupt-4.$i.1 { set ::sqlite_interrupt_count $::i catchsql $sql } {1 interrupted} } # Interrupt during parsing # do_test interrupt-5.1 { proc fake_interrupt {args} { db collate fake_collation no-op sqlite3_interrupt db return SQLITE_OK } db collation_needed fake_interrupt catchsql { CREATE INDEX fake ON fake1(a COLLATE fake_collation, b, c DESC); } } {1 interrupt} | > > | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 | for {set i 1} {$i<$max_count-5} {incr i 1} { do_test interrupt-4.$i.1 { set ::sqlite_interrupt_count $::i catchsql $sql } {1 interrupted} } if {0} { # This doesn't work anymore since the collation factor is # no longer called during schema parsing. # Interrupt during parsing # do_test interrupt-5.1 { proc fake_interrupt {args} { db collate fake_collation no-op sqlite3_interrupt db return SQLITE_OK } db collation_needed fake_interrupt catchsql { CREATE INDEX fake ON fake1(a COLLATE fake_collation, b, c DESC); } } {1 interrupt} } finish_test |
Changes to test/malloc3.test.
︙ | ︙ | |||
23 24 25 26 27 28 29 30 31 32 33 34 35 36 | # if {!$MEMDEBUG} { puts "Skipping malloc3 tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } #-------------------------------------------------------------------------- # NOTES ON RECOVERING FROM A MALLOC FAILURE # # The tests in this file test the behaviours described in the following # paragraphs. These tests test the behaviour of the system when malloc() fails # inside of a call to _prepare(), _step(), _finalize() or _reset(). The # handling of malloc() failures within ancillary procedures is tested | > > > > > > > > > > > > > > > > > > | 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | # if {!$MEMDEBUG} { puts "Skipping malloc3 tests: not compiled with -DSQLITE_MEMDEBUG..." finish_test return } # Do not run these tests with an in-memory journal. # # In the pager layer, if an IO or OOM error occurs during a ROLLBACK, or # when flushing a page to disk due to cache-stress, the pager enters an # "error state". The only way out of the error state is to unlock the # database file and end the transaction, leaving whatever journal and # database files happen to be on disk in place. The next time the current # (or any other) connection opens a read transaction, hot-journal rollback # is performed if necessary. # # Of course, this doesn't work with an in-memory journal. # if {[permutation]=="inmemory_journal"} { finish_test return } #-------------------------------------------------------------------------- # NOTES ON RECOVERING FROM A MALLOC FAILURE # # The tests in this file test the behaviours described in the following # paragraphs. These tests test the behaviour of the system when malloc() fails # inside of a call to _prepare(), _step(), _finalize() or _reset(). The # handling of malloc() failures within ancillary procedures is tested |
︙ | ︙ | |||
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | #-------------------------------------------------------------------------- # These procs are used to build up a "program" in global variable # ::run_test_script. At the end of this file, the proc [run_test] is used # to execute the program (and all test cases contained therein). # set ::run_test_script [list] proc TEST {id t} {lappend ::run_test_script -test [list $id $t]} proc PREP {p} {lappend ::run_test_script -prep [string trim $p]} proc DEBUG {s} {lappend ::run_test_script -debug $s} # SQL -- # # SQL ?-norollback? <sql-text> # # Add an 'SQL' primitive to the program (see notes above). If the -norollback # switch is present, then the statement is not allowed to automatically roll # back any active transaction if malloc() fails. It must rollback the statement # transaction only. # proc SQL {a1 {a2 ""}} { | > | | | > | | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 | #-------------------------------------------------------------------------- # These procs are used to build up a "program" in global variable # ::run_test_script. At the end of this file, the proc [run_test] is used # to execute the program (and all test cases contained therein). # set ::run_test_sql_id 0 set ::run_test_script [list] proc TEST {id t} {lappend ::run_test_script -test [list $id $t]} proc PREP {p} {lappend ::run_test_script -prep [string trim $p]} proc DEBUG {s} {lappend ::run_test_script -debug $s} # SQL -- # # SQL ?-norollback? <sql-text> # # Add an 'SQL' primitive to the program (see notes above). If the -norollback # switch is present, then the statement is not allowed to automatically roll # back any active transaction if malloc() fails. It must rollback the statement # transaction only. # proc SQL {a1 {a2 ""}} { # An SQL primitive parameter is a list of three elements, an id, a boolean # value indicating if the statement may cause transaction rollback when # malloc() fails, and the sql statement itself. set id [incr ::run_test_sql_id] if {$a2 == ""} { lappend ::run_test_script -sql [list $id true [string trim $a1]] } else { lappend ::run_test_script -sql [list $id false [string trim $a2]] } } # TEST_AUTOCOMMIT -- # # A shorthand test to see if a transaction is active or not. The first # argument - $id - is the integer number of the test case. The second |
︙ | ︙ | |||
254 255 256 257 258 259 260 | } } {abc abc abc_i abc abc_t abc abc_v abc_v 1 2 3} } set sql { BEGIN;DELETE FROM abc; } | | | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 | } } {abc abc abc_i abc abc_t abc abc_v abc_v 1 2 3} } set sql { BEGIN;DELETE FROM abc; } for {set i 1} {$i < 100} {incr i} { set a $i set b "String value $i" set c [string repeat X $i] append sql "INSERT INTO abc VALUES ($a, '$b', '$c');" } append sql {COMMIT;} PREP $sql |
︙ | ︙ | |||
525 526 527 528 529 530 531 | proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { if {[llength $arglist] %2} { error "Uneven number of arguments to TEST" } for {set i 0} {$i < $pcstart} {incr i} { | | | | > > > > < < > > > > > | | | > | | | < | | | | | > | | | 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 | proc run_test {arglist iRepeat {pcstart 0} {iFailStart 1}} { if {[llength $arglist] %2} { error "Uneven number of arguments to TEST" } for {set i 0} {$i < $pcstart} {incr i} { set k2 [lindex $arglist [expr {2 * $i}]] set v2 [lindex $arglist [expr {2 * $i + 1}]] set ac [sqlite3_get_autocommit $::DB] ;# Auto-Commit switch -- $k2 { -sql {db eval [lindex $v2 2]} -prep {db eval $v2} -debug {eval $v2} } set nac [sqlite3_get_autocommit $::DB] ;# New Auto-Commit if {$ac && !$nac} {set begin_pc $i} } db rollback_hook [list incr ::rollback_hook_count] set iFail $iFailStart set pc $pcstart while {$pc*2 < [llength $arglist]} { # Fetch the current instruction type and payload. set k [lindex $arglist [expr {2 * $pc}]] set v [lindex $arglist [expr {2 * $pc + 1}]] # Id of this iteration: set iterid "pc=$pc.iFail=$iFail$k" switch -- $k { -test { foreach {id script} $v {} set testid "malloc3-(test $id).$iterid" eval $script incr pc } -sql { set ::rollback_hook_count 0 set id [lindex $v 0] set testid "malloc3-(integrity $id).$iterid" set ac [sqlite3_get_autocommit $::DB] ;# Auto-Commit sqlite3_memdebug_fail $iFail -repeat 0 set rc [catch {db eval [lindex $v 2]} msg] ;# True error occurs set nac [sqlite3_get_autocommit $::DB] ;# New Auto-Commit if {$rc != 0 && $nac && !$ac} { # Before [db eval] the auto-commit flag was clear. Now it # is set. Since an error occured we assume this was not a # commit - therefore a rollback occured. Check that the # rollback-hook was invoked. do_test malloc3-rollback_hook_count.$iterid { set ::rollback_hook_count } {1} } set nFail [sqlite3_memdebug_fail -1 -benigncnt nBenign] if {$rc == 0} { # Successful execution of sql. The number of failed malloc() # calls should be equal to the number of benign failures. # Otherwise a malloc() failed and the error was not reported. # set expr {$nFail!=$nBenign} if {[expr $expr]} { error "Unreported malloc() failure, test \"$testid\", $expr" } if {$ac && !$nac} { # Before the [db eval] the auto-commit flag was set, now it # is clear. We can deduce that a "BEGIN" statement has just # been successfully executed. set begin_pc $pc } incr pc set iFail 1 integrity_check $testid } elseif {[regexp {.*out of memory} $msg] || [db errorcode] == 3082} { # Out of memory error, as expected. # integrity_check $testid incr iFail if {$nac && !$ac} { if {![lindex $v 1] && [db errorcode] != 3082} { # error "Statement \"[lindex $v 2]\" caused a rollback" } for {set i $begin_pc} {$i < $pc} {incr i} { set k2 [lindex $arglist [expr {2 * $i}]] set v2 [lindex $arglist [expr {2 * $i + 1}]] set catchupsql "" switch -- $k2 { -sql {set catchupsql [lindex $v2 2]} -prep {set catchupsql $v2} } db eval $catchupsql } } } else { error $msg } # back up to the previous "-test" block. while {[lindex $arglist [expr {2 * ($pc - 1)}]] == "-test"} { incr pc -1 } } -prep { db eval $v incr pc } -debug { eval $v incr pc } default { error "Unknown switch: $k" } } } } # Turn off the Tcl interface's prepared statement caching facility. Then # run the tests with "persistent" malloc failures. sqlite3_extended_result_codes db 1 db cache size 0 run_test $::run_test_script 1 # Close and reopen the db. db close |
︙ | ︙ |
Changes to test/minmax.test.
︙ | ︙ | |||
13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # aggregate min() and max() functions and which are handled as # as a special case. # # $Id: minmax.test,v 1.21 2008/07/08 18:05:26 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl do_test minmax-1.0 { execsql { BEGIN; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES(1,1); INSERT INTO t1 VALUES(2,2); | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | # aggregate min() and max() functions and which are handled as # as a special case. # # $Id: minmax.test,v 1.21 2008/07/08 18:05:26 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix minmax do_test minmax-1.0 { execsql { BEGIN; CREATE TABLE t1(x, y); INSERT INTO t1 VALUES(1,1); INSERT INTO t1 VALUES(2,2); |
︙ | ︙ | |||
295 296 297 298 299 300 301 | ifcapable {compound && subquery} { do_test minmax-9.1 { execsql { SELECT max(rowid) FROM ( SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 ) } | | | 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | ifcapable {compound && subquery} { do_test minmax-9.1 { execsql { SELECT max(rowid) FROM ( SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 ) } } {{}} do_test minmax-9.2 { execsql { SELECT max(rowid) FROM ( SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5 ) } } {{}} |
︙ | ︙ | |||
532 533 534 535 536 537 538 539 540 541 542 | } {25} do_test minmax-12.17 { execsql { SELECT max(rowid) FROM t7 WHERE a=3 AND b=5 AND c=15; } } {5} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | } {25} do_test minmax-12.17 { execsql { SELECT max(rowid) FROM t7 WHERE a=3 AND b=5 AND c=15; } } {5} #------------------------------------------------------------------------- reset_db proc do_test_13 {op name sql1 sql2 res} { set ::sqlite_search_count 0 uplevel [list do_execsql_test $name.1 $sql1 $res] set a $::sqlite_search_count set ::sqlite_search_count 0 uplevel [list do_execsql_test $name.2 $sql2 $res] set b $::sqlite_search_count uplevel [list do_test $name.3 [list expr "$a $op $b"] 1] } # Run a test named $name. Check that SQL statements $sql1 and $sql2 both # return the same result, but that $sql2 increments the $sqlite_search_count # variable more often (indicating that it is visiting more rows to determine # the result). # proc do_test_13_opt {name sql1 sql2 res} { uplevel [list do_test_13 < $name $sql1 $sql2 $res] } # Like [do_test_13_noopt], except this time check that the $sqlite_search_count # variable is incremented the same number of times by both SQL statements. # proc do_test_13_noopt {name sql1 sql2 res} { uplevel [list do_test_13 == $name $sql1 $sql2 $res] } do_execsql_test 13.1 { CREATE TABLE t1(a, b, c); INSERT INTO t1 VALUES('a', 1, 1); INSERT INTO t1 VALUES('b', 6, 6); INSERT INTO t1 VALUES('c', 5, 5); INSERT INTO t1 VALUES('a', 4, 4); INSERT INTO t1 VALUES('a', 5, 5); INSERT INTO t1 VALUES('c', 6, 6); INSERT INTO t1 VALUES('b', 4, 4); INSERT INTO t1 VALUES('c', 7, 7); INSERT INTO t1 VALUES('b', 2, 2); INSERT INTO t1 VALUES('b', 3, 3); INSERT INTO t1 VALUES('a', 3, 3); INSERT INTO t1 VALUES('b', 5, 5); INSERT INTO t1 VALUES('c', 4, 4); INSERT INTO t1 VALUES('c', 3, 3); INSERT INTO t1 VALUES('a', 2, 2); SELECT * FROM t1 ORDER BY a, b, c; } {a 1 1 a 2 2 a 3 3 a 4 4 a 5 5 b 2 2 b 3 3 b 4 4 b 5 5 b 6 6 c 3 3 c 4 4 c 5 5 c 6 6 c 7 7 } do_execsql_test 13.2 { CREATE INDEX i1 ON t1(a, b, c) } do_test_13_opt 13.3 { SELECT min(b) FROM t1 WHERE a='b' } { SELECT min(c) FROM t1 WHERE a='b' } {2} do_test_13_opt 13.4 { SELECT a, min(b) FROM t1 WHERE a='b' } { SELECT a, min(c) FROM t1 WHERE a='b' } {b 2} do_test_13_opt 13.4 { SELECT a||c, max(b)+4 FROM t1 WHERE a='c' } { SELECT a||c, max(c)+4 FROM t1 WHERE a='c' } {c7 11} do_test_13_noopt 13.5 { SELECT a||c, max(b+1) FROM t1 WHERE a='c' } { SELECT a||c, max(c+1) FROM t1 WHERE a='c' } {c7 8} do_test_13_noopt 13.6 { SELECT count(b) FROM t1 WHERE a='c' } { SELECT count(c) FROM t1 WHERE a='c' } {5} do_test_13_noopt 13.7 { SELECT min(b), count(b) FROM t1 WHERE a='a'; } { SELECT min(c), count(c) FROM t1 WHERE a='a'; } {1 5} finish_test |
Changes to test/minmax2.test.
︙ | ︙ | |||
285 286 287 288 289 290 291 | ifcapable {compound && subquery} { do_test minmax2-9.1 { execsql { SELECT max(rowid) FROM ( SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 ) } | | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | ifcapable {compound && subquery} { do_test minmax2-9.1 { execsql { SELECT max(rowid) FROM ( SELECT max(rowid) FROM t4 UNION SELECT max(rowid) FROM t5 ) } } {{}} do_test minmax2-9.2 { execsql { SELECT max(rowid) FROM ( SELECT max(rowid) FROM t4 EXCEPT SELECT max(rowid) FROM t5 ) } } {{}} |
︙ | ︙ |
Changes to test/orderby1.test.
︙ | ︙ | |||
44 45 46 47 48 49 50 | (NULL, 2, 1, 'two-a'), (NULL, 3, 1, 'three-a'); COMMIT; } } {} do_test 1.1a { db eval { | | | | | | | | | | | | | | | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | (NULL, 2, 1, 'two-a'), (NULL, 3, 1, 'three-a'); COMMIT; } } {} do_test 1.1a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} # Verify that the ORDER BY clause is optimized out # do_test 1.1b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {~/ORDER BY/} ;# ORDER BY optimized out # The same query with ORDER BY clause optimization disabled via + operators # should give exactly the same answer. # do_test 1.2a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn } } {one-a one-c two-a two-b three-a three-c} # The output is sorted manually in this case. # do_test 1.2b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn } } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms # The same query with ORDER BY optimizations turned off via built-in test. # do_test 1.3a { optimization_control db order-by-idx-join 0 db cache flush db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} do_test 1.3b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {/ORDER BY/} ;# separate sorting pass due to disabled optimization optimization_control db all 1 db cache flush # Reverse order sorts # do_test 1.4a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} do_test 1.4b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title DESC, +tn } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 1.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn } } {~/ORDER BY/} ;# optimized out do_test 1.5a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 1.5b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting do_test 1.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {~/ORDER BY/} ;# optimized out do_test 1.6a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 1.6b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 1.6c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {~/ORDER BY/} ;# ORDER BY optimized-out # Reconstruct the test data to use indices rather than integer primary keys. # do_test 2.0 { |
︙ | ︙ | |||
179 180 181 182 183 184 185 | (20, 1, 'two-a'), (3, 1, 'three-a'); COMMIT; } } {} do_test 2.1a { db eval { | | | | | | | | | | | | | | | | | | | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 | (20, 1, 'two-a'), (3, 1, 'three-a'); COMMIT; } } {} do_test 2.1a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} # Verify that the ORDER BY clause is optimized out # do_test 2.1b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {~/ORDER BY/} ;# ORDER BY optimized out do_test 2.1c { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, aid, tn } } {one-a one-c two-a two-b three-a three-c} do_test 2.1d { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, aid, tn } } {~/ORDER BY/} ;# ORDER BY optimized out # The same query with ORDER BY clause optimization disabled via + operators # should give exactly the same answer. # do_test 2.2a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn } } {one-a one-c two-a two-b three-a three-c} # The output is sorted manually in this case. # do_test 2.2b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn } } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms # The same query with ORDER BY optimizations turned off via built-in test. # do_test 2.3a { optimization_control db order-by-idx-join 0 db cache flush db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} do_test 2.3b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {/ORDER BY/} ;# separate sorting pass due to disabled optimization optimization_control db all 1 db cache flush # Reverse order sorts # do_test 2.4a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} do_test 2.4b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title DESC, +tn } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 2.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn } } {~/ORDER BY/} ;# optimized out do_test 2.5a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 2.5b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} ;# verify same order after sorting do_test 2.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {~/ORDER BY/} ;# optimized out do_test 2.6a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 2.6b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 2.6c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {~/ORDER BY/} ;# ORDER BY optimized out # Generate another test dataset, but this time using mixed ASC/DESC indices. # do_test 3.0 { |
︙ | ︙ | |||
326 327 328 329 330 331 332 | (NULL, 2, 1, 'two-a'), (NULL, 3, 1, 'three-a'); COMMIT; } } {} do_test 3.1a { db eval { | | | | | | | | | | | | | | | | | 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 | (NULL, 2, 1, 'two-a'), (NULL, 3, 1, 'three-a'); COMMIT; } } {} do_test 3.1a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} # Verify that the ORDER BY clause is optimized out # do_test 3.1b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {~/ORDER BY/} ;# ORDER BY optimized out # The same query with ORDER BY clause optimization disabled via + operators # should give exactly the same answer. # do_test 3.2a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn DESC } } {one-c one-a two-b two-a three-c three-a} # The output is sorted manually in this case. # do_test 3.2b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn DESC } } {/ORDER BY/} ;# separate sorting pass due to "+" on ORDER BY terms # The same query with ORDER BY optimizations turned off via built-in test. # do_test 3.3a { optimization_control db order-by-idx-join 0 db cache flush db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {one-c one-a two-b two-a three-c three-a} do_test 3.3b { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn DESC } } {/ORDER BY/} ;# separate sorting pass due to disabled optimization optimization_control db all 1 db cache flush # Without the mixed ASC/DESC on ORDER BY # do_test 3.4a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {one-a one-c two-a two-b three-a three-c} do_test 3.4b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title, +tn } } {one-a one-c two-a two-b three-a three-c} ;# verify same order after sorting do_test 3.4c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title, tn } } {~/ORDER BY/} ;# optimized out do_test 3.5a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {three-c three-a two-b two-a one-c one-a} do_test 3.5b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title DESC, +tn DESC } } {three-c three-a two-b two-a one-c one-a} ;# verify same order after sorting do_test 3.5c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn DESC } } {~/ORDER BY/} ;# optimzed out do_test 3.6a { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn } } {three-a three-c two-a two-b one-a one-c} do_test 3.6b { db eval { SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY +title DESC, +tn } } {three-a three-c two-a two-b one-a one-c} ;# verify same order after sorting do_test 3.6c { db eval { EXPLAIN QUERY PLAN SELECT name FROM album CROSS JOIN track USING (aid) ORDER BY title DESC, tn } } {~/ORDER BY/} ;# inverted ASC/DESC is optimized out finish_test |
Changes to test/pager1.test.
︙ | ︙ | |||
2482 2483 2484 2485 2486 2487 2488 2489 2490 | } db close file size test.db } {20971520} # Cleanup 20MB file left by the previous test. forcedelete test.db finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 | } db close file size test.db } {20971520} # Cleanup 20MB file left by the previous test. forcedelete test.db #------------------------------------------------------------------------- # Test that if a transaction is committed in journal_mode=DELETE mode, # and the call to unlink() returns an ENOENT error, the COMMIT does not # succeed. # if {$::tcl_platform(platform)=="unix"} { do_test pager1-33.1 { sqlite3 db test.db execsql { CREATE TABLE t1(x); INSERT INTO t1 VALUES('one'); INSERT INTO t1 VALUES('two'); BEGIN; INSERT INTO t1 VALUES('three'); INSERT INTO t1 VALUES('four'); } forcedelete bak-journal file rename test.db-journal bak-journal catchsql COMMIT } {1 {disk I/O error}} do_test pager1-33.2 { file rename bak-journal test.db-journal execsql { SELECT * FROM t1 } } {one two} } finish_test |
Changes to test/releasetest.tcl.
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | -DSQLITE_SOUNDEX=1 } "Update-Delete-Limit" { -O2 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 } "Debug-One" { -O2 -DSQLITE_DEBUG=1 -DSQLITE_MEMDEBUG=1 -DSQLITE_MUTEX_NOOP=1 -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 -DSQLITE_ENABLE_FTS3=1 | > > > > > > > > > > > > > > > > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | -DSQLITE_SOUNDEX=1 } "Update-Delete-Limit" { -O2 -DSQLITE_DEFAULT_FILE_FORMAT=4 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 } "Check-Symbols" { -DSQLITE_MEMDEBUG=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_RTREE=1 -DSQLITE_ENABLE_MEMSYS5=1 -DSQLITE_ENABLE_MEMSYS3=1 -DSQLITE_ENABLE_COLUMN_METADATA=1 -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1 -DSQLITE_SECURE_DELETE=1 -DSQLITE_SOUNDEX=1 -DSQLITE_ENABLE_ATOMIC_WRITE=1 -DSQLITE_ENABLE_IOTRACE=1 -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1 -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1 } "Debug-One" { -O2 -DSQLITE_DEBUG=1 -DSQLITE_MEMDEBUG=1 -DSQLITE_MUTEX_NOOP=1 -DSQLITE_TCL_DEFAULT_FULLMUTEX=1 -DSQLITE_ENABLE_FTS3=1 |
︙ | ︙ | |||
160 161 162 163 164 165 166 | -DSQLITE_DISABLE_FTS4_DEFERRED -DSQLITE_ENABLE_RTREE } } array set ::Platforms { Linux-x86_64 { | > | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | -DSQLITE_DISABLE_FTS4_DEFERRED -DSQLITE_ENABLE_RTREE } } array set ::Platforms { Linux-x86_64 { "Check-Symbols" checksymbols "Debug-One" test "Secure-Delete" test "Unlock-Notify" "QUICKTEST_INCLUDE=notify2.test test" "Update-Delete-Limit" test "Extra-Robustness" test "Device-Two" test "Ftrapv" test "Default" "threadtest test" |
︙ | ︙ | |||
326 327 328 329 330 331 332 | set config_options $::Configs($zConfig) run_test_suite $zConfig $target $config_options # If the configuration included the SQLITE_DEBUG option, then remove # it and run veryquick.test. If it did not include the SQLITE_DEBUG option # add it and run veryquick.test. | > | | | | | | | | | > | 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | set config_options $::Configs($zConfig) run_test_suite $zConfig $target $config_options # If the configuration included the SQLITE_DEBUG option, then remove # it and run veryquick.test. If it did not include the SQLITE_DEBUG option # add it and run veryquick.test. if {$target!="checksymbols"} { set debug_idx [lsearch -glob $config_options -DSQLITE_DEBUG*] if {$debug_idx < 0} { run_test_suite "${zConfig}_debug" test [ concat $config_options -DSQLITE_DEBUG=1 ] } else { run_test_suite "${zConfig}_ndebug" test [ lreplace $config_options $debug_idx $debug_idx ] } } } } main $argv |
Changes to test/shared9.test.
︙ | ︙ | |||
131 132 133 134 135 136 137 138 139 140 141 142 143 144 | set ::invoked_mycollate_db1 0 db2 eval { INSERT INTO t1 VALUES('two'); } db2 close set ::invoked_mycollate_db1 } {0} #------------------------------------------------------------------------- # This test verifies that a bug causing a busy-handler belonging to one # shared-cache connection to be executed as a result of an sqlite3_step() # on another has been fixed. # forcedelete test.db test.db2 | > > > > > > > > > > > > > > > > > > > > > > > > | 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | set ::invoked_mycollate_db1 0 db2 eval { INSERT INTO t1 VALUES('two'); } db2 close set ::invoked_mycollate_db1 } {0} forcedelete test.db test.db2 sqlite3 db1 test.db sqlite3 db2 test.db db1 collate mycollate mycollate_db1 db2 collate mycollate mycollate_db2 do_test 2.13 { set ::invoked_mycollate_db1 0 db1 eval { CREATE TABLE t1(a, CHECK (a COLLATE mycollate IN ('one', 'two', 'three'))); INSERT INTO t1 VALUES('one'); } db1 close set ::invoked_mycollate_db1 } {1} do_test 2.14 { set ::invoked_mycollate_db1 0 db2 eval { INSERT INTO t1 VALUES('two'); } db2 close set ::invoked_mycollate_db1 } {0} #------------------------------------------------------------------------- # This test verifies that a bug causing a busy-handler belonging to one # shared-cache connection to be executed as a result of an sqlite3_step() # on another has been fixed. # forcedelete test.db test.db2 |
︙ | ︙ | |||
200 201 202 203 204 205 206 | } {} db1 close db2 close sqlite3_enable_shared_cache $::enable_shared_cache finish_test | < | 224 225 226 227 228 229 230 | } {} db1 close db2 close sqlite3_enable_shared_cache $::enable_shared_cache finish_test |
Changes to test/shared_err.test.
︙ | ︙ | |||
397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | } db2 for {set i 0} {$i < 2} {incr i} { set a [string repeat $i 10] set b [string repeat $i 2000] execsql {INSERT INTO t1 VALUES($a, $b)} db2 } execsql {COMMIT} db2 set ::DB2 [sqlite3_connection_pointer db2] set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] sqlite3_step $::STMT ;# Cursor points at 0000000000 sqlite3_step $::STMT ;# Cursor points at 1111111111 } -tclbody { execsql { BEGIN; INSERT INTO t1 VALUES(6, NULL); | > > | < | 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 | } db2 for {set i 0} {$i < 2} {incr i} { set a [string repeat $i 10] set b [string repeat $i 2000] execsql {INSERT INTO t1 VALUES($a, $b)} db2 } execsql {COMMIT} db2 execsql BEGIN execsql ROLLBACK set ::DB2 [sqlite3_connection_pointer db2] set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY] sqlite3_step $::STMT ;# Cursor points at 0000000000 sqlite3_step $::STMT ;# Cursor points at 1111111111 } -tclbody { execsql { BEGIN; INSERT INTO t1 VALUES(6, NULL); ROLLBACK} } -cleanup { # UPDATE: As of [5668], if the rollback fails SQLITE_CORRUPT is returned. # So these tests have been updated to expect SQLITE_CORRUPT and its # associated English language error message. # do_test shared_malloc-8.$::n.cleanup.1 { set res [catchsql {SELECT a FROM t1} db2] |
︙ | ︙ |
Changes to test/shell1.test.
︙ | ︙ | |||
145 146 147 148 149 150 151 | do_test shell1-1.14.2 { catchcmd "-separator x test.db" "" } {0 {}} do_test shell1-1.14.3 { set res [catchcmd "-separator" ""] set rc [lindex $res 0] list $rc \ | | | | 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | do_test shell1-1.14.2 { catchcmd "-separator x test.db" "" } {0 {}} do_test shell1-1.14.3 { set res [catchcmd "-separator" ""] set rc [lindex $res 0] list $rc \ [regexp {Error: missing argument to -separator} $res] } {1 1} # -stats print memory stats before each finalize do_test shell1-1.14b.1 { catchcmd "-stats test.db" "" } {0 {}} # -nullvalue 'text' set text string for NULL values do_test shell1-1.15.1 { catchcmd "-nullvalue 'x' test.db" "" } {0 {}} do_test shell1-1.15.2 { catchcmd "-nullvalue x test.db" "" } {0 {}} do_test shell1-1.15.3 { set res [catchcmd "-nullvalue" ""] set rc [lindex $res 0] list $rc \ [regexp {Error: missing argument to -nullvalue} $res] } {1 1} # -version show SQLite version do_test shell1-1.16.1 { set x [catchcmd "-version test.db" ""] } {/3.[0-9.]+ 20\d\d-[01]\d-\d\d \d\d:\d\d:\d\d [0-9a-f]+/} |
︙ | ︙ | |||
715 716 717 718 719 720 721 | } {0 {this is a test}} # Test the output of the ".dump" command # do_test shell1-4.1 { db eval { CREATE TABLE t1(x); | | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 | } {0 {this is a test}} # Test the output of the ".dump" command # do_test shell1-4.1 { db eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(null), (''), (1), (2.25), ('hello'), (x'807f'); } catchcmd test.db {.dump} } {0 {PRAGMA foreign_keys=OFF; BEGIN TRANSACTION; CREATE TABLE t1(x); INSERT INTO "t1" VALUES(NULL); INSERT INTO "t1" VALUES(''); INSERT INTO "t1" VALUES(1); INSERT INTO "t1" VALUES(2.25); INSERT INTO "t1" VALUES('hello'); INSERT INTO "t1" VALUES(X'807F'); COMMIT;}} # Test the output of ".mode insert" # do_test shell1-4.2 { catchcmd test.db ".mode insert t1\nselect * from t1;" } {0 {INSERT INTO t1 VALUES(NULL); INSERT INTO t1 VALUES(''); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2.25); INSERT INTO t1 VALUES('hello'); INSERT INTO t1 VALUES(X'807f');}} # Test the output of ".mode tcl" # do_test shell1-4.3 { catchcmd test.db ".mode tcl\nselect * from t1;" } {0 {"" "" "1" "2.25" "hello" "\200\177"}} # Test the output of ".mode tcl" with multiple columns # do_test shell1-4.4 { db eval { CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(null, ''), (1, 2.25), ('hello', x'807f'); } catchcmd test.db ".mode tcl\nselect * from t2;" } {0 {"" "" "1" "2.25" "hello" "\200\177"}} # Test the output of ".mode tcl" with ".nullvalue" # do_test shell1-4.5 { catchcmd test.db ".mode tcl\n.nullvalue NULL\nselect * from t2;" } {0 {"NULL" "" "1" "2.25" "hello" "\200\177"}} # Test the output of ".mode tcl" with Tcl reserved characters # do_test shell1-4.6 { db eval { CREATE TABLE tcl1(x); INSERT INTO tcl1 VALUES('"'), ('['), (']'), ('\{'), ('\}'), (';'), ('$'); } foreach {x y} [catchcmd test.db ".mode tcl\nselect * from tcl1;"] break list $x $y [llength $y] } {0 {"\"" "[" "]" "\\{" "\\}" ";" "$"} 7} finish_test |
Changes to test/subquery2.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 18 19 20 21 22 23 24 | # This file implements regression tests for SQLite library. The # focus of this script is testing correlated subqueries # # set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable !subquery { finish_test return } do_test subquery2-1.1 { | > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | # This file implements regression tests for SQLite library. The # focus of this script is testing correlated subqueries # # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix subquery2 ifcapable !subquery { finish_test return } do_test subquery2-1.1 { |
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 | do_test subquery2-1.22 { execsql { SELECT a FROM t1 WHERE b=(SELECT x+1 FROM (SELECT DISTINCT f/d AS x FROM t2 JOIN t3 ON d*a=f)) } } {1 3 5 7} finish_test | > > > > > > > > > > > > > > > > > > > > | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | do_test subquery2-1.22 { execsql { SELECT a FROM t1 WHERE b=(SELECT x+1 FROM (SELECT DISTINCT f/d AS x FROM t2 JOIN t3 ON d*a=f)) } } {1 3 5 7} #------------------------------------------------------------------------- # Test that ticket d6b36be38a has been fixed. do_execsql_test 2.1 { CREATE TABLE t4(a, b); CREATE TABLE t5(a, b); INSERT INTO t5 VALUES(3, 5); INSERT INTO t4 VALUES(1, 1); INSERT INTO t4 VALUES(2, 3); INSERT INTO t4 VALUES(3, 6); INSERT INTO t4 VALUES(4, 10); INSERT INTO t4 VALUES(5, 15); } do_execsql_test 2.2 { SELECT * FROM (SELECT * FROM t4 ORDER BY a LIMIT -1 OFFSET 1) LIMIT (SELECT a FROM t5) } {2 3 3 6 4 10} finish_test |
Changes to test/thread001.test.
︙ | ︙ | |||
83 84 85 86 87 88 89 | } for {set i 0} {$i < 100} {incr i} { # Test that the invariant is true. do_test t1 { execsql { SELECT | | | 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | } for {set i 0} {$i < 100} {incr i} { # Test that the invariant is true. do_test t1 { execsql { SELECT (SELECT md5sum(a, b) FROM ab WHERE +a < (SELECT max(a) FROM ab)) == (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) } } {1} # Add another row to the database. execsql { INSERT INTO ab SELECT NULL, md5sum(a, b) FROM ab } } |
︙ | ︙ | |||
127 128 129 130 131 132 133 | # do_test thread001.$tn.5 { execsql { SELECT count(*) FROM ab; } } [expr {1 + $::NTHREAD*100}] do_test thread001.$tn.6 { execsql { SELECT | | | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | # do_test thread001.$tn.5 { execsql { SELECT count(*) FROM ab; } } [expr {1 + $::NTHREAD*100}] do_test thread001.$tn.6 { execsql { SELECT (SELECT md5sum(a, b) FROM ab WHERE +a < (SELECT max(a) FROM ab)) == (SELECT b FROM ab WHERE a = (SELECT max(a) FROM ab)) } } {1} do_test thread001.$tn.7 { execsql { PRAGMA integrity_check } } {ok} } sqlite3_enable_shared_cache $::enable_shared_cache set sqlite_open_file_count 0 finish_test |
Changes to test/tkt-31338dca7e.test.
︙ | ︙ | |||
87 88 89 90 91 92 93 | INSERT INTO t2 VALUES(10,-8); CREATE INDEX t1a ON t1(a); CREATE INDEX t1b ON t1(b); CREATE TABLE t3(g); INSERT INTO t3 VALUES(4); CREATE TABLE t4(h); INSERT INTO t4 VALUES(5); | | | 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | INSERT INTO t2 VALUES(10,-8); CREATE INDEX t1a ON t1(a); CREATE INDEX t1b ON t1(b); CREATE TABLE t3(g); INSERT INTO t3 VALUES(4); CREATE TABLE t4(h); INSERT INTO t4 VALUES(5); SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h WHERE (a=1 AND h=4) OR (b IN ( SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2) GROUP BY e )); } |
︙ | ︙ |
Changes to test/tkt2822.test.
︙ | ︙ | |||
269 270 271 272 273 274 275 | CREATE TABLE t7(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14, a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25); } catchsql { SELECT * FROM t7 ORDER BY 0; } } {1 {1st ORDER BY term out of range - should be between 1 and 25}} | | > > > > > > > > > > | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | CREATE TABLE t7(a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12,a13,a14, a15,a16,a17,a18,a19,a20,a21,a22,a23,a24,a25); } catchsql { SELECT * FROM t7 ORDER BY 0; } } {1 {1st ORDER BY term out of range - should be between 1 and 25}} do_test tkt2822-7.2.1 { catchsql { SELECT * FROM t7 ORDER BY 1, 0; } } {1 {2nd ORDER BY term out of range - should be between 1 and 25}} do_test tkt2822-7.2.2 { catchsql { SELECT * FROM t7 ORDER BY 1, 26; } } {1 {2nd ORDER BY term out of range - should be between 1 and 25}} do_test tkt2822-7.2.3 { catchsql { SELECT * FROM t7 ORDER BY 1, 65536; } } {1 {2nd ORDER BY term out of range - should be between 1 and 25}} do_test tkt2822-7.3 { catchsql { SELECT * FROM t7 ORDER BY 1, 2, 0; } } {1 {3rd ORDER BY term out of range - should be between 1 and 25}} |
︙ | ︙ |
Changes to test/tkt3527.test.
︙ | ︙ | |||
48 49 50 51 52 53 54 | INSERT INTO Element VALUES(1,'Elem1'); INSERT INTO Element VALUES(2,'Elem2'); INSERT INTO Element VALUES(3,'Elem3'); INSERT INTO Element VALUES(4,'Elem4'); INSERT INTO Element VALUES(5,'Elem5'); INSERT INTO ElemOr Values(3,4); INSERT INTO ElemOr Values(3,5); | | | | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | INSERT INTO Element VALUES(1,'Elem1'); INSERT INTO Element VALUES(2,'Elem2'); INSERT INTO Element VALUES(3,'Elem3'); INSERT INTO Element VALUES(4,'Elem4'); INSERT INTO Element VALUES(5,'Elem5'); INSERT INTO ElemOr Values(3,4); INSERT INTO ElemOr Values(3,5); INSERT INTO ElemAnd VALUES(1,3,'a','b','c'); INSERT INTO ElemAnd VALUES(1,2,'x','y','z'); CREATE VIEW ElemView1 AS SELECT CAST(Element.Code AS VARCHAR(50)) AS ElemId, Element.Code AS ElemCode, Element.Name AS ElemName, ElemAnd.Code AS InnerCode, |
︙ | ︙ | |||
108 109 110 111 112 113 114 | FROM ElemView1 AS Element JOIN ElemView1 AS InnerElem ON Element.Level=0 AND Element.InnerCode=InnerElem.ElemCode ORDER BY ElemId, InnerCode; SELECT * FROM ElemView1; } | | | | 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | FROM ElemView1 AS Element JOIN ElemView1 AS InnerElem ON Element.Level=0 AND Element.InnerCode=InnerElem.ElemCode ORDER BY ElemId, InnerCode; SELECT * FROM ElemView1; } } {1 1 Elem1 2 x y z 0 0 1 1 Elem1 3 a b c 0 0 3 3 Elem3 4 {} {} {} 0 1 3 3 Elem3 5 {} {} {} 0 1} do_test tkt3527-1.2 { db eval { SELECT * FROM ElemView2; } } {1 1 Elem1 2 x y z 0 0 1 1 Elem1 3 a b c 0 0 1.3 3 Elem3 4 {} {} {} 1 1 1.3 3 Elem3 5 {} {} {} 1 1 3 3 Elem3 4 {} {} {} 0 1 3 3 Elem3 5 {} {} {} 0 1} finish_test |
Changes to test/triggerC.test.
︙ | ︙ | |||
945 946 947 948 949 950 951 | UPDATE t12 SET a=new.a+1, b=new.b+1; END; } {} do_catchsql_test triggerC-13.2 { UPDATE t12 SET a=a+1, b=b+1; } {1 {too many levels of trigger recursion}} | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 | UPDATE t12 SET a=new.a+1, b=new.b+1; END; } {} do_catchsql_test triggerC-13.2 { UPDATE t12 SET a=a+1, b=b+1; } {1 {too many levels of trigger recursion}} #------------------------------------------------------------------------- # The following tests seek to verify that constant values (i.e. literals) # are not factored out of loops within trigger programs. SQLite does # not factor constants out of loops within trigger programs as it may only # do so in code generated before the first table or index is opened. And # by the time a trigger program is coded, at least one table or index has # always been opened. # # At one point, due to a bug allowing constant factoring within triggers, # the following SQL would produce the wrong result. # set SQL { CREATE TABLE t1(a, b, c); CREATE INDEX i1 ON t1(a, c); CREATE INDEX i2 ON t1(b, c); INSERT INTO t1 VALUES(1, 2, 3); CREATE TABLE t2(e, f); CREATE INDEX i3 ON t2(e); INSERT INTO t2 VALUES(1234567, 3); CREATE TABLE empty(x); CREATE TABLE not_empty(x); INSERT INTO not_empty VALUES(2); CREATE TABLE t4(x); CREATE TABLE t5(g, h, i); CREATE TRIGGER trig BEFORE INSERT ON t4 BEGIN INSERT INTO t5 SELECT * FROM t1 WHERE (a IN (SELECT x FROM empty) OR b IN (SELECT x FROM not_empty)) AND c IN (SELECT f FROM t2 WHERE e=1234567); END; INSERT INTO t4 VALUES(0); SELECT * FROM t5; } reset_db do_execsql_test triggerC-14.1 $SQL {1 2 3} reset_db optimization_control db factor-constants 0 do_execsql_test triggerC-14.2 $SQL {1 2 3} finish_test |
Changes to test/vtab1.test.
︙ | ︙ | |||
1330 1331 1332 1333 1334 1335 1336 1337 1338 | } SQLITE_OK do_test 19.2 { register_echo_module [sqlite3_connection_pointer db2] } SQLITE_MISUSE do_test 19.3 { db2 close } {} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 | } SQLITE_OK do_test 19.2 { register_echo_module [sqlite3_connection_pointer db2] } SQLITE_MISUSE do_test 19.3 { db2 close } {} #------------------------------------------------------------------------- # Test that the bug fixed by [b0c1ba655d69] really is fixed. # do_execsql_test 20.1 { CREATE TABLE t7 (a, b); CREATE TABLE t8 (c, d); CREATE INDEX i2 ON t7(a); CREATE INDEX i3 ON t7(b); CREATE INDEX i4 ON t8(c); CREATE INDEX i5 ON t8(d); CREATE VIRTUAL TABLE t7v USING echo(t7); CREATE VIRTUAL TABLE t8v USING echo(t8); } do_test 20.2 { for {set i 0} {$i < 1000} {incr i} { db eval {INSERT INTO t7 VALUES($i, $i)} db eval {INSERT INTO t8 VALUES($i, $i)} } } {} do_execsql_test 20.3 { SELECT a, b FROM ( SELECT a, b FROM t7 WHERE a=11 OR b=12 UNION ALL SELECT c, d FROM t8 WHERE c=5 OR d=6 ) ORDER BY 1, 2; } {5 5 6 6 11 11 12 12} do_execsql_test 20.4 { SELECT a, b FROM ( SELECT a, b FROM t7v WHERE a=11 OR b=12 UNION ALL SELECT c, d FROM t8v WHERE c=5 OR d=6 ) ORDER BY 1, 2; } {5 5 6 6 11 11 12 12} finish_test |
Changes to test/wal9.test.
︙ | ︙ | |||
56 57 58 59 60 61 62 63 | INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; COMMIT; } {} # Check file sizes are as expected. The real requirement here is that # the *shm file is now more than one chunk (>32KiB). do_test 1.3 { file size test.db } {1024} | > > > | | | | > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | INSERT INTO t SELECT randomblob(100) FROM t; INSERT INTO t SELECT randomblob(100) FROM t; COMMIT; } {} # Check file sizes are as expected. The real requirement here is that # the *shm file is now more than one chunk (>32KiB). # # The sizes of various files are slightly different in normal and # auto-vacuum mode. do_test 1.3 { file size test.db } {1024} do_test 1.4 { expr {[file size test.db-wal]>(1500*1024)} } {1} do_test 1.5 { expr {[file size test.db-shm]>32768} } {1} do_test 1.6 { foreach {a b c} [db eval {PRAGMA wal_checkpoint}] break list [expr {$a==0}] [expr {$b>14500}] [expr {$c>14500}] [expr {$b==$c}] } {1 1 1 1} # At this point connection [db2] has mapped the first 32KB of the *shm file # only. Because the entire WAL file has been checkpointed, it is not # necessary to map any more of the *-shm file to read or write the database # (since all data will be read directly from the db file). # # However, at one point if a transaction that had not yet written to the |
︙ | ︙ | |||
83 84 85 86 87 88 89 | INSERT INTO t VALUES('hello'); ROLLBACK; } db2 } {} db2 close finish_test | < | 88 89 90 91 92 93 94 | INSERT INTO t VALUES('hello'); ROLLBACK; } db2 } {} db2 close finish_test |
Changes to test/where.test.
︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 | } {1 one 4 four nosort} # Ticket #2211. # # When optimizing out ORDER BY clauses, make sure that trailing terms # of the ORDER BY clause do not reference other tables in a join. # do_test where-14.1 { execsql { CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT UNIQUE); INSERT INTO t8 VALUES(1,'one'); INSERT INTO t8 VALUES(4,'four'); } cksort { | > | 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 | } {1 one 4 four nosort} # Ticket #2211. # # When optimizing out ORDER BY clauses, make sure that trailing terms # of the ORDER BY clause do not reference other tables in a join. # if {[permutation] != "no_optimization"} { do_test where-14.1 { execsql { CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT UNIQUE); INSERT INTO t8 VALUES(1,'one'); INSERT INTO t8 VALUES(4,'four'); } cksort { |
︙ | ︙ | |||
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 | } } {4/1 4/4 1/1 1/4 sort} do_test where-14.12 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, y.a||x.b DESC } } {4/4 4/1 1/4 1/1 sort} # Ticket #2445. # # There was a crash that could occur when a where clause contains an # alias for an expression in the result set, and that expression retrieves # a column of the second or subsequent table in a join. # | > | 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | } } {4/1 4/4 1/1 1/4 sort} do_test where-14.12 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.b, y.a||x.b DESC } } {4/4 4/1 1/4 1/1 sort} } ;# {permutation != "no_optimization"} # Ticket #2445. # # There was a crash that could occur when a where clause contains an # alias for an expression in the result set, and that expression retrieves # a column of the second or subsequent table in a join. # |
︙ | ︙ |
Added test/whereE.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # 2012 November 9 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the query planner to make sure it # is making good planning decisions. # set testdir [file dirname $argv0] source $testdir/tester.tcl set ::testprefix whereE do_execsql_test 1.1 { CREATE TABLE t1(a,b); INSERT INTO t1 VALUES(1,10), (2,20), (3,30), (2,22), (3, 33); INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; INSERT INTO t1 SELECT * FROM t1; ALTER TABLE t1 ADD COLUMN c; UPDATE t1 SET c=a*rowid+10000; CREATE INDEX t1ab ON t1(a,b); CREATE TABLE t2(x,y); INSERT INTO t2 VALUES(4,44),(5,55),(6,66),(7,77); INSERT INTO t2 SELECT x+4, (x+4)*11 FROM t2; INSERT INTO t2 SELECT x+8, (x+8)*11 FROM t2; INSERT INTO t2 SELECT x+16, (x+16)*11 FROM t2; INSERT INTO t2 SELECT x+32, (x+32)*11 FROM t2; INSERT INTO t2 SELECT x+64, (x+32)*11 FROM t2; ALTER TABLE t2 ADD COLUMN z; UPDATE t2 SET z=2; CREATE UNIQUE INDEX t2zx ON t2(z,x); EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x; } {/.*SCAN TABLE t1 .*SEARCH TABLE t2 .*/} do_execsql_test 1.2 { EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x; } {/.*SCAN TABLE t1 .*SEARCH TABLE t2 .*/} do_execsql_test 1.3 { ANALYZE; EXPLAIN QUERY PLAN SELECT x FROM t1, t2 WHERE a=z AND c=x; } {/.*SCAN TABLE t1 .*SEARCH TABLE t2 .*/} do_execsql_test 1.4 { EXPLAIN QUERY PLAN SELECT x FROM t2, t1 WHERE a=z AND c=x; } {/.*SCAN TABLE t1 .*SEARCH TABLE t2 .*/} finish_test |
Added test/whereF.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # 2012 November 9 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Test cases for query planning decisions. # # The tests in this file demonstrate the behaviour of the query planner # in determining the order in which joined tables are scanned. # # Assume there are two tables being joined - t1 and t2. Each has a cost # if it is the outer loop, and a cost if it is the inner loop. As follows: # # t1(outer) - cost of scanning t1 as the outer loop. # t1(inner) - cost of scanning t1 as the inner loop. # t2(outer) - cost of scanning t2 as the outer loop. # t2(inner) - cost of scanning t2 as the inner loop. # # Depending on the order in which the planner nests the scans, the total # cost of the join query is one of: # # t1(outer) * t2(inner) # t2(outer) * t1(inner) # # The tests in this file attempt to verify that the planner nests joins in # the correct order when the following are true: # # + (t1(outer) * t2(inner)) > (t1(inner) * t2(outer) # + t1(outer) < t2(outer) # # In other words, when the best overall query plan has t2 as the outer loop, # but when the outer loop is considered independent of the inner, t1 is the # most efficient choice. # # In order to make them more predictable, automatic indexes are turned off for # the tests in this file. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix x do_execsql_test 1.0 { PRAGMA automatic_index = 0; CREATE TABLE t1(a, b, c); CREATE TABLE t2(d, e, f); CREATE UNIQUE INDEX i1 ON t1(a); CREATE UNIQUE INDEX i2 ON t2(d); } {} foreach {tn sql} { 1 "SELECT * FROM t1, t2 WHERE t1.a=t2.e AND t2.d<t1.b AND t1.c!=10" 2 "SELECT * FROM t2, t1 WHERE t1.a=t2.e AND t2.d<t1.b AND t1.c!=10" 3 "SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a=t2.e AND t2.d<t1.b AND t1.c!=10" } { do_test 1.$tn { db eval "EXPLAIN QUERY PLAN $sql" } {/.*SCAN TABLE t2 .*SEARCH TABLE t1 .*/} } do_execsql_test 2.0 { DROP TABLE t1; DROP TABLE t2; CREATE TABLE t1(a, b, c); CREATE TABLE t2(d, e, f); CREATE UNIQUE INDEX i1 ON t1(a); CREATE UNIQUE INDEX i2 ON t1(b); CREATE UNIQUE INDEX i3 ON t2(d); } {} foreach {tn sql} { 1 "SELECT * FROM t1, t2 WHERE t1.a>? AND t2.d>t1.c AND t1.b=t2.e" 2 "SELECT * FROM t2, t1 WHERE t1.a>? AND t2.d>t1.c AND t1.b=t2.e" 3 "SELECT * FROM t2 CROSS JOIN t1 WHERE t1.a>? AND t2.d>t1.c AND t1.b=t2.e" } { do_test 2.$tn { db eval "EXPLAIN QUERY PLAN $sql" } {/.*SCAN TABLE t2 .*SEARCH TABLE t1 .*/} } do_execsql_test 3.0 { DROP TABLE t1; DROP TABLE t2; CREATE TABLE t1(a, b, c); CREATE TABLE t2(d, e, f); CREATE UNIQUE INDEX i1 ON t1(a, b); CREATE INDEX i2 ON t2(d); } {} foreach {tn sql} { 1 {SELECT t1.a, t1.b, t2.d, t2.e FROM t1, t2 WHERE t2.d=t1.b AND t1.a=(t2.d+1) AND t1.b = (t2.e+1)} 2 {SELECT t1.a, t1.b, t2.d, t2.e FROM t2, t1 WHERE t2.d=t1.b AND t1.a=(t2.d+1) AND t1.b = (t2.e+1)} 3 {SELECT t1.a, t1.b, t2.d, t2.e FROM t2 CROSS JOIN t1 WHERE t2.d=t1.b AND t1.a=(t2.d+1) AND t1.b = (t2.e+1)} } { do_test 3.$tn { db eval "EXPLAIN QUERY PLAN $sql" } {/.*SCAN TABLE t2 .*SEARCH TABLE t1 .*/} } finish_test |
Changes to tool/build-all-msvc.bat.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @ECHO OFF :: :: build-all-msvc.bat -- :: :: Multi-Platform Build Tool for MSVC :: SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO REM SET __ECHO3=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) IF NOT DEFINED _CECHO (SET _CECHO=REM) | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | @ECHO OFF :: :: build-all-msvc.bat -- :: :: Multi-Platform Build Tool for MSVC :: REM REM This batch script is used to build the SQLite DLL for multiple platforms REM and configurations using MSVC. The built SQLite DLLs, their associated REM import libraries, and optionally their symbols files, are placed within REM the directory specified on the command line, in sub-directories named for REM their respective platforms and configurations. This batch script must be REM run from inside a Visual Studio Command Prompt for the desired version of REM Visual Studio ^(the initial platform configured for the command prompt does REM not really matter^). Exactly one command line argument is required, the REM name of an existing directory to be used as the final destination directory REM for the generated output files, which will be placed in sub-directories REM created therein. Ideally, the directory specified should be empty. REM REM Example: REM REM CD /D C:\dev\sqlite\core REM tool\build-all-msvc.bat C:\Temp REM REM In the example above, "C:\dev\sqlite\core" represents the root of the REM source tree for SQLite and "C:\Temp" represents the final destination REM directory for the generated output files. REM REM There are several environment variables that may be set to modify the REM behavior of this batch script and its associated Makefile. The list of REM platforms to build may be overriden by using the PLATFORMS environment REM variable, which should contain a list of platforms ^(e.g. x86 x86_amd64 REM x86_arm^). All platforms must be supported by the version of Visual Studio REM being used. The list of configurations to build may be overridden by REM setting the CONFIGURATIONS environment variable, which should contain a REM list of configurations to build ^(e.g. Debug Retail^). Neither of these REM variable values may contain any double quotes, surrounding or embedded. REM Finally, the NCRTLIBPATH and NSDKLIBPATH environment variables may be set REM to specify the location of the CRT and SDK, respectively, needed to compile REM executables native to the architecture of the build machine during any REM cross-compilation that may be necessary, depending on the platforms to be REM built. These values in these two variables should be surrounded by double REM quotes if they contain spaces. REM REM Please note that the SQLite build process performed by the Makefile REM associated with this batch script requires both Gawk ^(gawk.exe^) and Tcl REM 8.5 ^(tclsh85.exe^) to be present in a directory contained in the PATH REM environment variable unless a pre-existing amalgamation file is used. REM SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO REM SET __ECHO3=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) IF NOT DEFINED _CECHO (SET _CECHO=REM) |
︙ | ︙ | |||
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | REM IF NOT DEFINED PLATFORMS ( SET PLATFORMS=x86 x86_amd64 x86_arm ) %_VECHO% Platforms = '%PLATFORMS%' REM REM NOTE: Setup environment variables to translate between the MSVC platform REM names and the names to be used for the platform-specific binary REM directories. REM SET x86_NAME=x86 SET x86_amd64_NAME=x64 SET x86_arm_NAME=ARM %_VECHO% x86_Name = '%x86_NAME%' %_VECHO% x86_amd64_Name = '%x86_amd64_NAME%' %_VECHO% x86_arm_Name = '%x86_arm_NAME%' REM REM NOTE: Check for the external tools needed during the build process ^(i.e. REM those that do not get compiled as part of the build process itself^) REM along the PATH. REM FOR %%T IN (gawk.exe tclsh85.exe) DO ( SET %%T_PATH=%%~dp$PATH:T ) REM REM NOTE: Set the TOOLPATH variable to contain all the directories where the REM external tools were found in the search above. REM SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH% %_VECHO% ToolPath = '%TOOLPATH%' REM REM NOTE: Check for MSVC 2012 because the Windows SDK directory handling is REM slightly different for that version. REM IF "%VisualStudioVersion%" == "11.0" ( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | REM IF NOT DEFINED PLATFORMS ( SET PLATFORMS=x86 x86_amd64 x86_arm ) %_VECHO% Platforms = '%PLATFORMS%' REM REM NOTE: If the list of configurations is not already set, use the default REM list. REM IF NOT DEFINED CONFIGURATIONS ( SET CONFIGURATIONS=Debug Retail ) %_VECHO% Configurations = '%CONFIGURATIONS%' REM REM NOTE: Setup environment variables to translate between the MSVC platform REM names and the names to be used for the platform-specific binary REM directories. REM SET amd64_NAME=x64 SET arm_NAME=ARM SET x64_NAME=x64 SET x86_NAME=x86 SET x86_amd64_NAME=x64 SET x86_arm_NAME=ARM SET x86_x64_NAME=x64 %_VECHO% amd64_Name = '%amd64_NAME%' %_VECHO% arm_Name = '%arm_NAME%' %_VECHO% x64_Name = '%x64_NAME%' %_VECHO% x86_Name = '%x86_NAME%' %_VECHO% x86_amd64_Name = '%x86_amd64_NAME%' %_VECHO% x86_arm_Name = '%x86_arm_NAME%' %_VECHO% x86_x64_Name = '%x86_x64_NAME%' REM REM NOTE: Check for the external tools needed during the build process ^(i.e. REM those that do not get compiled as part of the build process itself^) REM along the PATH. REM FOR %%T IN (gawk.exe tclsh85.exe) DO ( SET %%T_PATH=%%~dp$PATH:T ) REM REM NOTE: The Gawk executable "gawk.exe" is required during the SQLite build REM process unless a pre-existing amalgamation file is used. REM IF NOT DEFINED gawk.exe_PATH ( ECHO The Gawk executable "gawk.exe" is required to be in the PATH. GOTO errors ) REM REM NOTE: The Tcl 8.5 executable "tclsh85.exe" is required during the SQLite REM build process unless a pre-existing amalgamation file is used. REM IF NOT DEFINED tclsh85.exe_PATH ( ECHO The Tcl 8.5 executable "tclsh85.exe" is required to be in the PATH. GOTO errors ) REM REM NOTE: Set the TOOLPATH variable to contain all the directories where the REM external tools were found in the search above. REM SET TOOLPATH=%gawk.exe_PATH%;%tclsh85.exe_PATH% %_VECHO% ToolPath = '%TOOLPATH%' REM REM NOTE: Check for MSVC 2012 because the Windows SDK directory handling is REM slightly different for that version. REM IF "%VisualStudioVersion%" == "11.0" ( REM REM NOTE: If the Windows SDK library path has already been set, do not set REM it to something else later on. REM IF NOT DEFINED NSDKLIBPATH ( SET SET_NSDKLIBPATH=1 ) ) ELSE ( CALL :fn_UnsetVariable SET_NSDKLIBPATH ) REM REM NOTE: Check if this is the Windows Phone SDK. If so, a different batch REM file is necessary to setup the build environment. Since the variable REM values involved here may contain parenthesis, using GOTO instead of REM an IF block is required. REM IF DEFINED WindowsPhoneKitDir GOTO set_vcvarsall_phone SET VCVARSALL=%VCINSTALLDIR%\vcvarsall.bat GOTO set_vcvarsall_done :set_vcvarsall_phone SET VCVARSALL=%VCINSTALLDIR%\WPSDK\WP80\vcvarsphoneall.bat :set_vcvarsall_done REM REM NOTE: This is the outer loop. There should be exactly one iteration per REM platform. REM FOR %%P IN (%PLATFORMS%) DO ( REM REM NOTE: Using the MSVC platform name, lookup the simpler platform name to |
︙ | ︙ | |||
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | CALL :fn_UnsetVariable FSHARPINSTALLDIR CALL :fn_UnsetVariable INCLUDE CALL :fn_UnsetVariable LIB CALL :fn_UnsetVariable LIBPATH CALL :fn_UnsetVariable Platform REM CALL :fn_UnsetVariable VCINSTALLDIR CALL :fn_UnsetVariable VSINSTALLDIR CALL :fn_UnsetVariable WindowsSdkDir CALL :fn_UnsetVariable WindowsSdkDir_35 CALL :fn_UnsetVariable WindowsSdkDir_old REM REM NOTE: Reset the PATH here to the absolute bare minimum required. REM SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot% | > | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | CALL :fn_UnsetVariable FSHARPINSTALLDIR CALL :fn_UnsetVariable INCLUDE CALL :fn_UnsetVariable LIB CALL :fn_UnsetVariable LIBPATH CALL :fn_UnsetVariable Platform REM CALL :fn_UnsetVariable VCINSTALLDIR CALL :fn_UnsetVariable VSINSTALLDIR CALL :fn_UnsetVariable WindowsPhoneKitDir CALL :fn_UnsetVariable WindowsSdkDir CALL :fn_UnsetVariable WindowsSdkDir_35 CALL :fn_UnsetVariable WindowsSdkDir_old REM REM NOTE: Reset the PATH here to the absolute bare minimum required. REM SET PATH=%TOOLPATH%;%SystemRoot%\System32;%SystemRoot% FOR %%B IN (%CONFIGURATIONS%) DO ( REM REM NOTE: When preparing the debug build, set the DEBUG and MEMDEBUG REM environment variables to be picked up by the MSVC makefile REM itself. REM IF /I "%%B" == "Debug" ( SET DEBUG=2 |
︙ | ︙ | |||
211 212 213 214 215 216 217 | REM platform to the platform-specific directory beneath the REM binary directory. REM "%ComSpec%" /C ( REM REM NOTE: Attempt to setup the MSVC environment for this platform. REM | | | | > | | | > > > > > | | > | 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 | REM platform to the platform-specific directory beneath the REM binary directory. REM "%ComSpec%" /C ( REM REM NOTE: Attempt to setup the MSVC environment for this platform. REM %__ECHO3% CALL "%VCVARSALL%" %%P IF ERRORLEVEL 1 ( ECHO Failed to call "%VCVARSALL%" for platform %%P. GOTO errors ) REM REM NOTE: If this batch file is not running in "what-if" mode, check to REM be sure we were actually able to setup the MSVC environment REM as current versions of their official batch file do not set REM the exit code upon failure. REM IF NOT DEFINED __ECHO3 ( IF NOT DEFINED WindowsPhoneKitDir ( IF NOT DEFINED WindowsSdkDir ( ECHO Cannot build, Windows SDK not found for platform %%P. GOTO errors ) ) ) REM REM NOTE: When using MSVC 2012, the native SDK path cannot simply use REM the "lib" sub-directory beneath the location specified in the REM WindowsSdkDir environment variable because that location does REM not actually contain the necessary library files for x86. REM This must be done for each iteration because it relies upon REM the WindowsSdkDir environment variable being set by the batch REM file used to setup the MSVC environment. REM IF DEFINED SET_NSDKLIBPATH ( IF DEFINED WindowsPhoneKitDir ( CALL :fn_CopyVariable WindowsPhoneKitDir NSDKLIBPATH CALL :fn_AppendVariable NSDKLIBPATH \lib\x86 ) ELSE IF DEFINED WindowsSdkDir ( CALL :fn_CopyVariable WindowsSdkDir NSDKLIBPATH CALL :fn_AppendVariable NSDKLIBPATH \lib\win8\um\x86 ) ) REM REM NOTE: Unless prevented from doing so, invoke NMAKE with the MSVC REM makefile to clean any stale build output from previous REM iterations of this loop and/or previous runs of this batch REM file, etc. |
︙ | ︙ |
Changes to tool/mkvsix.tcl.
1 2 3 4 | #!/usr/bin/tclsh # # This script is used to generate a VSIX (Visual Studio Extension) file for # SQLite usable by Visual Studio. | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | #!/usr/bin/tclsh # # This script is used to generate a VSIX (Visual Studio Extension) file for # SQLite usable by Visual Studio. # # PREREQUISITES # # 1. Tcl 8.4 and later are supported, earlier versions have not been tested. # # 2. The "sqlite3.h" file is assumed to exist in the parent directory of the # directory containing this script. The [optional] second command line # argument to this script may be used to specify an alternate location. # This script also assumes that the "sqlite3.h" file corresponds with the # version of the binaries to be packaged. This assumption is not verified # by this script. # # 3. The temporary directory specified in the TEMP or TMP environment variables # must refer to an existing directory writable by the current user. # # 4. The "zip" and "unzip" command line tools must be located either in a # directory contained in the PATH environment variable or specified as the # exact file names to execute in the "ZipTool" and "UnZipTool" environment # variables, respectively. # # 5. The template VSIX file (which is basically a zip file) must be located in # a "win" directory inside the directory containing this script. It should # not contain any executable binaries. It should only contain dynamic # textual content files to be processed using [subst] and/or static content # files to be copied verbatim. # # 6. The executable and other compiled binary files to be packaged into the # final VSIX file (e.g. DLLs, LIBs, and PDBs) must be located in a single # directory tree. The top-level directory of the tree must be specified as # the first command line argument to this script. The second level # sub-directory names must match those of the build configuration (e.g. # "Debug" or "Retail"). The third level sub-directory names must match # those of the platform (e.g. "x86", "x64", and "ARM"). For example, the # binary files to be packaged would need to be organized as follows when # packaging the "Debug" and "Retail" build configurations for the "x86" and # "x64" platforms (in this example, "C:\temp" is the top-level directory as # specified in the first command line argument): # # C:\Temp\Debug\x86\sqlite3.lib # C:\Temp\Debug\x86\sqlite3.dll # C:\Temp\Debug\x86\sqlite3.pdb # C:\Temp\Debug\x64\sqlite3.lib # C:\Temp\Debug\x64\sqlite3.dll # C:\Temp\Debug\x64\sqlite3.pdb # C:\Temp\Retail\x86\sqlite3.lib # C:\Temp\Retail\x86\sqlite3.dll # C:\Temp\Retail\x86\sqlite3.pdb # C:\Temp\Retail\x64\sqlite3.lib # C:\Temp\Retail\x64\sqlite3.dll # C:\Temp\Retail\x64\sqlite3.pdb # # The above directory tree organization is performed automatically if the # "tool\build-all-msvc.bat" batch script is used to build the binary files # to be packaged. # # USAGE # # The first argument to this script is required and must be the name of the # top-level directory containing the directories and files organized into a # tree as described in item 6 of the PREREQUISITES section, above. The second # argument is optional and if present must contain the name of the directory # containing the root of the source tree for SQLite. The third argument is # optional and if present must contain the flavor the VSIX package to build. # Currently, the only supported package flavors are "WinRT" and "WP80". The # fourth argument is optional and if present must be a string containing a list # of platforms to include in the VSIX package. The format of the platform list # string is "platform1,platform2,platform3". Typically, when on Windows, this # script is executed using commands similar to the following from a normal # Windows command prompt: # # CD /D C:\dev\sqlite\core # tclsh85 tool\mkvsix.tcl C:\Temp # # In the example above, "C:\dev\sqlite\core" represents the root of the source # tree for SQLite and "C:\Temp" represents the top-level directory containing # the executable and other compiled binary files, organized into a directory # tree as described in item 6 of the PREREQUISITES section, above. # # This script should work on non-Windows platforms as well, provided that all # the requirements listed in the PREREQUISITES section are met. # # NOTES # # The temporary directory is used as a staging area for the final VSIX file. # The template VSIX file is extracted, its contents processed, and then the # resulting files are packaged into the final VSIX file. # package require Tcl 8.4 proc fail { {error ""} {usage false} } { if {[string length $error] > 0} then { puts stdout $error if {!$usage} then {exit 1} } puts stdout "usage:\ [file tail [info nameofexecutable]]\ [file tail [info script]] <binaryDirectory> \[sourceDirectory\]\ \[packageFlavor\] \[platformNames\]" exit 1 } proc getEnvironmentVariable { name } { # # NOTE: Returns the value of the specified environment variable or an empty |
︙ | ︙ | |||
80 81 82 83 84 85 86 | close $file_id return "" } proc substFile { fileName } { # # NOTE: Performs all Tcl command, variable, and backslash substitutions in | | | | | > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 | close $file_id return "" } proc substFile { fileName } { # # NOTE: Performs all Tcl command, variable, and backslash substitutions in # the specified file and then rewrites the contents of that same file # with the substituted data. # return [writeFile $fileName [uplevel 1 [list subst [readFile $fileName]]]] } proc replaceFileNameTokens { fileName name buildName platformName } { # # NOTE: Returns the specified file name containing the platform name instead # of platform placeholder tokens. # return [string map [list <build> $buildName <platform> $platformName \ <name> $name] $fileName] } # # NOTE: This is the entry point for this script. # set script [file normalize [info script]] if {[string length $script] == 0} then { fail "script file currently being evaluated is unknown" true } set path [file dirname $script] set rootName [file rootname [file tail $script]] ############################################################################### # # NOTE: Process and verify all the command line arguments. # set argc [llength $argv] if {$argc < 1 || $argc > 4} then {fail} set binaryDirectory [lindex $argv 0] if {[string length $binaryDirectory] == 0} then { fail "invalid binary directory" } if {![file exists $binaryDirectory] || \ ![file isdirectory $binaryDirectory]} then { fail "binary directory does not exist" } if {$argc >= 2} then { set sourceDirectory [lindex $argv 1] } else { # # NOTE: Assume that the source directory is the parent directory of the one # that contains this script file. # set sourceDirectory [file dirname $path] } if {[string length $sourceDirectory] == 0} then { fail "invalid source directory" } if {![file exists $sourceDirectory] || \ ![file isdirectory $sourceDirectory]} then { fail "source directory does not exist" } if {$argc >= 3} then { set packageFlavor [lindex $argv 2] } else { # # NOTE: Assume the package flavor is WinRT. # set packageFlavor WinRT } if {[string length $packageFlavor] == 0} then { fail "invalid package flavor" } if {[string equal -nocase $packageFlavor WinRT]} then { set shortName SQLite.WinRT set displayName "SQLite for Windows Runtime" set targetPlatformIdentifier Windows set extraSdkPath "" set extraFileListAttributes [appendArgs \ "\r\n " {AppliesTo="WindowsAppContainer"} \ "\r\n " {DependsOn="Microsoft.VCLibs, version=11.0"}] } elseif {[string equal -nocase $packageFlavor WP80]} then { set shortName SQLite.WP80 set displayName "SQLite for Windows Phone" set targetPlatformIdentifier "Windows Phone" set extraSdkPath "\\..\\$targetPlatformIdentifier" set extraFileListAttributes "" } else { fail "unsupported package flavor, must be \"WinRT\" or \"WP80\"" } if {$argc >= 4} then { set platformNames [list] foreach platformName [split [lindex $argv 3] ", "] { if {[string length $platformName] > 0} then { lappend platformNames $platformName } } } ############################################################################### # # NOTE: Evaluate the user-specific customizations file, if it exists. # set userFile [file join $path [appendArgs \ |
︙ | ︙ | |||
165 166 167 168 169 170 171 | if {![file exists $templateFile] || \ ![file isfile $templateFile]} then { fail [appendArgs "template file \"" $templateFile "\" does not exist"] } set currentDirectory [pwd] | | > | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 | if {![file exists $templateFile] || \ ![file isfile $templateFile]} then { fail [appendArgs "template file \"" $templateFile "\" does not exist"] } set currentDirectory [pwd] set outputFile [file join $currentDirectory [appendArgs sqlite- \ $packageFlavor -output.vsix]] if {[file exists $outputFile]} then { fail [appendArgs "output file \"" $outputFile "\" already exists"] } ############################################################################### |
︙ | ︙ | |||
241 242 243 244 245 246 247 | fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \ [file join $sourceDirectory sqlite3.h] \"] } ############################################################################### # | | > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | | | | | | < | | | | | | < < < < | < < | < | < < | < < | < < < < < < < < < < < < < < < < | > | > > | | | | | > > | | | | | | | > | > | | | | > | | > > > > > | | | | | | | | | > | > | > > > > > > > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | fail [appendArgs "cannot locate SQLITE_VERSION value in \"" \ [file join $sourceDirectory sqlite3.h] \"] } ############################################################################### # # NOTE: Setup all the master file list data. This includes the source file # names, the destination file names, and the file processing flags. The # possible file processing flags are: # # "buildNeutral" -- This flag indicates the file location and content do # not depend on the build configuration. # # "platformNeutral" -- This flag indicates the file location and content # do not depend on the build platform. # # "subst" -- This flag indicates that the file contains dynamic textual # content that needs to be processed using [subst] prior to # packaging the file into the final VSIX package. The primary # use of this flag is to insert the name of the VSIX package, # some package flavor-specific value, or the SQLite version # into a file. # # "noDebug" -- This flag indicates that the file should be skipped when # processing the debug build. # # "noRetail" -- This flag indicates that the file should be skipped when # processing the retail build. # # "move" -- This flag indicates that the file should be moved from the # source to the destination instead of being copied. # # This file metadata may be overridden, either in whole or in part, via # the user-specific customizations file. # if {![info exists fileNames(source)]} then { set fileNames(source) [list "" "" \ [file join $stagingDirectory DesignTime <build> <platform> sqlite3.props] \ [file join $sourceDirectory sqlite3.h] \ [file join $binaryDirectory <build> <platform> sqlite3.lib] \ [file join $binaryDirectory <build> <platform> sqlite3.dll]] if {![info exists no(symbols)]} then { lappend fileNames(source) \ [file join $binaryDirectory <build> <platform> sqlite3.pdb] } } if {![info exists fileNames(destination)]} then { set fileNames(destination) [list \ [file join $stagingDirectory extension.vsixmanifest] \ [file join $stagingDirectory SDKManifest.xml] \ [file join $stagingDirectory DesignTime <build> <platform> <name>.props] \ [file join $stagingDirectory DesignTime <build> <platform> sqlite3.h] \ [file join $stagingDirectory DesignTime <build> <platform> sqlite3.lib] \ [file join $stagingDirectory Redist <build> <platform> sqlite3.dll]] if {![info exists no(symbols)]} then { lappend fileNames(destination) \ [file join $stagingDirectory Redist <build> <platform> sqlite3.pdb] } } if {![info exists fileNames(flags)]} then { set fileNames(flags) [list \ [list buildNeutral platformNeutral subst] \ [list buildNeutral platformNeutral subst] \ [list buildNeutral platformNeutral subst move] \ [list buildNeutral platformNeutral] \ [list] [list] [list noRetail]] if {![info exists no(symbols)]} then { lappend fileNames(flags) [list noRetail] } } ############################################################################### # # NOTE: Setup the list of builds supported by this script. These may be # overridden via the user-specific customizations file. # if {![info exists buildNames]} then { set buildNames [list Debug Retail] } ############################################################################### # # NOTE: Setup the list of platforms supported by this script. These may be # overridden via the command line or the user-specific customizations # file. # if {![info exists platformNames]} then { set platformNames [list x86 x64 ARM] } ############################################################################### # # NOTE: Make sure the staging directory exists, creating it if necessary. # file mkdir $stagingDirectory # # NOTE: Build the Tcl command used to extract the template VSIX package to # the staging directory. # set extractCommand [list exec -- $unzip $templateFile -d $stagingDirectory] # # NOTE: Extract the template VSIX package to the staging directory. # eval $extractCommand ############################################################################### # # NOTE: Process each file in the master file list. There are actually three # parallel lists that contain the source file names, the destination file # names, and the file processing flags. If the "buildNeutral" flag is # present, the file location and content do not depend on the build # configuration and "CommonConfiguration" will be used in place of the # build configuration name. If the "platformNeutral" flag is present, # the file location and content do not depend on the build platform and # "neutral" will be used in place of the build platform name. If the # "subst" flag is present, the file is assumed to be a text file that may # contain Tcl variable, command, and backslash replacements, to be # dynamically replaced during processing using the Tcl [subst] command. # If the "noDebug" flag is present, the file will be skipped when # processing for the debug build. If the "noRetail" flag is present, the # file will be skipped when processing for the retail build. If the # "move" flag is present, the source file will be deleted after it is # copied to the destination file. If the source file name is an empty # string, the destination file name will be assumed to already exist in # the staging directory and will not be copied; however, Tcl variable, # command, and backslash replacements may still be performed on the # destination file prior to the final VSIX package being built if the # "subst" flag is present. # foreach sourceFileName $fileNames(source) \ destinationFileName $fileNames(destination) \ fileFlags $fileNames(flags) { # # NOTE: Process the file flags into separate boolean variables that may be # used within the loop. # set isBuildNeutral [expr {[lsearch $fileFlags buildNeutral] != -1}] set isPlatformNeutral [expr {[lsearch $fileFlags platformNeutral] != -1}] set isMove [expr {[lsearch $fileFlags move] != -1}] set useSubst [expr {[lsearch $fileFlags subst] != -1}] # # NOTE: If the current file is build-neutral, then only one build will # be processed for it, namely "CommonConfiguration"; otherwise, each # supported build will be processed for it individually. # foreach buildName \ [expr {$isBuildNeutral ? [list CommonConfiguration] : $buildNames}] { # # NOTE: Should the current file be skipped for this build? # if {[lsearch $fileFlags no${buildName}] != -1} then { continue } # # NOTE: If the current file is platform-neutral, then only one platform # will be processed for it, namely "neutral"; otherwise, each # supported platform will be processed for it individually. # foreach platformName \ [expr {$isPlatformNeutral ? [list neutral] : $platformNames}] { # # NOTE: Use the actual platform name in the destination file name. # set newDestinationFileName [replaceFileNameTokens $destinationFileName \ $shortName $buildName $platformName] # # NOTE: Does the source file need to be copied to the destination file? # if {[string length $sourceFileName] > 0} then { # # NOTE: First, make sure the destination directory exists. # file mkdir [file dirname $newDestinationFileName] # # NOTE: Then, copy the source file to the destination file verbatim. # set newSourceFileName [replaceFileNameTokens $sourceFileName \ $shortName $buildName $platformName] file copy $newSourceFileName $newDestinationFileName # # NOTE: If this is a move instead of a copy, delete the source file # now. # if {$isMove} then { file delete $newSourceFileName } } # # NOTE: Does the destination file contain dynamic replacements that must # be processed now? # if {$useSubst} then { |
︙ | ︙ | |||
442 443 444 445 446 447 448 | # NOTE: Change the current directory to the staging directory so that the # external archive building tool can pickup the necessary files using # relative paths. # cd $stagingDirectory # | | | | 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 | # NOTE: Change the current directory to the staging directory so that the # external archive building tool can pickup the necessary files using # relative paths. # cd $stagingDirectory # # NOTE: Build the Tcl command used to archive the final VSIX package in the # output directory. # set archiveCommand [list exec -- $zip -r $outputFile *] # # NOTE: Build the final VSIX package archive in the output directory. # eval $archiveCommand # # NOTE: Change back to the previously saved current directory. # cd $currentDirectory |
︙ | ︙ |
Changes to tool/win/sqlite.vsix.
cannot compute difference between binary files