Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge latest trunk changes, including sqlite3_db_cacheflush(), with this branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | apple-osx |
Files: | files | file ages | folders |
SHA1: |
6e4306efaf5c0d34a1aead8ad1fe5aa8 |
User & Date: | dan 2015-10-30 16:23:03.670 |
Context
2015-10-30
| ||
16:37 | Merge the 3.10.0 version number update from trunk. (check-in: 980d620743 user: drh tags: apple-osx) | |
16:23 | Merge latest trunk changes, including sqlite3_db_cacheflush(), with this branch. (check-in: 6e4306efaf user: dan tags: apple-osx) | |
16:14 | Add new API function sqlite3_db_cacheflush(). (check-in: ad80d30733 user: dan tags: trunk) | |
2015-10-26
| ||
20:50 | Merge latest trunk changes, including the SQLITE_IOERR_AUTH error code, with this branch. (check-in: bc195e1cd9 user: dan tags: apple-osx) | |
Changes
Changes to Makefile.in.
︙ | ︙ | |||
50 51 52 53 54 55 56 57 58 59 60 61 62 63 | # 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. # LIBREADLINE = @TARGET_READLINE_LIBS@ # Should the database engine be compiled threadsafe # | > | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | # 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@ READLINE_FLAGS += -DHAVE_EDITLINE=@TARGET_HAVE_EDITLINE@ # The library that programs using readline() must link against. # LIBREADLINE = @TARGET_READLINE_LIBS@ # Should the database engine be compiled threadsafe # |
︙ | ︙ |
Changes to autoconf/configure.ac.
︙ | ︙ | |||
14 15 16 17 18 19 20 | # Use automake. AM_INIT_AUTOMAKE([foreign]) AC_SYS_LARGEFILE # Check for required programs. AC_PROG_CC | < > > > > > | | > > > > > > > > > > | 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 | # Use automake. AM_INIT_AUTOMAKE([foreign]) AC_SYS_LARGEFILE # Check for required programs. AC_PROG_CC AC_PROG_LIBTOOL AC_PROG_MKDIR_P # Check for library functions that SQLite can optionally use. AC_CHECK_FUNCS([fdatasync usleep fullfsync localtime_r gmtime_r]) AC_FUNC_STRERROR_R AC_CONFIG_FILES([Makefile sqlite3.pc]) AC_SUBST(BUILD_CFLAGS) #----------------------------------------------------------------------- # --enable-editline # --enable-readline # AC_ARG_ENABLE(editline, [AS_HELP_STRING( [--enable-editline], [use BSD libedit])], [], [enable_editline=yes]) AC_ARG_ENABLE(readline, [AS_HELP_STRING( [--enable-readline], [use readline])], [], [enable_readline=no]) if test x"$enable_editline" != xno ; then sLIBS=$LIBS LIBS="" AC_SEARCH_LIBS([readline],[edit],[enable_readline=no],[enable_editline=no]) READLINE_LIBS=$LIBS if test x"$LIBS" != "x"; then AC_DEFINE([HAVE_EDITLINE],1,Define to use BSD editline) fi LIBS=$sLIBS fi if test x"$enable_readline" != xno ; then sLIBS=$LIBS LIBS="" AC_SEARCH_LIBS(tgetent, curses ncurses ncursesw, [], []) AC_SEARCH_LIBS(readline, readline, [], [enable_readline=no]) AC_CHECK_FUNCS(readline, [], []) READLINE_LIBS=$LIBS |
︙ | ︙ |
Changes to autoconf/tea/win/nmakehlp.c.
︙ | ︙ | |||
599 600 601 602 603 604 605 | /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { | | | | | 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 | /* * Build a list of substutitions from the first filename */ sp = fopen(substitutions, "rt"); if (sp != NULL) { while (fgets(szBuffer, cbBuffer, sp) != NULL) { unsigned char *ks, *ke, *vs, *ve; ks = (unsigned char*)szBuffer; while (ks && *ks && isspace(*ks)) ++ks; ke = ks; while (ke && *ke && !isspace(*ke)) ++ke; vs = ke; while (vs && *vs && isspace(*vs)) ++vs; ve = vs; while (ve && *ve && !(*ve == '\r' || *ve == '\n')) ++ve; *ke = 0, *ve = 0; list_insert(&substPtr, (char*)ks, (char*)vs); } fclose(sp); } /* debug: dump the list */ #ifdef _DEBUG { |
︙ | ︙ |
Changes to configure.
︙ | ︙ | |||
770 771 772 773 774 775 776 777 778 779 780 781 782 783 | ac_subst_vars='LTLIBOBJS LIBOBJS BUILD_CFLAGS USE_GCOV OPT_FEATURE_FLAGS USE_AMALGAMATION TARGET_DEBUG TARGET_HAVE_READLINE TARGET_READLINE_INC TARGET_READLINE_LIBS HAVE_TCL TCL_SHLIB_SUFFIX TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG | > | 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | ac_subst_vars='LTLIBOBJS LIBOBJS BUILD_CFLAGS USE_GCOV OPT_FEATURE_FLAGS USE_AMALGAMATION TARGET_DEBUG TARGET_HAVE_EDITLINE TARGET_HAVE_READLINE TARGET_READLINE_INC TARGET_READLINE_LIBS HAVE_TCL TCL_SHLIB_SUFFIX TCL_STUB_LIB_SPEC TCL_STUB_LIB_FLAG |
︙ | ︙ | |||
891 892 893 894 895 896 897 898 899 900 901 902 903 904 | enable_libtool_lock enable_largefile enable_threadsafe enable_releasemode enable_tempstore enable_tcl with_tcl enable_readline with_readline_lib with_readline_inc enable_debug enable_amalgamation enable_load_extension enable_fts3 | > | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 | enable_libtool_lock enable_largefile enable_threadsafe enable_releasemode enable_tempstore enable_tcl with_tcl enable_editline enable_readline with_readline_lib with_readline_inc enable_debug enable_amalgamation enable_load_extension enable_fts3 |
︙ | ︙ | |||
1538 1539 1540 1541 1542 1543 1544 | --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --disable-threadsafe Disable mutexing --enable-releasemode Support libtool link to release mode --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always) --disable-tcl do not build TCL extension | > | | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 | --disable-libtool-lock avoid locking (might break parallel builds) --disable-largefile omit support for large files --disable-threadsafe Disable mutexing --enable-releasemode Support libtool link to release mode --enable-tempstore Use an in-ram database for temporary tables (never,no,yes,always) --disable-tcl do not build TCL extension --enable-editline enable BSD editline support --disable-readline disable readline support --enable-debug enable debugging & verbose explain --disable-amalgamation Disable the amalgamation and instead build all files separately --disable-load-extension Disable loading of external extensions --enable-fts3 Enable the FTS3 extension --enable-fts4 Enable the FTS4 extension |
︙ | ︙ | |||
3916 3917 3918 3919 3920 3921 3922 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; then : $as_echo_n "(cached) " >&6 else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext | | | | | 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 | { $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 $as_echo_n "checking the name lister ($NM) interface... " >&6; } if ${lt_cv_nm_interface+:} false; 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:3926: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:3929: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:3932: 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:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 |
︙ | ︙ | |||
5128 5129 5130 5131 5132 5133 5134 | ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. | | | 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 | ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5138 "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in |
︙ | ︙ | |||
6653 6654 6655 6656 6657 6658 6659 | # 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:'` | | | | 6656 6657 6658 6659 6660 6661 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 | # 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:6663: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:6667: \$? = $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 |
︙ | ︙ | |||
6992 6993 6994 6995 6996 6997 6998 | # 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:'` | | | | 6995 6996 6997 6998 6999 7000 7001 7002 7003 7004 7005 7006 7007 7008 7009 7010 7011 7012 7013 | # 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:7002: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7006: \$? = $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 |
︙ | ︙ | |||
7097 7098 7099 7100 7101 7102 7103 | # (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:'` | | | | 7100 7101 7102 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 | # (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:7107: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7111: \$? = $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 |
︙ | ︙ | |||
7152 7153 7154 7155 7156 7157 7158 | # (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:'` | | | | 7155 7156 7157 7158 7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 | # (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:7162: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7166: \$? = $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 |
︙ | ︙ | |||
9532 9533 9534 9535 9536 9537 9538 | 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 | | | 9535 9536 9537 9538 9539 9540 9541 9542 9543 9544 9545 9546 9547 9548 9549 | 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 9542 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> |
︙ | ︙ | |||
9628 9629 9630 9631 9632 9633 9634 | 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 | | | 9631 9632 9633 9634 9635 9636 9637 9638 9639 9640 9641 9642 9643 9644 9645 | 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 9638 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> |
︙ | ︙ | |||
10828 10829 10830 10831 10832 10833 10834 10835 10836 10837 10838 10839 10840 10841 10842 10843 10844 10845 10846 10847 10848 10849 | ########## # Figure out what C libraries are required to compile programs # that use "readline()" library. # TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : enableval=$enable_readline; with_readline=$enableval else with_readline=auto fi if test x"$with_readline" != xno; then found="yes" # Check whether --with-readline-lib was given. if test "${with_readline_lib+set}" = set; then : withval=$with_readline_lib; with_readline_lib=$withval | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 10831 10832 10833 10834 10835 10836 10837 10838 10839 10840 10841 10842 10843 10844 10845 10846 10847 10848 10849 10850 10851 10852 10853 10854 10855 10856 10857 10858 10859 10860 10861 10862 10863 10864 10865 10866 10867 10868 10869 10870 10871 10872 10873 10874 10875 10876 10877 10878 10879 10880 10881 10882 10883 10884 10885 10886 10887 10888 10889 10890 10891 10892 10893 10894 10895 10896 10897 10898 10899 10900 10901 10902 10903 10904 10905 10906 10907 10908 10909 10910 10911 10912 10913 10914 10915 10916 10917 10918 10919 10920 10921 10922 10923 10924 10925 | ########## # Figure out what C libraries are required to compile programs # that use "readline()" library. # TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 TARGET_HAVE_EDITLINE=0 # Check whether --enable-editline was given. if test "${enable_editline+set}" = set; then : enableval=$enable_editline; with_editline=$enableval else with_editline=auto fi # Check whether --enable-readline was given. if test "${enable_readline+set}" = set; then : enableval=$enable_readline; with_readline=$enableval else with_readline=auto fi if test x"$with_editline" != xno; then sLIBS=$LIBS LIBS="" TARGET_HAVE_EDITLINE=1 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing readline" >&5 $as_echo_n "checking for library containing readline... " >&6; } if ${ac_cv_search_readline+:} false; then : $as_echo_n "(cached) " >&6 else ac_func_search_save_LIBS=$LIBS cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ /* Override any GCC internal prototype to avoid an error. Use char because int might match the return type of a GCC builtin and then its argument prototype would still apply. */ #ifdef __cplusplus extern "C" #endif char readline (); int main () { return readline (); ; return 0; } _ACEOF for ac_lib in '' edit; do if test -z "$ac_lib"; then ac_res="none required" else ac_res=-l$ac_lib LIBS="-l$ac_lib $ac_func_search_save_LIBS" fi if ac_fn_c_try_link "$LINENO"; then : ac_cv_search_readline=$ac_res fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext if ${ac_cv_search_readline+:} false; then : break fi done if ${ac_cv_search_readline+:} false; then : else ac_cv_search_readline=no fi rm conftest.$ac_ext LIBS=$ac_func_search_save_LIBS fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_readline" >&5 $as_echo "$ac_cv_search_readline" >&6; } ac_res=$ac_cv_search_readline if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" with_readline=no else TARGET_HAVE_EDITLINE=0 fi TARGET_READLINE_LIBS=$LIBS LIBS=$sLIBS fi if test x"$with_readline" != xno; then found="yes" # Check whether --with-readline-lib was given. if test "${with_readline_lib+set}" = set; then : withval=$with_readline_lib; with_readline_lib=$withval |
︙ | ︙ | |||
11019 11020 11021 11022 11023 11024 11025 11026 11027 11028 11029 11030 11031 11032 | TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 else TARGET_HAVE_READLINE=1 fi fi ########## # Figure out what C libraries are required to compile programs | > | 11095 11096 11097 11098 11099 11100 11101 11102 11103 11104 11105 11106 11107 11108 11109 | TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 else TARGET_HAVE_READLINE=1 fi fi ########## # Figure out what C libraries are required to compile programs |
︙ | ︙ |
Changes to configure.ac.
︙ | ︙ | |||
456 457 458 459 460 461 462 463 | ########## # Figure out what C libraries are required to compile programs # that use "readline()" library. # TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 AC_ARG_ENABLE([readline], | > > > > > | > > > > > > > > | 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 | ########## # Figure out what C libraries are required to compile programs # that use "readline()" library. # TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 TARGET_HAVE_EDITLINE=0 AC_ARG_ENABLE([editline], [AC_HELP_STRING([--enable-editline],[enable BSD editline support])], [with_editline=$enableval], [with_editline=auto]) AC_ARG_ENABLE([readline], [AC_HELP_STRING([--disable-readline],[disable readline support])], [with_readline=$enableval], [with_readline=auto]) if test x"$with_editline" != xno; then sLIBS=$LIBS LIBS="" TARGET_HAVE_EDITLINE=1 AC_SEARCH_LIBS(readline,edit,[with_readline=no],[TARGET_HAVE_EDITLINE=0]) TARGET_READLINE_LIBS=$LIBS LIBS=$sLIBS fi if test x"$with_readline" != xno; then found="yes" AC_ARG_WITH([readline-lib], [AC_HELP_STRING([--with-readline-lib],[specify readline library])], [with_readline_lib=$withval], [with_readline_lib="auto"]) |
︙ | ︙ | |||
515 516 517 518 519 520 521 522 523 524 525 526 527 528 | TARGET_HAVE_READLINE=1 fi fi AC_SUBST(TARGET_READLINE_LIBS) AC_SUBST(TARGET_READLINE_INC) AC_SUBST(TARGET_HAVE_READLINE) ########## # Figure out what C libraries are required to compile programs # that use "fdatasync()" function. # AC_SEARCH_LIBS(fdatasync, [rt]) | > | 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 | TARGET_HAVE_READLINE=1 fi fi AC_SUBST(TARGET_READLINE_LIBS) AC_SUBST(TARGET_READLINE_INC) AC_SUBST(TARGET_HAVE_READLINE) AC_SUBST(TARGET_HAVE_EDITLINE) ########## # Figure out what C libraries are required to compile programs # that use "fdatasync()" function. # AC_SEARCH_LIBS(fdatasync, [rt]) |
︙ | ︙ |
Changes to ext/fts1/fts1.c.
︙ | ︙ | |||
201 202 203 204 205 206 207 | */ /* TODO(shess) The snippet-generation code should be using the ** tokenizer-generated tokens rather than doing its own local ** tokenization. */ /* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ static int safe_isspace(char c){ | | | | | 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | */ /* TODO(shess) The snippet-generation code should be using the ** tokenizer-generated tokens rather than doing its own local ** tokenization. */ /* TODO(shess) Is __isascii() a portable version of (c&0x80)==0? */ static int safe_isspace(char c){ return (c&0x80)==0 ? isspace((unsigned char)c) : 0; } static int safe_tolower(char c){ return (c&0x80)==0 ? tolower((unsigned char)c) : c; } static int safe_isalnum(char c){ return (c&0x80)==0 ? isalnum((unsigned char)c) : 0; } typedef enum DocListType { DL_DOCIDS, /* docids only */ DL_POSITIONS, /* docids + positions */ DL_POSITIONS_OFFSETS /* docids + positions + offsets */ } DocListType; |
︙ | ︙ |
Changes to ext/fts1/simple_tokenizer.c.
︙ | ︙ | |||
134 135 136 137 138 139 140 | c->zToken = realloc(c->zToken, n+1); } for(ii=0; ii<n; ii++){ /* TODO(shess) This needs expansion to handle UTF-8 ** case-insensitivity. */ char ch = c->pCurrent[ii]; | | | 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | c->zToken = realloc(c->zToken, n+1); } for(ii=0; ii<n; ii++){ /* TODO(shess) This needs expansion to handle UTF-8 ** case-insensitivity. */ char ch = c->pCurrent[ii]; c->zToken[ii] = (unsigned char)ch<0x80 ? tolower((unsigned char)ch):ch; } c->zToken[n] = '\0'; *ppToken = c->zToken; *pnBytes = n; *piStartOffset = (int) (c->pCurrent-c->pInput); *piEndOffset = *piStartOffset+n; *piPosition = c->iToken++; |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 | int iOff = pIter->iLeafOffset; /* Offset to read at */ int nSz; ASSERT_SZLEAF_OK(pIter->pLeaf); fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; pIter->iLeafOffset = iOff; } } static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ int iOff = pIter->iLeafOffset; | > | 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 | int iOff = pIter->iLeafOffset; /* Offset to read at */ int nSz; ASSERT_SZLEAF_OK(pIter->pLeaf); fts5FastGetVarint32(pIter->pLeaf->p, iOff, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; pIter->iLeafOffset = iOff; assert_nc( pIter->nPos>=0 ); } } static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ int iOff = pIter->iLeafOffset; |
︙ | ︙ | |||
1668 1669 1670 1671 1672 1673 1674 | pIter->iLeafPgno--; pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID( pIter->pSeg->iSegid, pIter->iLeafPgno )); if( pNew ){ /* iTermLeafOffset may be equal to szLeaf if the term is the last ** thing on the page - i.e. the first rowid is on the following page. | | | > | < | | > | 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 | pIter->iLeafPgno--; pNew = fts5DataRead(p, FTS5_SEGMENT_ROWID( pIter->pSeg->iSegid, pIter->iLeafPgno )); if( pNew ){ /* iTermLeafOffset may be equal to szLeaf if the term is the last ** thing on the page - i.e. the first rowid is on the following page. ** In this case leave pIter->pLeaf==0, this iterator is at EOF. */ if( pIter->iLeafPgno==pIter->iTermLeafPgno ){ assert( pIter->pLeaf==0 ); if( pIter->iTermLeafOffset<pNew->szLeaf ){ pIter->pLeaf = pNew; pIter->iLeafOffset = pIter->iTermLeafOffset; } }else{ int iRowidOff; iRowidOff = fts5LeafFirstRowidOff(pNew); if( iRowidOff ){ pIter->pLeaf = pNew; pIter->iLeafOffset = iRowidOff; } |
︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 | ** this block is particularly performance critical, so equivalent ** code is inlined. */ int nSz; assert( p->rc==SQLITE_OK ); fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; } } } } } #define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; } | > | 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 | ** this block is particularly performance critical, so equivalent ** code is inlined. */ int nSz; assert( p->rc==SQLITE_OK ); fts5FastGetVarint32(pIter->pLeaf->p, pIter->iLeafOffset, nSz); pIter->bDel = (nSz & 0x0001); pIter->nPos = nSz>>1; assert_nc( pIter->nPos>=0 ); } } } } } #define SWAPVAL(T, a, b) { T tmp; tmp=a; a=b; b=tmp; } |
︙ | ︙ | |||
2055 2056 2057 2058 2059 2060 2061 | return; }else if( bEndOfPage ){ do { fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ) return; a = pIter->pLeaf->p; if( fts5LeafIsTermless(pIter->pLeaf)==0 ){ | > | > > | 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 | return; }else if( bEndOfPage ){ do { fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ) return; a = pIter->pLeaf->p; if( fts5LeafIsTermless(pIter->pLeaf)==0 ){ iPgidx = pIter->pLeaf->szLeaf; iPgidx += fts5GetVarint32(&pIter->pLeaf->p[iPgidx], iOff); if( iOff<4 || iOff>=pIter->pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; }else{ nKeep = 0; iTermOff = iOff; n = pIter->pLeaf->nn; iOff += fts5GetVarint32(&a[iOff], nNew); break; } } }while( 1 ); } |
︙ | ︙ | |||
4371 4372 4373 4374 4375 4376 4377 | if( aBuf && pStruct ){ const int flags = FTS5INDEX_QUERY_SCAN; int i; i64 iLastRowid = 0; Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ Fts5Data *pData; Fts5Buffer doclist; | | | 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 | if( aBuf && pStruct ){ const int flags = FTS5INDEX_QUERY_SCAN; int i; i64 iLastRowid = 0; Fts5IndexIter *p1 = 0; /* Iterator used to gather data from index */ Fts5Data *pData; Fts5Buffer doclist; int bNewTerm = 1; memset(&doclist, 0, sizeof(doclist)); for(fts5MultiIterNew(p, pStruct, 1, flags, pToken, nToken, -1, 0, &p1); fts5MultiIterEof(p, p1)==0; fts5MultiIterNext2(p, p1, &bNewTerm) ){ i64 iRowid = fts5MultiIterRowid(p1); |
︙ | ︙ | |||
5578 5579 5580 5581 5582 5583 5584 | if( n>0 ){ iOff = sqlite3Fts5GetVarint(a, (u64*)&iDocid); sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid); } while( iOff<n ){ int nPos; | | | > | 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 | if( n>0 ){ iOff = sqlite3Fts5GetVarint(a, (u64*)&iDocid); sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid); } while( iOff<n ){ int nPos; int bDel; iOff += fts5GetPoslistSize(&a[iOff], &nPos, &bDel); sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " nPos=%d%s", nPos, bDel?"*":""); iOff += fts5DecodePoslist(pRc, pBuf, &a[iOff], MIN(n-iOff, nPos)); if( iOff<n ){ i64 iDelta; iOff += sqlite3Fts5GetVarint(&a[iOff], (u64*)&iDelta); iDocid += iDelta; sqlite3Fts5BufferAppendPrintf(pRc, pBuf, " id=%lld", iDocid); } |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
1447 1448 1449 1450 1451 1452 1453 | ** 1) DELETE ** 2) UPDATE (rowid not modified) ** 3) UPDATE (rowid modified) ** 4) INSERT ** ** Cases 3 and 4 may violate the rowid constraint. */ | > > | > | 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 | ** 1) DELETE ** 2) UPDATE (rowid not modified) ** 3) UPDATE (rowid modified) ** 4) INSERT ** ** Cases 3 and 4 may violate the rowid constraint. */ int eConflict = SQLITE_ABORT; if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ eConflict = sqlite3_vtab_on_conflict(pConfig->db); } assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL ); assert( nArg!=1 || eType0==SQLITE_INTEGER ); /* Filter out attempts to run UPDATE or DELETE on contentless tables. ** This is not suported. */ if( eType0==SQLITE_INTEGER && fts5IsContentless(pTab) ){ |
︙ | ︙ |
Changes to ext/fts5/fts5_storage.c.
︙ | ︙ | |||
509 510 511 512 513 514 515 | sqlite3_bind_int64(pDel, 1, iDel); sqlite3_step(pDel); rc = sqlite3_reset(pDel); } } /* Delete the %_content record */ | > | | | | | | | > | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | sqlite3_bind_int64(pDel, 1, iDel); sqlite3_step(pDel); rc = sqlite3_reset(pDel); } } /* Delete the %_content record */ if( pConfig->eContent==FTS5_CONTENT_NORMAL ){ if( rc==SQLITE_OK ){ rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0); } if( rc==SQLITE_OK ){ sqlite3_bind_int64(pDel, 1, iDel); sqlite3_step(pDel); rc = sqlite3_reset(pDel); } } /* Write the averages record */ if( rc==SQLITE_OK ){ rc = fts5StorageSaveTotals(p); } |
︙ | ︙ |
Changes to ext/fts5/test/fts5aa.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # This file implements regression tests for SQLite library. The # focus of this script is testing the FTS5 module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5aa | | | 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 the FTS5 module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5aa # If SQLITE_ENABLE_FTS5 is not defined, omit this file. ifcapable !fts5 { finish_test return } do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts5(a, b, c); |
︙ | ︙ |
Added ext/fts5/test/fts5conflict.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 | # 2015 October 27 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing the FTS5 module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5conflict # If SQLITE_ENABLE_FTS5 is not defined, omit this file. ifcapable !fts5 { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(x INTEGER PRIMARY KEY, a, b); CREATE VIRTUAL TABLE ft USING fts5(a, b, content=t1, content_rowid=x); } do_execsql_test 1.1 { REPLACE INTO ft(rowid, a, b) VALUES(1, 'a b c', 'a b c'); REPLACE INTO t1 VALUES(1, 'a b c', 'a b c'); } do_execsql_test 1.2 { INSERT INTO ft(ft) VALUES('integrity-check'); } do_execsql_test 2.0 { CREATE TABLE tbl(a INTEGER PRIMARY KEY, b, c); CREATE VIRTUAL TABLE fts_idx USING fts5(b, c, content=tbl, content_rowid=a); CREATE TRIGGER tbl_ai AFTER INSERT ON tbl BEGIN INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c); END; CREATE TRIGGER tbl_ad AFTER DELETE ON tbl BEGIN INSERT INTO fts_idx(fts_idx, rowid, b, c) VALUES('delete', old.a, old.b, old.c); END; CREATE TRIGGER tbl_au AFTER UPDATE ON tbl BEGIN INSERT INTO fts_idx(fts_idx, rowid, b, c) VALUES('delete', old.a, old.b, old.c); INSERT INTO fts_idx(rowid, b, c) VALUES (new.a, new.b, new.c); END; } do_execsql_test 2.1 { PRAGMA recursive_triggers = 1; INSERT INTO tbl VALUES(1, 'x y z', '1 2 3'); INSERT INTO tbl VALUES(10, 'x y z', '1 2 3'); INSERT INTO tbl VALUES(100, 'x 1 z', '1 y 3'); UPDATE tbl SET b = '1 2 x' WHERE rowid=10; REPLACE INTO tbl VALUES(1, '4 5 6', '3 2 1'); DELETE FROM tbl WHERE a=100; INSERT INTO fts_idx(fts_idx) VALUES('integrity-check'); } finish_test |
Changes to ext/fts5/test/fts5integrity.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2015 Jan 13 # # 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. # #*********************************************************************** # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # 2015 Jan 13 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains tests focused on the integrity-check procedure. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5integrity # If SQLITE_ENABLE_FTS5 is defined, omit this file. ifcapable !fts5 { |
︙ | ︙ | |||
98 99 100 101 102 103 104 105 106 107 | INSERT INTO aa_content VALUES(23, ''); INSERT INTO aa(aa) VALUES('integrity-check'); } {1 {database disk image is malformed}} #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r} #exit finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | INSERT INTO aa_content VALUES(23, ''); INSERT INTO aa(aa) VALUES('integrity-check'); } {1 {database disk image is malformed}} #db eval {SELECT rowid, fts5_decode(rowid, block) aS r FROM zz_data} {puts $r} #exit execsql { ROLLBACK } #------------------------------------------------------------------------- # Test that integrity-check works on a reasonably large db with many # different terms. # Document generator command. proc rnddoc {n} { set doc [list] for {set i 0} {$i<$n} {incr i} { lappend doc [format %.5d [expr int(rand()*10000)]] } return $doc } db func rnddoc rnddoc expr srand(0) do_execsql_test 5.0 { CREATE VIRTUAL TABLE gg USING fts5(a, prefix="1,2,3"); INSERT INTO gg(gg, rank) VALUES('pgsz', 256); INSERT INTO gg VALUES(rnddoc(20)); INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; INSERT INTO gg SELECT rnddoc(20) FROM gg; } do_execsql_test 5.1 { INSERT INTO gg(gg) VALUES('integrity-check'); } do_execsql_test 5.2 { INSERT INTO gg(gg) VALUES('optimize'); } breakpoint do_execsql_test 5.3 { INSERT INTO gg(gg) VALUES('integrity-check'); } finish_test |
Added ext/fts5/test/fts5query.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 | # 2015 October 27 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #************************************************************************* # This file implements regression tests for SQLite library. The # focus of this script is testing the FTS5 module. # source [file join [file dirname [info script]] fts5_common.tcl] set testprefix fts5query # If SQLITE_ENABLE_FTS5 is defined, omit this file. ifcapable !fts5 { finish_test return } for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} { reset_db do_test 1.$tn.1 { execsql { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); BEGIN; } foreach x [list aaa bbb ccc ddd eee fff ggg hhh iii jjj] { set doc [string repeat "$x " 30] execsql { INSERT INTO t1 VALUES($doc) } } execsql COMMIT } {} do_execsql_test 1.$tn.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } set ret 1 foreach x [list a b c d e f g h i j] { do_execsql_test 1.$tn.3.$ret { SELECT rowid FROM t1 WHERE t1 MATCH $x || '*'; } $ret incr ret } } for {set tn 1 ; set pgsz 64} {$tn<32} {incr tn; incr pgsz 16} { reset_db do_test 2.$tn.1 { execsql { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', $pgsz); BEGIN; } foreach x [list bbb ddd fff hhh jjj lll nnn ppp rrr ttt] { set doc [string repeat "$x " 30] execsql { INSERT INTO t1 VALUES($doc) } } execsql COMMIT } {} do_execsql_test 1.$tn.2 { INSERT INTO t1(t1) VALUES('integrity-check'); } set ret 1 foreach x [list a c e g i k m o q s u] { do_execsql_test 2.$tn.3.$ret { SELECT rowid FROM t1 WHERE t1 MATCH $x || '*'; } {} incr ret } } finish_test |
Changes to ext/fts5/tool/showfts5.tcl.
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 | #------------------------------------------------------------------------- # Process command line arguments. # proc usage {} { puts stderr "usage: $::argv0 ?OPTIONS? database table" puts stderr "" puts stderr " -nterm (count number of terms in each segment)" puts stderr "" exit 1 } set O(nterm) 0 if {[llength $argv]<2} usage foreach a [lrange $argv 0 end-2] { switch -- $a { -nterm { set O(nterm) 1 } default { usage } } } | > > > > > > | 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 | #------------------------------------------------------------------------- # Process command line arguments. # proc usage {} { puts stderr "usage: $::argv0 ?OPTIONS? database table" puts stderr "" puts stderr " -nterm (count number of terms in each segment)" puts stderr " -segments (output segment contents)" puts stderr "" exit 1 } set O(nterm) 0 set O(segments) 0 if {[llength $argv]<2} usage foreach a [lrange $argv 0 end-2] { switch -- $a { -nterm { set O(nterm) 1 } -segments { set O(segments) 1 } default { usage } } } |
︙ | ︙ | |||
73 74 75 76 77 78 79 80 81 82 83 84 | puts [format " % -28s nTerm=%d" $seg $nTerm] } else { puts [format " % -28s" $seg] } } } } | > > > > > > > | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 | puts [format " % -28s nTerm=%d" $seg $nTerm] } else { puts [format " % -28s" $seg] } } } } if {$O(segments)} { puts "" db eval "SELECT fts5_decode(rowid, block) AS d FROM ${tbl}_data WHERE id>10" { puts $d } } |
Changes to ext/misc/amatch.c.
︙ | ︙ | |||
812 813 814 815 816 817 818 | */ static const char *amatchValueOfKey(const char *zKey, const char *zStr){ int nKey = (int)strlen(zKey); int nStr = (int)strlen(zStr); int i; if( nStr<nKey+1 ) return 0; if( memcmp(zStr, zKey, nKey)!=0 ) return 0; | | | | 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | */ static const char *amatchValueOfKey(const char *zKey, const char *zStr){ int nKey = (int)strlen(zKey); int nStr = (int)strlen(zStr); int i; if( nStr<nKey+1 ) return 0; if( memcmp(zStr, zKey, nKey)!=0 ) return 0; for(i=nKey; isspace((unsigned char)zStr[i]); i++){} if( zStr[i]!='=' ) return 0; i++; while( isspace((unsigned char)zStr[i]) ){ i++; } return zStr+i; } /* ** xConnect/xCreate method for the amatch module. Arguments are: ** ** argv[0] -> module name ("approximate_match") |
︙ | ︙ |
Changes to ext/misc/closure.c.
︙ | ︙ | |||
482 483 484 485 486 487 488 | */ static const char *closureValueOfKey(const char *zKey, const char *zStr){ int nKey = (int)strlen(zKey); int nStr = (int)strlen(zStr); int i; if( nStr<nKey+1 ) return 0; if( memcmp(zStr, zKey, nKey)!=0 ) return 0; | | | | 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 | */ static const char *closureValueOfKey(const char *zKey, const char *zStr){ int nKey = (int)strlen(zKey); int nStr = (int)strlen(zStr); int i; if( nStr<nKey+1 ) return 0; if( memcmp(zStr, zKey, nKey)!=0 ) return 0; for(i=nKey; isspace((unsigned char)zStr[i]); i++){} if( zStr[i]!='=' ) return 0; i++; while( isspace((unsigned char)zStr[i]) ){ i++; } return zStr+i; } /* ** xConnect/xCreate method for the closure module. Arguments are: ** ** argv[0] -> module name ("transitive_closure") |
︙ | ︙ |
Changes to ext/misc/spellfix.c.
︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 | ** Make a copy of a string. Remove leading and trailing whitespace ** and dequote it. */ static char *spellfix1Dequote(const char *zIn){ char *zOut; int i, j; char c; | | | 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 | ** Make a copy of a string. Remove leading and trailing whitespace ** and dequote it. */ static char *spellfix1Dequote(const char *zIn){ char *zOut; int i, j; char c; while( isspace((unsigned char)zIn[0]) ) zIn++; zOut = sqlite3_mprintf("%s", zIn); if( zOut==0 ) return 0; i = (int)strlen(zOut); #if 0 /* The parser will never leave spaces at the end */ while( i>0 && isspace(zOut[i-1]) ){ i--; } #endif zOut[i] = 0; |
︙ | ︙ |
Changes to mptest/mptest.c.
︙ | ︙ | |||
41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #else # include <unistd.h> #endif #include <stdlib.h> #include <string.h> #include <assert.h> #include <ctype.h> /* The suffix to append to the child command lines, if any */ #if defined(_WIN32) # define GETPID (int)GetCurrentProcessId #else # define GETPID getpid #endif | > > > | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | #else # include <unistd.h> #endif #include <stdlib.h> #include <string.h> #include <assert.h> #include <ctype.h> #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) /* The suffix to append to the child command lines, if any */ #if defined(_WIN32) # define GETPID (int)GetCurrentProcessId #else # define GETPID getpid #endif |
︙ | ︙ | |||
183 184 185 186 187 188 189 | } prior_c = c2; } c2 = *(zGlob++); } if( c2==0 || (seen ^ invert)==0 ) return 0; }else if( c=='#' ){ | | | | | 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | } prior_c = c2; } c2 = *(zGlob++); } if( c2==0 || (seen ^ invert)==0 ) return 0; }else if( c=='#' ){ if( (z[0]=='-' || z[0]=='+') && ISDIGIT(z[1]) ) z++; if( !ISDIGIT(z[0]) ) return 0; z++; while( ISDIGIT(z[0]) ){ z++; } }else{ if( c!=(*(z++)) ) return 0; } } return *z==0; } |
︙ | ︙ | |||
285 286 287 288 289 290 291 | } /* ** Return the length of a string omitting trailing whitespace */ static int clipLength(const char *z){ int n = (int)strlen(z); | | | 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | } /* ** Return the length of a string omitting trailing whitespace */ static int clipLength(const char *z){ int n = (int)strlen(z); while( n>0 && ISSPACE(z[n-1]) ){ n--; } return n; } /* ** Auxiliary SQL function to return the name of the VFS */ static void vfsNameFunc( |
︙ | ︙ | |||
440 441 442 443 444 445 446 | static void stringAppendTerm(String *p, const char *z){ int i; if( p->n ) stringAppend(p, " ", 1); if( z==0 ){ stringAppend(p, "nil", 3); return; } | | | 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 | static void stringAppendTerm(String *p, const char *z){ int i; if( p->n ) stringAppend(p, " ", 1); if( z==0 ){ stringAppend(p, "nil", 3); return; } for(i=0; z[i] && !ISSPACE(z[i]); i++){} if( i>0 && z[i]==0 ){ stringAppend(p, z, i); return; } stringAppend(p, "'", 1); while( z[0] ){ for(i=0; z[i] && z[i]!='\''; i++){} |
︙ | ︙ | |||
695 696 697 698 699 700 701 | } /* ** Return the length of the next token. */ static int tokenLength(const char *z, int *pnLine){ int n = 0; | | | | 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 | } /* ** Return the length of the next token. */ static int tokenLength(const char *z, int *pnLine){ int n = 0; if( ISSPACE(z[0]) || (z[0]=='/' && z[1]=='*') ){ int inC = 0; int c; if( z[0]=='/' ){ inC = 1; n = 2; } while( (c = z[n++])!=0 ){ if( c=='\n' ) (*pnLine)++; if( ISSPACE(c) ) continue; if( inC && c=='*' && z[n]=='/' ){ n++; inC = 0; }else if( !inC && c=='/' && z[n]=='*' ){ n++; inC = 1; }else if( !inC ){ |
︙ | ︙ | |||
730 731 732 733 734 735 736 | if( z[n]==delim ){ n++; if( z[n+1]!=delim ) break; } } }else{ int c; | | | | | | | | 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 | if( z[n]==delim ){ n++; if( z[n+1]!=delim ) break; } } }else{ int c; for(n=1; (c = z[n])!=0 && !ISSPACE(c) && c!='"' && c!='\'' && c!=';'; n++){} } return n; } /* ** Copy a single token into a string buffer. */ static int extractToken(const char *zIn, int nIn, char *zOut, int nOut){ int i; if( nIn<=0 ){ zOut[0] = 0; return 0; } for(i=0; i<nIn && i<nOut-1 && !ISSPACE(zIn[i]); i++){ zOut[i] = zIn[i]; } zOut[i] = 0; return i; } /* ** Find the number of characters up to the start of the next "--end" token. */ static int findEnd(const char *z, int *pnLine){ int n = 0; while( z[n] && (strncmp(z+n,"--end",5) || !ISSPACE(z[n+5])) ){ n += tokenLength(z+n, pnLine); } return n; } /* ** Find the number of characters up to the first character past the ** of the next "--endif" or "--else" token. Nested --if commands are ** also skipped. */ static int findEndif(const char *z, int stopAtElse, int *pnLine){ int n = 0; while( z[n] ){ int len = tokenLength(z+n, pnLine); if( (strncmp(z+n,"--endif",7)==0 && ISSPACE(z[n+7])) || (stopAtElse && strncmp(z+n,"--else",6)==0 && ISSPACE(z[n+6])) ){ return n+len; } if( strncmp(z+n,"--if",4)==0 && ISSPACE(z[n+4]) ){ int skip = findEndif(z+n+len, 0, pnLine); n += skip + len; }else{ n += len; } } return n; |
︙ | ︙ | |||
884 885 886 887 888 889 890 | char azArg[MX_ARG][100]; memset(&sResult, 0, sizeof(sResult)); stringReset(&sResult); while( (c = zScript[ii])!=0 ){ prevLine = lineno; len = tokenLength(zScript+ii, &lineno); | | | | 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 | char azArg[MX_ARG][100]; memset(&sResult, 0, sizeof(sResult)); stringReset(&sResult); while( (c = zScript[ii])!=0 ){ prevLine = lineno; len = tokenLength(zScript+ii, &lineno); if( ISSPACE(c) || (c=='/' && zScript[ii+1]=='*') ){ ii += len; continue; } if( c!='-' || zScript[ii+1]!='-' || !isalpha(zScript[ii+2]) ){ ii += len; continue; } /* Run any prior SQL before processing the new --command */ if( ii>iBegin ){ char *zSql = sqlite3_mprintf("%.*s", ii-iBegin, zScript+iBegin); evalSql(&sResult, zSql); sqlite3_free(zSql); iBegin = ii + len; } /* Parse the --command */ if( g.iTrace>=2 ) logMessage("%.*s", len, zScript+ii); n = extractToken(zScript+ii+2, len-2, zCmd, sizeof(zCmd)); for(nArg=0; n<len-2 && nArg<MX_ARG; nArg++){ while( n<len-2 && ISSPACE(zScript[ii+2+n]) ){ n++; } if( n>=len-2 ) break; n += extractToken(zScript+ii+2+n, len-2-n, azArg[nArg], sizeof(azArg[nArg])); } for(j=nArg; j<MX_ARG; j++) azArg[j++][0] = 0; /* |
︙ | ︙ | |||
972 973 974 975 976 977 978 | ** --match ANSWER... ** ** Check to see if output matches ANSWER. Report an error if not. */ if( strcmp(zCmd, "match")==0 ){ int jj; char *zAns = zScript+ii; | | | 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 | ** --match ANSWER... ** ** Check to see if output matches ANSWER. Report an error if not. */ if( strcmp(zCmd, "match")==0 ){ int jj; char *zAns = zScript+ii; for(jj=7; jj<len-1 && ISSPACE(zAns[jj]); jj++){} zAns += jj; if( len-jj-1!=sResult.n || strncmp(sResult.z, zAns, len-jj-1) ){ errorMessage("line %d of %s:\nExpected [%.*s]\n Got [%s]", prevLine, zFilename, len-jj-1, zAns, sResult.z); } g.nTest++; stringReset(&sResult); |
︙ | ︙ | |||
994 995 996 997 998 999 1000 | ** ANSWER. */ if( strcmp(zCmd, "glob")==0 || strcmp(zCmd, "notglob")==0 ){ int jj; char *zAns = zScript+ii; char *zCopy; int isGlob = (zCmd[0]=='g'); | | | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 | ** ANSWER. */ if( strcmp(zCmd, "glob")==0 || strcmp(zCmd, "notglob")==0 ){ int jj; char *zAns = zScript+ii; char *zCopy; int isGlob = (zCmd[0]=='g'); for(jj=9-3*isGlob; jj<len-1 && ISSPACE(zAns[jj]); jj++){} zAns += jj; zCopy = sqlite3_mprintf("%.*s", len-jj-1, zAns); if( (sqlite3_strglob(zCopy, sResult.z)==0)^isGlob ){ errorMessage("line %d of %s:\nExpected [%s]\n Got [%s]", prevLine, zFilename, zCopy, sResult.z); } sqlite3_free(zCopy); |
︙ | ︙ | |||
1046 1047 1048 1049 1050 1051 1052 | /* ** --print MESSAGE.... ** ** Output the remainder of the line to the log file */ if( strcmp(zCmd, "print")==0 ){ int jj; | | | | 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 | /* ** --print MESSAGE.... ** ** Output the remainder of the line to the log file */ if( strcmp(zCmd, "print")==0 ){ int jj; for(jj=7; jj<len && ISSPACE(zScript[ii+jj]); jj++){} logMessage("%.*s", len-jj, zScript+ii+jj); }else /* ** --if EXPR ** ** Skip forward to the next matching --endif or --else if EXPR is false. */ if( strcmp(zCmd, "if")==0 ){ int jj, rc; sqlite3_stmt *pStmt; for(jj=4; jj<len && ISSPACE(zScript[ii+jj]); jj++){} pStmt = prepareSql("SELECT %.*s", len-jj, zScript+ii+jj); rc = sqlite3_step(pStmt); if( rc!=SQLITE_ROW || sqlite3_column_int(pStmt, 0)==0 ){ ii += findEndif(zScript+ii+len, 1, &lineno); } sqlite3_finalize(pStmt); }else |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
859 860 861 862 863 864 865 866 867 868 869 870 871 872 | *pDifferentRow = 1; }else{ assert( pCur->skipNext==0 ); *pDifferentRow = 0; } return SQLITE_OK; } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. ** | > > > > > > > > > > > > > > > > > > > > | 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 | *pDifferentRow = 1; }else{ assert( pCur->skipNext==0 ); *pDifferentRow = 0; } return SQLITE_OK; } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* ** Provide hints to the cursor. The particular hint given (and the type ** and number of the varargs parameters) is determined by the eHintType ** parameter. See the definitions of the BTREE_HINT_* macros for details. */ void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){ /* Used only by system that substitute their own storage engine */ } #endif /* ** Provide flag hints to the cursor. */ void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){ assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 ); pCur->hints = x; } #ifndef SQLITE_OMIT_AUTOVACUUM /* ** Given a page number of a regular database page, return the page ** number for the pointer-map page that contains the entry for the ** input page number. ** |
︙ | ︙ | |||
9649 9650 9651 9652 9653 9654 9655 | } } pBt->btsFlags &= ~BTS_NO_WAL; return rc; } | < < < < < < < < | 9669 9670 9671 9672 9673 9674 9675 9676 9677 9678 9679 9680 9681 9682 | } } pBt->btsFlags &= ~BTS_NO_WAL; return rc; } #ifdef SQLITE_DEBUG /* ** Return true if the cursor has a hint specified. This routine is ** only used from within assert() statements */ int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){ return (pCsr->hints & mask)!=0; |
︙ | ︙ |
Changes to src/btree.h.
︙ | ︙ | |||
146 147 148 149 150 151 152 | #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 #define BTREE_APPLICATION_ID 8 #define BTREE_DATA_VERSION 15 /* A virtual meta-value */ /* | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | 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 | #define BTREE_TEXT_ENCODING 5 #define BTREE_USER_VERSION 6 #define BTREE_INCR_VACUUM 7 #define BTREE_APPLICATION_ID 8 #define BTREE_DATA_VERSION 15 /* A virtual meta-value */ /* ** Kinds of hints that can be passed into the sqlite3BtreeCursorHint() ** interface. ** ** BTREE_HINT_RANGE (arguments: Expr*, Mem*) ** ** The first argument is an Expr* (which is guaranteed to be constant for ** the lifetime of the cursor) that defines constraints on which rows ** might be fetched with this cursor. The Expr* tree may contain ** TK_REGISTER nodes that refer to values stored in the array of registers ** passed as the second parameter. In other words, if Expr.op==TK_REGISTER ** then the value of the node is the value in Mem[pExpr.iTable]. Any ** TK_COLUMN node in the expression tree refers to the Expr.iColumn-th ** column of the b-tree of the cursor. The Expr tree will not contain ** any function calls nor subqueries nor references to b-trees other than ** the cursor being hinted. ** ** The design of the _RANGE hint is aid b-tree implementations that try ** to prefetch content from remote machines - to provide those ** implementations with limits on what needs to be prefetched and thereby ** reduce network bandwidth. ** ** Note that BTREE_HINT_FLAGS with BTREE_BULKLOAD is the only hint used by ** standard SQLite. The other hints are provided for extentions that use ** the SQLite parser and code generator but substitute their own storage ** engine. */ #define BTREE_HINT_RANGE 0 /* Range constraints on queries */ /* ** Values that may be OR'd together to form the argument to the ** BTREE_HINT_FLAGS hint for sqlite3BtreeCursorHint(): ** ** The BTREE_BULKLOAD flag is set on index cursors when the index is going ** to be filled with content that is already in sorted order. ** ** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or ** OP_SeekLE opcodes for a range search, but where the range of entries ** selected will all have the same key. In other words, the cursor will |
︙ | ︙ | |||
186 187 188 189 190 191 192 193 194 195 196 197 198 199 | int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); int sqlite3BtreeCursorSize(void); void sqlite3BtreeCursorZero(BtCursor*); int sqlite3BtreeCloseCursor(BtCursor*); int sqlite3BtreeMovetoUnpacked( BtCursor*, UnpackedRecord *pUnKey, i64 intKey, int bias, | > > > > | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 | int iTable, /* Index of root page */ int wrFlag, /* 1 for writing. 0 for read-only */ struct KeyInfo*, /* First argument to compare function */ BtCursor *pCursor /* Space to write cursor structure */ ); int sqlite3BtreeCursorSize(void); void sqlite3BtreeCursorZero(BtCursor*); void sqlite3BtreeCursorHintFlags(BtCursor*, unsigned); #ifdef SQLITE_ENABLE_CURSOR_HINTS void sqlite3BtreeCursorHint(BtCursor*, int, ...); #endif int sqlite3BtreeCloseCursor(BtCursor*); int sqlite3BtreeMovetoUnpacked( BtCursor*, UnpackedRecord *pUnKey, i64 intKey, int bias, |
︙ | ︙ | |||
220 221 222 223 224 225 226 | char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); | < | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*); struct Pager *sqlite3BtreePager(Btree*); int sqlite3BtreePutData(BtCursor*, u32 offset, u32 amt, void*); void sqlite3BtreeIncrblobCursor(BtCursor *); void sqlite3BtreeClearCursor(BtCursor *); int sqlite3BtreeSetVersion(Btree *pBt, int iVersion); #ifdef SQLITE_DEBUG int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask); #endif int sqlite3BtreeIsReadonly(Btree *pBt); int sqlite3HeaderSizeBtree(void); #ifndef NDEBUG |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
544 545 546 547 548 549 550 | Parse *pParse, /* Parsing context */ int op, /* Expression opcode */ Expr *pLeft, /* Left operand */ Expr *pRight, /* Right operand */ const Token *pToken /* Argument token */ ){ Expr *p; | | | | 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 | Parse *pParse, /* Parsing context */ int op, /* Expression opcode */ Expr *pLeft, /* Left operand */ Expr *pRight, /* Right operand */ const Token *pToken /* Argument token */ ){ Expr *p; if( op==TK_AND && pParse->nErr==0 ){ /* Take advantage of short-circuit false optimization for AND */ p = sqlite3ExprAnd(pParse->db, pLeft, pRight); }else{ p = sqlite3ExprAlloc(pParse->db, op & TKFLG_MASK, pToken, 1); sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight); } if( p ) { sqlite3ExprCheckHeight(pParse, p->nHeight); } return p; } |
︙ | ︙ | |||
1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 | ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); return exprIsConst(p, 4+isInit, 0); } /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ | > > > > > > > > > > > > > > > > | 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 | ** is considered a variable but a single-quoted string (ex: 'abc') is ** a constant. */ int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){ assert( isInit==0 || isInit==1 ); return exprIsConst(p, 4+isInit, 0); } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* ** Walk an expression tree. Return 1 if the expression contains a ** subquery of some kind. Return 0 if there are no subqueries. */ int sqlite3ExprContainsSubquery(Expr *p){ Walker w; memset(&w, 0, sizeof(w)); w.eCode = 1; w.xExprCallback = sqlite3ExprWalkNoop; w.xSelectCallback = selectNodeIsConstant; sqlite3WalkExpr(&w, p); return w.eCode==0; } #endif /* ** If the expression p codes a constant integer that is small enough ** to fit in a 32-bit integer, return 1 and put the value of the integer ** in *pValue. If the expression is not an integer or if it is too big ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged. */ |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
738 739 740 741 742 743 744 745 746 747 748 749 750 751 | sqlite3PagerShrink(pPager); } } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } /* ** Configuration settings for an individual database connection */ int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | sqlite3PagerShrink(pPager); } } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return SQLITE_OK; } /* ** Flush any dirty pages in the pager-cache for any attached database ** to disk. */ int sqlite3_db_cacheflush(sqlite3 *db){ int i; int rc = SQLITE_OK; int bSeenBusy = 0; #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT; #endif sqlite3_mutex_enter(db->mutex); sqlite3BtreeEnterAll(db); for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt && sqlite3BtreeIsInTrans(pBt) ){ Pager *pPager = sqlite3BtreePager(pBt); rc = sqlite3PagerFlush(pPager); if( rc==SQLITE_BUSY ){ bSeenBusy = 1; rc = SQLITE_OK; } } } sqlite3BtreeLeaveAll(db); sqlite3_mutex_leave(db->mutex); return ((rc==SQLITE_OK && bSeenBusy) ? SQLITE_BUSY : rc); } /* ** Configuration settings for an individual database connection */ int sqlite3_db_config(sqlite3 *db, int op, ...){ va_list ap; int rc; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 | PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } return pager_error(pPager, rc); } /* ** Allocate and initialize a new Pager object and put a pointer to it ** in *ppPager. The pager should eventually be freed by passing it ** to sqlite3PagerClose(). ** ** The zFilename argument is the path to the database file to open. | > > > > > > > > > > > > > > > > > > > | 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 | PAGERTRACE(("STRESS %d page %d\n", PAGERID(pPager), pPg->pgno)); sqlite3PcacheMakeClean(pPg); } return pager_error(pPager, rc); } /* ** Flush all unreferenced dirty pages to disk. */ int sqlite3PagerFlush(Pager *pPager){ int rc = pPager->errCode; if( !MEMDB ){ PgHdr *pList = sqlite3PcacheDirtyList(pPager->pPCache); assert( assert_pager_state(pPager) ); while( rc==SQLITE_OK && pList ){ PgHdr *pNext = pList->pDirty; if( pList->nRef==0 ){ rc = pagerStress((void*)pPager, pList); } pList = pNext; } } return rc; } /* ** Allocate and initialize a new Pager object and put a pointer to it ** in *ppPager. The pager should eventually be freed by passing it ** to sqlite3PagerClose(). ** ** The zFilename argument is the path to the database file to open. |
︙ | ︙ | |||
5918 5919 5920 5921 5922 5923 5924 | ** If an error occurs, SQLITE_NOMEM or an IO error code is returned ** as appropriate. Otherwise, SQLITE_OK. */ int sqlite3PagerWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); | < > > | | 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 | ** If an error occurs, SQLITE_NOMEM or an IO error code is returned ** as appropriate. Otherwise, SQLITE_OK. */ int sqlite3PagerWrite(PgHdr *pPg){ Pager *pPager = pPg->pPager; assert( (pPg->flags & PGHDR_MMAP)==0 ); assert( pPager->eState>=PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); if( pPager->errCode ){ return pPager->errCode; }else if( (pPg->flags & PGHDR_WRITEABLE)!=0 && pPager->dbSize>=pPg->pgno ){ if( pPager->nSavepoint ) return subjournalPageIfRequired(pPg); return SQLITE_OK; }else if( pPager->sectorSize > (u32)pPager->pageSize ){ return pagerWriteLargeSector(pPg); }else{ return pager_write(pPg); } |
︙ | ︙ | |||
6098 6099 6100 6101 6102 6103 6104 | ** ** If the EXCLUSIVE lock is already held or the attempt to obtain it is ** successful, or the connection is in WAL mode, SQLITE_OK is returned. ** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is ** returned. */ int sqlite3PagerExclusiveLock(Pager *pPager){ | > > | | | | | | | | > | 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 | ** ** If the EXCLUSIVE lock is already held or the attempt to obtain it is ** successful, or the connection is in WAL mode, SQLITE_OK is returned. ** Otherwise, either SQLITE_BUSY or an SQLITE_IOERR_XXX error code is ** returned. */ int sqlite3PagerExclusiveLock(Pager *pPager){ int rc = pPager->errCode; assert( assert_pager_state(pPager) ); if( rc==SQLITE_OK ){ assert( pPager->eState==PAGER_WRITER_CACHEMOD || pPager->eState==PAGER_WRITER_DBMOD || pPager->eState==PAGER_WRITER_LOCKED ); assert( assert_pager_state(pPager) ); if( 0==pagerUseWal(pPager) ){ rc = pager_wait_on_lock(pPager, EXCLUSIVE_LOCK); } } return rc; } /* ** Sync the database file for the pager pPager. zMaster points to the name ** of a master journal file that should be written into the individual |
︙ | ︙ |
Changes to src/pager.h.
︙ | ︙ | |||
128 129 130 131 132 133 134 135 136 137 138 139 140 141 | void sqlite3PagerSetFlags(Pager*,unsigned); int sqlite3PagerLockingMode(Pager *, int); int sqlite3PagerSetJournalMode(Pager *, int); int sqlite3PagerGetJournalMode(Pager*); int sqlite3PagerOkToChangeJournalMode(Pager*); i64 sqlite3PagerJournalSizeLimit(Pager *, i64); sqlite3_backup **sqlite3PagerBackupPtr(Pager*); /* Functions used to obtain and release page references. */ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); void sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*); | > | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | void sqlite3PagerSetFlags(Pager*,unsigned); int sqlite3PagerLockingMode(Pager *, int); int sqlite3PagerSetJournalMode(Pager *, int); int sqlite3PagerGetJournalMode(Pager*); int sqlite3PagerOkToChangeJournalMode(Pager*); i64 sqlite3PagerJournalSizeLimit(Pager *, i64); sqlite3_backup **sqlite3PagerBackupPtr(Pager*); int sqlite3PagerFlush(Pager*); /* Functions used to obtain and release page references. */ int sqlite3PagerAcquire(Pager *pPager, Pgno pgno, DbPage **ppPage, int clrFlag); #define sqlite3PagerGet(A,B,C) sqlite3PagerAcquire(A,B,C,0) DbPage *sqlite3PagerLookup(Pager *pPager, Pgno pgno); void sqlite3PagerRef(DbPage*); void sqlite3PagerUnref(DbPage*); |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
925 926 927 928 929 930 931 932 933 934 935 936 937 938 | ExprSpan *pLeft, /* The left operand */ ExprSpan *pRight /* The right operand */ ){ pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); pOut->zStart = pLeft->zStart; pOut->zEnd = pRight->zEnd; } } expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) OR(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} | > > > > > > > | 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 | ExprSpan *pLeft, /* The left operand */ ExprSpan *pRight /* The right operand */ ){ pOut->pExpr = sqlite3PExpr(pParse, op, pLeft->pExpr, pRight->pExpr, 0); pOut->zStart = pLeft->zStart; pOut->zEnd = pRight->zEnd; } /* If doNot is true, then add a TK_NOT Expr-node wrapper around the ** outside of *ppExpr. */ static void exprNot(Parse *pParse, int doNot, Expr **ppExpr){ if( doNot ) *ppExpr = sqlite3PExpr(pParse, TK_NOT, *ppExpr, 0, 0); } } expr(A) ::= expr(X) AND(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) OR(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) LT|GT|GE|LE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} expr(A) ::= expr(X) EQ|NE(OP) expr(Y). {spanBinaryExpr(&A,pParse,@OP,&X,&Y);} |
︙ | ︙ | |||
947 948 949 950 951 952 953 | likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;} likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;} expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE_KW] { ExprList *pList; pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); pList = sqlite3ExprListAppend(pParse,pList, X.pExpr); A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator); | | | | 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 | likeop(A) ::= LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 0;} likeop(A) ::= NOT LIKE_KW|MATCH(X). {A.eOperator = X; A.bNot = 1;} expr(A) ::= expr(X) likeop(OP) expr(Y). [LIKE_KW] { ExprList *pList; pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); pList = sqlite3ExprListAppend(pParse,pList, X.pExpr); A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator); exprNot(pParse, OP.bNot, &A.pExpr); A.zStart = X.zStart; A.zEnd = Y.zEnd; if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; } expr(A) ::= expr(X) likeop(OP) expr(Y) ESCAPE expr(E). [LIKE_KW] { ExprList *pList; pList = sqlite3ExprListAppend(pParse,0, Y.pExpr); pList = sqlite3ExprListAppend(pParse,pList, X.pExpr); pList = sqlite3ExprListAppend(pParse,pList, E.pExpr); A.pExpr = sqlite3ExprFunction(pParse, pList, &OP.eOperator); exprNot(pParse, OP.bNot, &A.pExpr); A.zStart = X.zStart; A.zEnd = E.zEnd; if( A.pExpr ) A.pExpr->flags |= EP_InfixFunc; } %include { /* Construct an expression node for a unary postfix operator |
︙ | ︙ | |||
1048 1049 1050 1051 1052 1053 1054 | pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr); A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } | | | 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 | pList = sqlite3ExprListAppend(pParse,pList, Y.pExpr); A.pExpr = sqlite3PExpr(pParse, TK_BETWEEN, W.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = pList; }else{ sqlite3ExprListDelete(pParse->db, pList); } exprNot(pParse, N, &A.pExpr); A.zStart = W.zStart; A.zEnd = Y.zEnd; } %ifndef SQLITE_OMIT_SUBQUERY %type in_op {int} in_op(A) ::= IN. {A = 0;} in_op(A) ::= NOT IN. {A = 1;} |
︙ | ︙ | |||
1103 1104 1105 1106 1107 1108 1109 | A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } | | | 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 | A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pList = Y; sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3ExprListDelete(pParse->db, Y); } exprNot(pParse, N, &A.pExpr); } A.zStart = X.zStart; A.zEnd = &E.z[E.n]; } expr(A) ::= LP(B) select(X) RP(E). { A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0); if( A.pExpr ){ |
︙ | ︙ | |||
1129 1130 1131 1132 1133 1134 1135 | if( A.pExpr ){ A.pExpr->x.pSelect = Y; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); } | | | | 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 | if( A.pExpr ){ A.pExpr->x.pSelect = Y; ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SelectDelete(pParse->db, Y); } exprNot(pParse, N, &A.pExpr); A.zStart = X.zStart; A.zEnd = &E.z[E.n]; } expr(A) ::= expr(X) in_op(N) nm(Y) dbnm(Z). [IN] { SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z); A.pExpr = sqlite3PExpr(pParse, TK_IN, X.pExpr, 0, 0); if( A.pExpr ){ A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0); ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery); sqlite3ExprSetHeightAndFlags(pParse, A.pExpr); }else{ sqlite3SrcListDelete(pParse->db, pSrc); } exprNot(pParse, N, &A.pExpr); A.zStart = X.zStart; A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n]; } expr(A) ::= EXISTS(B) LP select(Y) RP(E). { Expr *p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0); if( p ){ p->x.pSelect = Y; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
4448 4449 4450 4451 4452 4453 4454 | ** ** When this routine is the Walker.xExprCallback then expression trees ** are walked without any actions being taken at each node. Presumably, ** when this routine is used for Walker.xExprCallback then ** Walker.xSelectCallback is set to do something useful for every ** subquery in the parser tree. */ | | | | 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 | ** ** When this routine is the Walker.xExprCallback then expression trees ** are walked without any actions being taken at each node. Presumably, ** when this routine is used for Walker.xExprCallback then ** Walker.xSelectCallback is set to do something useful for every ** subquery in the parser tree. */ int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){ UNUSED_PARAMETER2(NotUsed, NotUsed2); return WRC_Continue; } /* ** This routine "expands" a SELECT statement and all of its subqueries. ** For additional information on what it means to "expand" a SELECT ** statement, see the comment on the selectExpand worker callback above. ** ** Expanding a SELECT statement is the first step in processing a ** SELECT statement. The SELECT statement must be expanded before ** name resolution is performed. ** ** If anything goes wrong, an error message is written into pParse. ** The calling function can detect the problem by looking at pParse->nErr ** and/or pParse->db->mallocFailed. */ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ Walker w; memset(&w, 0, sizeof(w)); w.xExprCallback = sqlite3ExprWalkNoop; w.pParse = pParse; if( pParse->hasCompound ){ w.xSelectCallback = convertCompoundSelectToSubquery; sqlite3WalkSelect(&w, pSelect); } w.xSelectCallback = selectExpander; if( (pSelect->selFlags & SF_MultiValue)==0 ){ |
︙ | ︙ | |||
4536 4537 4538 4539 4540 4541 4542 | ** Use this routine after name resolution. */ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; memset(&w, 0, sizeof(w)); w.xSelectCallback2 = selectAddSubqueryTypeInfo; | | | 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 | ** Use this routine after name resolution. */ static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){ #ifndef SQLITE_OMIT_SUBQUERY Walker w; memset(&w, 0, sizeof(w)); w.xSelectCallback2 = selectAddSubqueryTypeInfo; w.xExprCallback = sqlite3ExprWalkNoop; w.pParse = pParse; sqlite3WalkSelect(&w, pSelect); #endif } /* |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 | ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 7789 7790 7791 7792 7793 7794 7795 7796 7797 7798 7799 7800 7801 7802 7803 7804 7805 7806 7807 7808 7809 7810 7811 7812 7813 7814 7815 7816 7817 7818 7819 7820 7821 7822 7823 7824 7825 7826 7827 7828 7829 7830 7831 | ** ^Zero all [sqlite3_stmt_scanstatus()] related event counters. ** ** This API is only available if the library is built with pre-processor ** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined. */ void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*); /* ** CAPI3REF: Flush caches to disk mid-transaction ** ** If a write-transaction is open when this function is called, any dirty ** pages in the pager-cache that are not currently in use are written out ** to disk. A dirty page may be in use if a database cursor created by an ** active SQL statement is reading from it, or if it is page 1 of a database ** file (page 1 is always "in use"). Dirty pages are flushed for all ** databases - "main", "temp" and any attached databases. ** ** If this function needs to obtain extra database locks before dirty pages ** can be flushed to disk, it does so. If said locks cannot be obtained ** immediately and there is a busy-handler callback configured, it is invoked ** in the usual manner. If the required lock still cannot be obtained, then ** the database is skipped and an attempt made to flush any dirty pages ** belonging to the next (if any) database. If any databases are skipped ** because locks cannot be obtained, but no other error occurs, this ** function returns SQLITE_BUSY. ** ** If any other error occurs while flushing dirty pages to disk (for ** example an IO error or out-of-memory condition), then processing is ** abandoned and an SQLite error code returned to the caller immediately. ** ** Otherwise, if no error occurs, SQLITE_OK is returned. ** ** This function does not set the database handle error code or message ** returned by the sqlite3_errcode() and sqlite3_errmsg() functions. */ int sqlite3_db_cacheflush(sqlite3*); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT # undef double |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 | #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_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ #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) | > | 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 | #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_Transitive 0x0200 /* Transitive constraints */ #define SQLITE_OmitNoopJoin 0x0400 /* Omit unused tables in joins */ #define SQLITE_Stat34 0x0800 /* Use STAT3 or STAT4 data */ #define SQLITE_CursorHints 0x2000 /* Add OP_CursorHint opcodes */ #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) |
︙ | ︙ | |||
3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 | u8 eCode; /* A small processing code */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int n; /* A counter */ int iCur; /* A cursor number */ SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); int sqlite3WalkSelectExpr(Walker*, Select*); int sqlite3WalkSelectFrom(Walker*, Select*); /* ** Return code from the parse-tree walking primitives and their ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ | > > | 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 | u8 eCode; /* A small processing code */ union { /* Extra data for callback */ NameContext *pNC; /* Naming context */ int n; /* A counter */ int iCur; /* A cursor number */ SrcList *pSrcList; /* FROM clause */ struct SrcCount *pSrcCount; /* Counting column references */ struct CCurHint *pCCurHint; /* Used by codeCursorHint() */ } u; }; /* Forward declarations */ int sqlite3WalkExpr(Walker*, Expr*); int sqlite3WalkExprList(Walker*, ExprList*); int sqlite3WalkSelect(Walker*, Select*); int sqlite3WalkSelectExpr(Walker*, Select*); int sqlite3WalkSelectFrom(Walker*, Select*); int sqlite3ExprWalkNoop(Walker*, Expr*); /* ** Return code from the parse-tree walking primitives and their ** callbacks. */ #define WRC_Continue 0 /* Continue down into children */ #define WRC_Prune 1 /* Omit children but continue walking siblings */ |
︙ | ︙ | |||
3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 | void sqlite3Savepoint(Parse*, int, Token*); void sqlite3CloseSavepoints(sqlite3 *); void sqlite3LeaveMutexAndCloseZombie(sqlite3*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsTableConstant(Expr*,int); int sqlite3ExprIsInteger(Expr*, int*); int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); | > > > | 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 | void sqlite3Savepoint(Parse*, int, Token*); void sqlite3CloseSavepoints(sqlite3 *); void sqlite3LeaveMutexAndCloseZombie(sqlite3*); int sqlite3ExprIsConstant(Expr*); int sqlite3ExprIsConstantNotJoin(Expr*); int sqlite3ExprIsConstantOrFunction(Expr*, u8); int sqlite3ExprIsTableConstant(Expr*,int); #ifdef SQLITE_ENABLE_CURSOR_HINTS int sqlite3ExprContainsSubquery(Expr*); #endif int sqlite3ExprIsInteger(Expr*, int*); int sqlite3ExprCanBeNull(const Expr*); int sqlite3ExprNeedsNoAffinityChange(const Expr*, char); int sqlite3IsRowid(const char*); void sqlite3GenerateRowDelete( Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8,int); void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*, int); |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 | return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_release_memory(db); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* ** Usage: sqlite3_db_filename DB DBNAME ** ** Return the name of a file associated with a database. */ static int test_db_filename( | > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 | return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_release_memory(db); Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); return TCL_OK; } /* ** Usage: sqlite3_db_cacheflush DB ** ** Attempt to flush any dirty pages to disk. */ static int test_db_cacheflush( void * clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[] ){ sqlite3 *db; int rc; if( objc!=2 ){ Tcl_WrongNumArgs(interp, 1, objv, "DB"); return TCL_ERROR; } if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; rc = sqlite3_db_cacheflush(db); if( rc ){ Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC); return TCL_ERROR; } Tcl_ResetResult(interp); return TCL_OK; } /* ** Usage: sqlite3_db_filename DB DBNAME ** ** Return the name of a file associated with a database. */ static int test_db_filename( |
︙ | ︙ | |||
7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 | { "sqlite3_next_stmt", test_next_stmt ,0 }, { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, { "sqlite3_stmt_busy", test_stmt_busy ,0 }, { "uses_stmt_journal", uses_stmt_journal ,0 }, { "sqlite3_release_memory", test_release_memory, 0}, { "sqlite3_db_release_memory", test_db_release_memory, 0}, { "sqlite3_db_filename", test_db_filename, 0}, { "sqlite3_db_readonly", test_db_readonly, 0}, { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, { "sqlite3_load_extension", test_load_extension, 0}, | > | 7093 7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 7104 7105 7106 7107 | { "sqlite3_next_stmt", test_next_stmt ,0 }, { "sqlite3_stmt_readonly", test_stmt_readonly ,0 }, { "sqlite3_stmt_busy", test_stmt_busy ,0 }, { "uses_stmt_journal", uses_stmt_journal ,0 }, { "sqlite3_release_memory", test_release_memory, 0}, { "sqlite3_db_release_memory", test_db_release_memory, 0}, { "sqlite3_db_cacheflush", test_db_cacheflush, 0}, { "sqlite3_db_filename", test_db_filename, 0}, { "sqlite3_db_readonly", test_db_readonly, 0}, { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0}, { "sqlite3_thread_cleanup", test_thread_cleanup, 0}, { "sqlite3_pager_refcounts", test_pager_refcounts, 0}, { "sqlite3_load_extension", test_load_extension, 0}, |
︙ | ︙ |
Changes to src/test_config.c.
︙ | ︙ | |||
114 115 116 117 118 119 120 121 122 123 124 125 126 127 | #endif #ifdef SQLITE_ENABLE_8_3_NAMES Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_MEMSYS3 Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY); #endif | > > > > > > | 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | #endif #ifdef SQLITE_ENABLE_8_3_NAMES Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "8_3_names", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_CURSOR_HINTS Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "cursorhints", "0", TCL_GLOBAL_ONLY); #endif #ifdef SQLITE_ENABLE_MEMSYS3 Tcl_SetVar2(interp, "sqlite_options", "mem3", "1", TCL_GLOBAL_ONLY); #else Tcl_SetVar2(interp, "sqlite_options", "mem3", "0", TCL_GLOBAL_ONLY); #endif |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
3394 3395 3396 3397 3398 3399 3400 | ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; open_cursor_set_hints: assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); | > > > > | | | 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 | ** and report database corruption if they were not, but this check has ** since moved into the btree layer. */ pCur->isTable = pOp->p4type!=P4_KEYINFO; open_cursor_set_hints: assert( OPFLAG_BULKCSR==BTREE_BULKLOAD ); assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ ); testcase( pOp->p5 & OPFLAG_BULKCSR ); #ifdef SQLITE_ENABLE_CURSOR_HINT testcase( pOp->p2 & OPFLAG_SEEKEQ ); #endif sqlite3BtreeCursorHintFlags(pCur->pCursor, (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ))); break; } /* Opcode: OpenEphemeral P1 P2 * P4 P5 ** Synopsis: nColumn=P2 ** ** Open a new cursor P1 to a transient table. |
︙ | ︙ | |||
6584 6585 6586 6587 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 | } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ if( pOp->p2 ) goto jump_to_p2; break; } /* Opcode: Noop * * * * * ** ** Do nothing. This instruction is often useful as a jump ** destination. */ /* | > > > > > > > > > > > > > > > > > > > > | 6588 6589 6590 6591 6592 6593 6594 6595 6596 6597 6598 6599 6600 6601 6602 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 | } #endif /* SQLITE_DEBUG */ #endif /* SQLITE_OMIT_TRACE */ if( pOp->p2 ) goto jump_to_p2; break; } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* Opcode: CursorHint P1 * * P4 * ** ** Provide a hint to cursor P1 that it only needs to return rows that ** satisfy the Expr in P4. TK_REGISTER terms in the P4 expression refer ** to values currently held in registers. TK_COLUMN terms in the P4 ** expression refer to columns in the b-tree to which cursor P1 is pointing. */ case OP_CursorHint: { VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); assert( pOp->p4type==P4_EXPR ); pC = p->apCsr[pOp->p1]; if( pC ){ sqlite3BtreeCursorHint(pC->pCursor, BTREE_HINT_RANGE, pOp->p4.pExpr, aMem); } break; } #endif /* SQLITE_ENABLE_CURSOR_HINTS */ /* Opcode: Noop * * * * * ** ** Do nothing. This instruction is often useful as a jump ** destination. */ /* |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
56 57 58 59 60 61 62 63 64 65 66 67 68 69 | sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ int (*xAdvance)(BtCursor *, int *); } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE u32 cnt; /* Number of times this instruction was executed */ | > > > | 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | sqlite3_context *pCtx; /* Used when p4type is P4_FUNCCTX */ CollSeq *pColl; /* Used when p4type is P4_COLLSEQ */ Mem *pMem; /* Used when p4type is P4_MEM */ VTable *pVtab; /* Used when p4type is P4_VTAB */ KeyInfo *pKeyInfo; /* Used when p4type is P4_KEYINFO */ int *ai; /* Used when p4type is P4_INTARRAY */ SubProgram *pProgram; /* Used when p4type is P4_SUBPROGRAM */ #ifdef SQLITE_ENABLE_CURSOR_HINTS Expr *pExpr; /* Used when p4type is P4_EXPR */ #endif int (*xAdvance)(BtCursor *, int *); } p4; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS char *zComment; /* Comment to improve readability */ #endif #ifdef VDBE_PROFILE u32 cnt; /* Number of times this instruction was executed */ |
︙ | ︙ | |||
106 107 108 109 110 111 112 113 114 115 116 117 118 119 | */ #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ #define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ #define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ #define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ #define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ | > | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | */ #define P4_NOTUSED 0 /* The P4 parameter is not used */ #define P4_DYNAMIC (-1) /* Pointer to a string obtained from sqliteMalloc() */ #define P4_STATIC (-2) /* Pointer to a static string */ #define P4_COLLSEQ (-4) /* P4 is a pointer to a CollSeq structure */ #define P4_FUNCDEF (-5) /* P4 is a pointer to a FuncDef structure */ #define P4_KEYINFO (-6) /* P4 is a pointer to a KeyInfo structure */ #define P4_EXPR (-7) /* P4 is a pointer to an Expr tree */ #define P4_MEM (-8) /* P4 is a pointer to a Mem* structure */ #define P4_TRANSIENT 0 /* P4 is a pointer to a transient string */ #define P4_VTAB (-10) /* P4 is a pointer to an sqlite3_vtab structure */ #define P4_MPRINTF (-11) /* P4 is a string obtained from sqlite3_mprintf() */ #define P4_REAL (-12) /* P4 is a 64-bit floating point value */ #define P4_INT64 (-13) /* P4 is a 64-bit signed integer */ #define P4_INT32 (-14) /* P4 is a 32-bit signed integer */ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ** The maximum number of times that a statement will try to reparse ** itself before giving up and returning SQLITE_SCHEMA. */ #ifndef SQLITE_MAX_SCHEMA_RETRY # define SQLITE_MAX_SCHEMA_RETRY 50 #endif /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. */ typedef struct VdbeOp Op; | > > > > > > > > > > > | 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 | ** The maximum number of times that a statement will try to reparse ** itself before giving up and returning SQLITE_SCHEMA. */ #ifndef SQLITE_MAX_SCHEMA_RETRY # define SQLITE_MAX_SCHEMA_RETRY 50 #endif /* ** VDBE_DISPLAY_P4 is true or false depending on whether or not the ** "explain" P4 display logic is enabled. */ #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \ || defined(VDBE_PROFILE) || defined(SQLITE_DEBUG) # define VDBE_DISPLAY_P4 1 #else # define VDBE_DISPLAY_P4 0 #endif /* ** SQL is translated into a sequence of instructions to be ** executed by a virtual machine. Each instruction is an instance ** of the following structure. */ typedef struct VdbeOp Op; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
759 760 761 762 763 764 765 766 767 768 769 770 771 772 | sqlite3DbFree(db, p4); break; } case P4_KEYINFO: { if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); break; } case P4_MPRINTF: { if( db->pnBytesFreed==0 ) sqlite3_free(p4); break; } case P4_FUNCDEF: { freeEphemeralFunction(db, (FuncDef*)p4); break; | > > > > > > | 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 | sqlite3DbFree(db, p4); break; } case P4_KEYINFO: { if( db->pnBytesFreed==0 ) sqlite3KeyInfoUnref((KeyInfo*)p4); break; } #ifdef SQLITE_ENABLE_CURSOR_HINTS case P4_EXPR: { sqlite3ExprDelete(db, (Expr*)p4); break; } #endif case P4_MPRINTF: { if( db->pnBytesFreed==0 ) sqlite3_free(p4); break; } case P4_FUNCDEF: { freeEphemeralFunction(db, (FuncDef*)p4); break; |
︙ | ︙ | |||
891 892 893 894 895 896 897 898 899 900 901 902 903 904 | pOp->p4type = P4_INT32; }else if( zP4==0 ){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; }else if( n==P4_KEYINFO ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_KEYINFO; }else if( n==P4_VTAB ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_VTAB; sqlite3VtabLock((VTable *)zP4); assert( ((VTable *)zP4)->db==p->db ); }else if( n<0 ){ pOp->p4.p = (void*)zP4; | > > > > > > > > > | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 | pOp->p4type = P4_INT32; }else if( zP4==0 ){ pOp->p4.p = 0; pOp->p4type = P4_NOTUSED; }else if( n==P4_KEYINFO ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_KEYINFO; #ifdef SQLITE_ENABLE_CURSOR_HINTS }else if( n==P4_EXPR ){ /* Responsibility for deleting the Expr tree is handed over to the ** VDBE by this operation. The caller should have already invoked ** sqlite3ExprDup() or whatever other routine is needed to make a ** private copy of the tree. */ pOp->p4.pExpr = (Expr*)zP4; pOp->p4type = P4_EXPR; #endif }else if( n==P4_VTAB ){ pOp->p4.p = (void*)zP4; pOp->p4type = P4_VTAB; sqlite3VtabLock((VTable *)zP4); assert( ((VTable *)zP4)->db==p->db ); }else if( n<0 ){ pOp->p4.p = (void*)zP4; |
︙ | ︙ | |||
1081 1082 1083 1084 1085 1086 1087 | zTemp[0] = 0; jj = 0; } return jj; } #endif /* SQLITE_DEBUG */ | > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | > > > > > > > > > > > > > > > > | 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 | zTemp[0] = 0; jj = 0; } return jj; } #endif /* SQLITE_DEBUG */ #if VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) /* ** Translate the P4.pExpr value for an OP_CursorHint opcode into text ** that can be displayed in the P4 column of EXPLAIN output. */ static int displayP4Expr(int nTemp, char *zTemp, Expr *pExpr){ const char *zOp = 0; int n; switch( pExpr->op ){ case TK_STRING: sqlite3_snprintf(nTemp, zTemp, "%Q", pExpr->u.zToken); break; case TK_INTEGER: sqlite3_snprintf(nTemp, zTemp, "%d", pExpr->u.iValue); break; case TK_NULL: sqlite3_snprintf(nTemp, zTemp, "NULL"); break; case TK_REGISTER: { sqlite3_snprintf(nTemp, zTemp, "r[%d]", pExpr->iTable); break; } case TK_COLUMN: { if( pExpr->iColumn<0 ){ sqlite3_snprintf(nTemp, zTemp, "rowid"); }else{ sqlite3_snprintf(nTemp, zTemp, "c%d", (int)pExpr->iColumn); } break; } case TK_LT: zOp = "LT"; break; case TK_LE: zOp = "LE"; break; case TK_GT: zOp = "GT"; break; case TK_GE: zOp = "GE"; break; case TK_NE: zOp = "NE"; break; case TK_EQ: zOp = "EQ"; break; case TK_IS: zOp = "IS"; break; case TK_ISNOT: zOp = "ISNOT"; break; case TK_AND: zOp = "AND"; break; case TK_OR: zOp = "OR"; break; case TK_PLUS: zOp = "ADD"; break; case TK_STAR: zOp = "MUL"; break; case TK_MINUS: zOp = "SUB"; break; case TK_REM: zOp = "REM"; break; case TK_BITAND: zOp = "BITAND"; break; case TK_BITOR: zOp = "BITOR"; break; case TK_SLASH: zOp = "DIV"; break; case TK_LSHIFT: zOp = "LSHIFT"; break; case TK_RSHIFT: zOp = "RSHIFT"; break; case TK_CONCAT: zOp = "CONCAT"; break; case TK_UMINUS: zOp = "MINUS"; break; case TK_UPLUS: zOp = "PLUS"; break; case TK_BITNOT: zOp = "BITNOT"; break; case TK_NOT: zOp = "NOT"; break; case TK_ISNULL: zOp = "ISNULL"; break; case TK_NOTNULL: zOp = "NOTNULL"; break; default: sqlite3_snprintf(nTemp, zTemp, "%s", "expr"); break; } if( zOp ){ sqlite3_snprintf(nTemp, zTemp, "%s(", zOp); n = sqlite3Strlen30(zTemp); n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pLeft); if( n<nTemp-1 && pExpr->pRight ){ zTemp[n++] = ','; n += displayP4Expr(nTemp-n, zTemp+n, pExpr->pRight); } sqlite3_snprintf(nTemp-n, zTemp+n, ")"); } return sqlite3Strlen30(zTemp); } #endif /* VDBE_DISPLAY_P4 && defined(SQLITE_ENABLE_CURSOR_HINTS) */ #if VDBE_DISPLAY_P4 /* ** Compute a string that describes the P4 parameter for an opcode. ** Use zTemp for any required temporary buffer space. */ static char *displayP4(Op *pOp, char *zTemp, int nTemp){ char *zP4 = zTemp; assert( nTemp>=20 ); |
︙ | ︙ | |||
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 | i += n; } zTemp[i++] = ')'; zTemp[i] = 0; assert( i<nTemp ); break; } case P4_COLLSEQ: { CollSeq *pColl = pOp->p4.pColl; sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; | > > > > > > | 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 | i += n; } zTemp[i++] = ')'; zTemp[i] = 0; assert( i<nTemp ); break; } #ifdef SQLITE_ENABLE_CURSOR_HINTS case P4_EXPR: { displayP4Expr(nTemp, zTemp, pOp->p4.pExpr); break; } #endif case P4_COLLSEQ: { CollSeq *pColl = pOp->p4.pColl; sqlite3_snprintf(nTemp, zTemp, "(%.20s)", pColl->zName); break; } case P4_FUNCDEF: { FuncDef *pDef = pOp->p4.pFunc; |
︙ | ︙ | |||
1198 1199 1200 1201 1202 1203 1204 | zTemp[0] = 0; } } } assert( zP4!=0 ); return zP4; } | | | 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 | zTemp[0] = 0; } } } assert( zP4!=0 ); return zP4; } #endif /* VDBE_DISPLAY_P4 */ /* ** Declare to the Vdbe that the BTree object at db->aDb[i] is used. ** ** The prepared statements need to know in advance the complete set of ** attached databases that will be use. A mask of these databases ** is maintained in p->btreeMask. The p->lockMask value is the subset of |
︙ | ︙ | |||
1512 1513 1514 1515 1516 1517 1518 | pMem->u.i = pOp->p2; /* P2 */ pMem++; pMem->flags = MEM_Int; pMem->u.i = pOp->p3; /* P3 */ pMem++; | | | | 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 | pMem->u.i = pOp->p2; /* P2 */ pMem++; pMem->flags = MEM_Int; pMem->u.i = pOp->p3; /* P3 */ pMem++; if( sqlite3VdbeMemClearAndResize(pMem, 100) ){ /* P4 */ assert( p->db->mallocFailed ); return SQLITE_ERROR; } pMem->flags = MEM_Str|MEM_Term; zP4 = displayP4(pOp, pMem->z, pMem->szMalloc); if( zP4!=pMem->z ){ sqlite3VdbeMemSetStr(pMem, zP4, -1, SQLITE_UTF8, 0); }else{ assert( pMem->z!=0 ); pMem->n = sqlite3Strlen30(pMem->z); pMem->enc = SQLITE_UTF8; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
4303 4304 4305 4306 4307 4308 4309 | && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = OP_OpenRead; if( pWInfo->eOnePass!=ONEPASS_OFF ){ op = OP_OpenWrite; pWInfo->aiCurOnePass[0] = pTabItem->iCursor; }; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); | < > > > > > > > > | 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 | && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = OP_OpenRead; if( pWInfo->eOnePass!=ONEPASS_OFF ){ op = OP_OpenWrite; pWInfo->aiCurOnePass[0] = pTabItem->iCursor; }; sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); assert( pTabItem->iCursor==pLevel->iTabCur ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS-1 ); testcase( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol==BMS ); if( pWInfo->eOnePass==ONEPASS_OFF && pTab->nCol<BMS && HasRowid(pTab) ){ Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} sqlite3VdbeChangeP4(v, sqlite3VdbeCurrentAddr(v)-1, SQLITE_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } #ifdef SQLITE_ENABLE_CURSOR_HINTS if( pLoop->u.btree.pIndex!=0 ){ sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ|bFordelete); }else #endif { sqlite3VdbeChangeP5(v, bFordelete); } #ifdef SQLITE_ENABLE_COLUMN_USED_MASK sqlite3VdbeAddOp4Dup8(v, OP_ColumnsUsed, pTabItem->iCursor, 0, 0, (const u8*)&pTabItem->colUsed, P4_INT64); #endif }else{ sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
586 587 588 589 590 591 592 593 594 595 596 597 598 599 | assert( pOp->opcode==OP_String8 || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); pOp->p3 = pLevel->iLikeRepCntr; pOp->p5 = 1; } } /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ Bitmask sqlite3WhereCodeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 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 | assert( pOp->opcode==OP_String8 || pTerm->pWC->pWInfo->pParse->db->mallocFailed ); pOp->p3 = pLevel->iLikeRepCntr; pOp->p5 = 1; } } #ifdef SQLITE_ENABLE_CURSOR_HINTS /* ** Information is passed from codeCursorHint() down to individual nodes of ** the expression tree (by sqlite3WalkExpr()) using an instance of this ** structure. */ struct CCurHint { int iTabCur; /* Cursor for the main table */ int iIdxCur; /* Cursor for the index, if pIdx!=0. Unused otherwise */ Index *pIdx; /* The index used to access the table */ }; /* ** This function is called for every node of an expression that is a candidate ** for a cursor hint on an index cursor. For TK_COLUMN nodes that reference ** the table CCurHint.iTabCur, verify that the same column can be ** accessed through the index. If it cannot, then set pWalker->eCode to 1. */ static int codeCursorHintCheckExpr(Walker *pWalker, Expr *pExpr){ struct CCurHint *pHint = pWalker->u.pCCurHint; assert( pHint->pIdx!=0 ); if( pExpr->op==TK_COLUMN && pExpr->iTable==pHint->iTabCur && sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn)<0 ){ pWalker->eCode = 1; } return WRC_Continue; } /* ** This function is called on every node of an expression tree used as an ** argument to the OP_CursorHint instruction. If the node is a TK_COLUMN ** that accesses any table other than the one identified by ** CCurHint.iTabCur, then do the following: ** ** 1) allocate a register and code an OP_Column instruction to read ** the specified column into the new register, and ** ** 2) transform the expression node to a TK_REGISTER node that reads ** from the newly populated register. ** ** Also, if the node is a TK_COLUMN that does access the table idenified ** by pCCurHint.iTabCur, and an index is being used (which we will ** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into ** an access of the index rather than the original table. */ static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){ int rc = WRC_Continue; struct CCurHint *pHint = pWalker->u.pCCurHint; if( pExpr->op==TK_COLUMN ){ if( pExpr->iTable!=pHint->iTabCur ){ Vdbe *v = pWalker->pParse->pVdbe; int reg = ++pWalker->pParse->nMem; /* Register for column value */ sqlite3ExprCodeGetColumnOfTable( v, pExpr->pTab, pExpr->iTable, pExpr->iColumn, reg ); pExpr->op = TK_REGISTER; pExpr->iTable = reg; }else if( pHint->pIdx!=0 ){ pExpr->iTable = pHint->iIdxCur; pExpr->iColumn = sqlite3ColumnOfIndex(pHint->pIdx, pExpr->iColumn); assert( pExpr->iColumn>=0 ); } }else if( pExpr->op==TK_AGG_FUNCTION ){ /* An aggregate function in the WHERE clause of a query means this must ** be a correlated sub-query, and expression pExpr is an aggregate from ** the parent context. Do not walk the function arguments in this case. ** ** todo: It should be possible to replace this node with a TK_REGISTER ** expression, as the result of the expression must be stored in a ** register at this point. The same holds for TK_AGG_COLUMN nodes. */ rc = WRC_Prune; } return rc; } /* ** Insert an OP_CursorHint instruction if it is appropriate to do so. */ static void codeCursorHint( WhereInfo *pWInfo, /* The where clause */ WhereLevel *pLevel, /* Which loop to provide hints for */ WhereTerm *pEndRange /* Hint this end-of-scan boundary term if not NULL */ ){ Parse *pParse = pWInfo->pParse; sqlite3 *db = pParse->db; Vdbe *v = pParse->pVdbe; Expr *pExpr = 0; WhereLoop *pLoop = pLevel->pWLoop; int iCur; WhereClause *pWC; WhereTerm *pTerm; int i, j; struct CCurHint sHint; Walker sWalker; if( OptimizationDisabled(db, SQLITE_CursorHints) ) return; iCur = pLevel->iTabCur; assert( iCur==pWInfo->pTabList->a[pLevel->iFrom].iCursor ); sHint.iTabCur = iCur; sHint.iIdxCur = pLevel->iIdxCur; sHint.pIdx = pLoop->u.btree.pIndex; memset(&sWalker, 0, sizeof(sWalker)); sWalker.pParse = pParse; sWalker.u.pCCurHint = &sHint; pWC = &pWInfo->sWC; for(i=0; i<pWC->nTerm; i++){ pTerm = &pWC->a[i]; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->prereqAll & pLevel->notReady ) continue; if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; /* All terms in pWLoop->aLTerm[] except pEndRange are used to initialize ** the cursor. These terms are not needed as hints for a pure range ** scan (that has no == terms) so omit them. */ if( pLoop->u.btree.nEq==0 && pTerm!=pEndRange ){ for(j=0; j<pLoop->nLTerm && pLoop->aLTerm[j]!=pTerm; j++){} if( j<pLoop->nLTerm ) continue; } /* No subqueries or non-deterministic functions allowed */ if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue; /* For an index scan, make sure referenced columns are actually in ** the index. */ if( sHint.pIdx!=0 ){ sWalker.eCode = 0; sWalker.xExprCallback = codeCursorHintCheckExpr; sqlite3WalkExpr(&sWalker, pTerm->pExpr); if( sWalker.eCode ) continue; } /* If we survive all prior tests, that means this term is worth hinting */ pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); } if( pExpr!=0 ){ sWalker.xExprCallback = codeCursorHintFixExpr; sqlite3WalkExpr(&sWalker, pExpr); sqlite3VdbeAddOp4(v, OP_CursorHint, (sHint.pIdx ? sHint.iIdxCur : sHint.iTabCur), 0, 0, (const char*)pExpr, P4_EXPR); } } #else # define codeCursorHint(A,B,C) /* No-op */ #endif /* SQLITE_ENABLE_CURSOR_HINTS */ /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ Bitmask sqlite3WhereCodeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ |
︙ | ︙ | |||
750 751 752 753 754 755 756 757 758 759 760 761 762 763 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++]; assert( pStart!=0 || pEnd!=0 ); if( bRev ){ pTerm = pStart; pStart = pEnd; pEnd = pTerm; } if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ /* The following constant maps TK_xx codes into corresponding ** seek opcodes. It depends on a particular ordering of TK_xx */ | > | 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++]; assert( pStart!=0 || pEnd!=0 ); if( bRev ){ pTerm = pStart; pStart = pEnd; pEnd = pTerm; } codeCursorHint(pWInfo, pLevel, pEnd); if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ /* The following constant maps TK_xx codes into corresponding ** seek opcodes. It depends on a particular ordering of TK_xx */ |
︙ | ︙ | |||
943 944 945 946 947 948 949 | && pIdx->pTable->aCol[j].notNull==0 ){ bSeekPastNull = 1; } } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); | < < < < < < < < < > > > > > > > > > > | 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 | && pIdx->pTable->aCol[j].notNull==0 ){ bSeekPastNull = 1; } } assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ if( (nEq<pIdx->nKeyCol && bRev==(pIdx->aSortOrder[nEq]==SQLITE_SO_ASC)) || (bRev && pIdx->nKeyCol==nEq) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); SWAP(u8, bSeekPastNull, bStopAtNull); } /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers ** starting at regBase. */ codeCursorHint(pWInfo, pLevel, pRangeEnd); regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq ); if( zStartAff ) cEndAff = zStartAff[nEq]; addrNxt = pLevel->addrNxt; testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); |
︙ | ︙ | |||
1245 1246 1247 1248 1249 1250 1251 | if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ | | | 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 | if( (pWC->a[iTerm].wtFlags & TERM_VIRTUAL)!=0 ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; testcase( pWC->a[iTerm].wtFlags & TERM_ORINFO ); pExpr = sqlite3ExprDup(db, pExpr, 0); pAndExpr = sqlite3ExprAnd(db, pAndExpr, pExpr); } if( pAndExpr ){ pAndExpr = sqlite3PExpr(pParse, TK_AND|TKFLG_DONTFOLD, 0, pAndExpr, 0); } } /* Run a separate WHERE clause for each term of the OR clause. After ** eliminating duplicates from other WHERE clauses, the action for each ** sub-WHERE clause is to to invoke the main loop body as a subroutine. */ |
︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 | static const u8 aStart[] = { OP_Rewind, OP_Last }; assert( bRev==0 || bRev==1 ); if( pTabItem->fg.isRecursive ){ /* Tables marked isRecursive have only a single row that is stored in ** a pseudo-cursor. No need to Rewind or Next such cursors. */ pLevel->op = OP_Noop; }else{ pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } | > | 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 | static const u8 aStart[] = { OP_Rewind, OP_Last }; assert( bRev==0 || bRev==1 ); if( pTabItem->fg.isRecursive ){ /* Tables marked isRecursive have only a single row that is stored in ** a pseudo-cursor. No need to Rewind or Next such cursors. */ pLevel->op = OP_Noop; }else{ codeCursorHint(pWInfo, pLevel, 0); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } |
︙ | ︙ |
Added test/cacheflush.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 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 | # 2011 November 16 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains test cases for sqlite3_db_cacheflush API. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix cacheflush test_set_config_pagecache 0 0 # Run the supplied SQL on a copy of the database currently stored on # disk in file $dbfile. proc diskquery {dbfile sql} { forcecopy $dbfile dq.db sqlite3 dq dq.db set res [execsql $sql dq] dq close set res } # Simplest possible test. # do_execsql_test 1.1.0 { CREATE TABLE t1(a, b); INSERT INTO t1 VALUES(1, 2); BEGIN; INSERT INTO t1 VALUES(3, 4); } do_test 1.1.1 { diskquery test.db { SELECT * FROM t1 } } {1 2} do_test 1.1.2 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1 } } {1 2 3 4} # Test that multiple pages may be flushed to disk. # do_execsql_test 1.2.0 { COMMIT; CREATE TABLE t2(a, b); BEGIN; INSERT INTO t1 VALUES(5, 6); INSERT INTO t2 VALUES('a', 'b'); } do_test 1.2.1 { diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; } } {1 2 3 4} do_test 1.2.2 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; } } {1 2 3 4 5 6 a b} # Test that pages with nRef!=0 are not flushed to disk. # do_execsql_test 1.3.0 { COMMIT; CREATE TABLE t3(a, b); BEGIN; INSERT INTO t1 VALUES(7, 8); INSERT INTO t2 VALUES('c', 'd'); INSERT INTO t3 VALUES('i', 'ii'); } do_test 1.3.1 { diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 4 5 6 a b} do_test 1.3.2 { db eval { SELECT a FROM t1 } { if {$a==3} { sqlite3_db_cacheflush db } } diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 4 5 6 a b c d i ii} do_test 1.3.2 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; SELECT * FROM t2; SELECT * FROM t3; } } {1 2 3 4 5 6 7 8 a b c d i ii} # Check that SQLITE_BUSY is returned if pages cannot be flushed due to # conflicting read locks. # do_execsql_test 1.4.0 { COMMIT; BEGIN; INSERT INTO t1 VALUES(9, 10); } do_test 1.4.1 { sqlite3 db2 test.db db2 eval { BEGIN; SELECT * FROM t1; } diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test 1.4.2 { list [catch { sqlite3_db_cacheflush db } msg] $msg } {1 {database is locked}} do_test 1.4.3 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8} do_test 1.4.4 { db2 close sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10} do_execsql_test 1.4.5 { COMMIT } #------------------------------------------------------------------------- # Test that ATTACHed database caches are also flushed. # forcedelete test.db2 do_execsql_test 2.1.0 { ATTACH 'test.db2' AS aux; CREATE TABLE aux.t4(x, y); INSERT INTO t4 VALUES('A', 'B'); BEGIN; INSERT INTO t1 VALUES(11, 12); INSERT INTO t4 VALUES('C', 'D'); } do_test 2.1.1 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10} do_test 2.1.2 { diskquery test.db2 { SELECT * FROM t4; } } {A B} do_test 2.1.3 { sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test 2.1.4 { sqlite3_db_cacheflush db diskquery test.db2 { SELECT * FROM t4; } } {A B C D} do_execsql_test 2.1.5 { COMMIT } # And that hitting an SQLITE_BUSY when flushing "main" does not stop # SQLite from going on to flush "aux". # do_execsql_test 2.2.0 { BEGIN; INSERT INTO t1 VALUES(13, 14); INSERT INTO t4 VALUES('E', 'F'); } do_test 2.2.1 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test 2.2.2 { diskquery test.db2 { SELECT * FROM t4; } } {A B C D} do_test 2.2.3 { sqlite3 db2 test.db execsql { BEGIN; SELECT * FROM t1; } db2 list [catch { sqlite3_db_cacheflush db } msg] $msg } {1 {database is locked}} do_test 2.2.4 { diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12} do_test 2.2.5 { diskquery test.db2 { SELECT * FROM t4; } } {A B C D E F} do_test 2.2.6 { db2 close sqlite3_db_cacheflush db diskquery test.db { SELECT * FROM t1; } } {1 2 3 4 5 6 7 8 9 10 11 12 13 14} do_execsql_test 2.2.7 { COMMIT } #------------------------------------------------------------------------- # Test that nothing terrible happens if sqlite3_db_cacheflush() is # called on an in-memory database. # do_test 3.0 { db close sqlite3 db :memory: db eval { CREATE TABLE t1(x PRIMARY KEY); CREATE TABLE t2(y PRIMARY KEY); BEGIN; INSERT INTO t1 VALUES(randomblob(100)); INSERT INTO t2 VALUES(randomblob(100)); INSERT INTO t1 VALUES(randomblob(100)); INSERT INTO t2 VALUES(randomblob(100)); } sqlite3_db_cacheflush db } {} do_execsql_test 3.1 { PRAGMA integrity_check } ok do_execsql_test 3.2 { COMMIT } do_execsql_test 3.3 { PRAGMA integrity_check } ok do_execsql_test 3.4 { SELECT count(*) FROM t1; SELECT count(*) FROM t2; } {2 2} #------------------------------------------------------------------------- # Test that calling sqlite3_db_cacheflush() does not interfere with # savepoint transactions. # do_test 4.0 { reset_db execsql { CREATE TABLE ta(a, aa); CREATE TABLE tb(b, bb); INSERT INTO ta VALUES('a', randomblob(500)); INSERT INTO tb VALUES('b', randomblob(500)); BEGIN; UPDATE ta SET a = 'A'; SAVEPOINT one; UPDATE tb SET b = 'B'; } sqlite3_db_cacheflush db diskquery test.db { SELECT a FROM ta; SELECT b FROM tb; } } {A B} do_test 4.1 { execsql { ROLLBACK TO one; } sqlite3_db_cacheflush db diskquery test.db { SELECT a FROM ta; SELECT b FROM tb; } } {A b} do_test 4.2 { execsql { INSERT INTO tb VALUES('c', randomblob(10)); INSERT INTO tb VALUES('d', randomblob(10)); INSERT INTO tb VALUES('e', randomblob(10)); } sqlite3_db_cacheflush db diskquery test.db { SELECT a FROM ta; SELECT b FROM tb; } } {A b c d e} do_test 4.3 { execsql { SAVEPOINT two; UPDATE tb SET b = upper(b); } sqlite3_db_cacheflush db diskquery test.db { SELECT a FROM ta; SELECT b FROM tb; } } {A B C D E} do_test 4.4 { execsql { ROLLBACK TO two; } sqlite3_db_cacheflush db diskquery test.db { SELECT a FROM ta; SELECT b FROM tb; } } {A b c d e} do_test 4.4 { execsql { ROLLBACK TO one; } sqlite3_db_cacheflush db diskquery test.db { SELECT a FROM ta; SELECT b FROM tb; } } {A b} do_test 4.5 { execsql { ROLLBACK; SELECT a FROM ta; SELECT b FROM tb; } } {a b} test_restore_config_pagecache finish_test |
Added test/cffault.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 | # 2011 November 16 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # This file contains fault-injection test cases for the # sqlite3_db_cacheflush API. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix cacheflush source $testdir/malloc_common.tcl # Run the supplied SQL on a copy of the database currently stored on # disk in file $dbfile. proc diskquery {dbfile sql} { forcecopy $dbfile dq.db sqlite3 dq dq.db set res [execsql $sql dq] dq close set res } do_execsql_test 1.0 { CREATE TABLE t1(a PRIMARY KEY, b); CREATE INDEX i1 ON t1(b); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t1 VALUES(5, 6); INSERT INTO t1 VALUES(7, 8); } faultsim_save_and_close do_faultsim_test 1.1 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b+1; } } -body { sqlite3_db_cacheflush db } -test { if {[sqlite3_get_autocommit db]} { error "Transaction rolled back!" } faultsim_test_result {0 {}} {1 {disk I/O error}} catch { db eval COMMIT } faultsim_integrity_check } do_faultsim_test 1.2 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b+1; } } -body { set result [list] db eval { SELECT * FROM t1 } { if {$a==5} { catch { sqlite3_db_cacheflush db } } lappend result $a $b } set result } -test { faultsim_test_result {0 {1 3 3 5 5 7 7 9}} {1 {disk I/O error}} catch { db eval COMMIT } faultsim_integrity_check } #------------------------------------------------------------------------- reset_db do_execsql_test 2.0 { CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE INDEX i1 ON t1(b); CREATE INDEX i2 ON t1(c, b); INSERT INTO t1 VALUES(1, 2, randomblob(600)); INSERT INTO t1 VALUES(3, 4, randomblob(600)); INSERT INTO t1 VALUES(5, 6, randomblob(600)); INSERT INTO t1 VALUES(7, 8, randomblob(600)); INSERT INTO t1 VALUES(9, 10, randomblob(600)); } faultsim_save_and_close do_faultsim_test 2.1 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b+1; } } -body { set result [list] db eval { SELECT * FROM t1 } { if {$a==5} { catch { sqlite3_db_cacheflush db } } lappend result $a $b } set result } -test { faultsim_test_result {0 {1 3 3 5 5 7 7 9 9 11}} {1 {disk I/O error}} catch { db eval { INSERT INTO t1 VALUES(11, 12, randomblob(600)) } } catch { db eval COMMIT } faultsim_integrity_check } do_faultsim_test 2.2 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b+1; } } -body { sqlite3_db_cacheflush db } -test { if {[sqlite3_get_autocommit db]} { error "Transaction rolled back!" } faultsim_test_result {0 {}} {1 {disk I/O error}} catch { db eval { SELECT * FROM t1 } } catch { db eval COMMIT } faultsim_integrity_check } do_faultsim_test 2.3 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b-1; } } -body { sqlite3_db_cacheflush db } -test { if {[sqlite3_get_autocommit db]} { error "Transaction rolled back!" } faultsim_test_result {0 {}} {1 {disk I/O error}} catch { db eval { INSERT INTO t1 VALUES(11, 12, randomblob(600)) } } catch { db eval COMMIT } faultsim_integrity_check } do_faultsim_test 2.4 -prep { faultsim_restore_and_reopen db eval { BEGIN; UPDATE t1 SET b=b-1; } } -body { catch { sqlite3_db_cacheflush db } catch { sqlite3_db_release_memory db } catch { sqlite3_db_cacheflush db } execsql { SELECT a, b FROM t1 } } -test { faultsim_test_result {0 {1 1 3 3 5 5 7 7 9 9}} {1 {disk I/O error}} catchsql ROLLBACK faultsim_integrity_check } finish_test |
Added test/cursorhint.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 | # 2014 July 15 # # 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. # set testdir [file dirname $argv0] source $testdir/tester.tcl set testprefix cursorhint ifcapable !cursorhints { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a,b,c,d); CREATE TABLE t2(x,y,z); INSERT INTO t1(a,b) VALUES(10, 15); INSERT INTO t1(a,b) VALUES(20, 25); INSERT INTO t2(x,y) VALUES('ten', 'fifteen'); INSERT INTO t2(x,y) VALUES('twenty', 'twentyfive'); CREATE TABLE t3(id TEXT PRIMARY KEY, a, b, c, d) WITHOUT ROWID; INSERT INTO t3(id,a,b,c,d) SELECT rowid, a, b, c, d FROM t1; PRAGMA automatic_index = 0; } # Run EXPLAIN on $sql. Return a list of P4 values for all $opcode # opcodes. # proc p4_of_opcode {db opcode sql} { set res {} $db eval "EXPLAIN $sql" x { if {$x(opcode)==$opcode} {lappend res $x(p4)} } return $res } # Run EXPLAIN on $sql. Return a list of P5 values for all $opcode # opcodes that contain regexp $comment in their comment # proc p5_of_opcode {db opcode comment sql} { set res {} $db eval "EXPLAIN $sql" x { if {$x(opcode)==$opcode && [regexp $comment $x(comment)]} { lappend res $x(p5) } } return $res } # Verify that when t1 is in the outer loop and t2 is in the inner loop, # no cursor hints occur for t1 (since it is a full table scan) but that # each t2 access has a cursor hint based on the current t1.a value. # do_test 1.1 { p4_of_opcode db CursorHint { SELECT * FROM t1 CROSS JOIN t2 WHERE a=x } } {{EQ(r[1],c0)}} do_test 1.2 { p5_of_opcode db OpenRead . { SELECT * FROM t1 CROSS JOIN t2 WHERE a=x } } {00 00} # Do the same test the other way around. # do_test 2.1 { p4_of_opcode db CursorHint { SELECT * FROM t2 CROSS JOIN t1 WHERE a=x } } {{EQ(c0,r[1])}} do_test 2.2 { p5_of_opcode db OpenRead . { SELECT * FROM t2 CROSS JOIN t1 WHERE a=x } } {00 00} # Various expressions captured by CursorHint # do_test 3.1 { p4_of_opcode db CursorHint { SELECT * FROM t1 WHERE a=15 AND c=22 AND rowid!=98 } } {AND(AND(EQ(c0,15),EQ(c2,22)),NE(rowid,98))} do_test 3.2 { p4_of_opcode db CursorHint { SELECT * FROM t3 WHERE a<15 AND b>22 AND id!=98 } } {AND(AND(LT(c1,15),GT(c2,22)),NE(c0,98))} # Indexed queries # do_test 4.1asc { db eval { CREATE INDEX t1bc ON t1(b,c); CREATE INDEX t2yz ON t2(y,z); } p4_of_opcode db CursorHint { SELECT * FROM t1 WHERE b>11 ORDER BY b ASC; } } {} do_test 4.1desc { p4_of_opcode db CursorHint { SELECT * FROM t1 WHERE b>11 ORDER BY b DESC; } } {GT(c0,11)} do_test 4.2 { p5_of_opcode db OpenRead . { SELECT * FROM t1 WHERE b>11; } } {02 00} do_test 4.3asc { p4_of_opcode db CursorHint { SELECT c FROM t1 WHERE b<11 ORDER BY b ASC; } } {LT(c0,11)} do_test 4.3desc { p4_of_opcode db CursorHint { SELECT c FROM t1 WHERE b<11 ORDER BY b DESC; } } {} do_test 4.4 { p5_of_opcode db OpenRead . { SELECT c FROM t1 WHERE b<11; } } {00} do_test 4.5asc { p4_of_opcode db CursorHint { SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b ASC; } } {LE(c0,20)} do_test 4.5desc { p4_of_opcode db CursorHint { SELECT c FROM t1 WHERE b>=10 AND b<=20 ORDER BY b DESC; } } {GE(c0,10)} # If there are any equality terms used in the constraint, then all terms # should be hinted. # do_test 4.6asc { p4_of_opcode db CursorHint { SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c ASC; } } {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))} do_test 4.6desc { p4_of_opcode db CursorHint { SELECT rowid FROM t1 WHERE b=22 AND c>=10 AND c<=20 ORDER BY b,c DESC; } } {AND(AND(EQ(c0,22),GE(c1,10)),LE(c1,20))} finish_test |
Changes to test/fuzzcheck.c.
︙ | ︙ | |||
66 67 68 69 70 71 72 73 74 75 76 77 78 79 | */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <ctype.h> #include "sqlite3.h" #ifdef __unix__ # include <signal.h> # include <unistd.h> #endif /* | > > > | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <ctype.h> #include "sqlite3.h" #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #ifdef __unix__ # include <signal.h> # include <unistd.h> #endif /* |
︙ | ︙ | |||
629 630 631 632 633 634 635 | zMore = 0; pStmt = 0; sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore); if( zMore==zSql ) break; if( runFlags & SQL_TRACE ){ const char *z = zSql; int n; | | | | 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 | zMore = 0; pStmt = 0; sqlite3_prepare_v2(db, zSql, -1, &pStmt, &zMore); if( zMore==zSql ) break; if( runFlags & SQL_TRACE ){ const char *z = zSql; int n; while( z<zMore && ISSPACE(z[0]) ) z++; n = (int)(zMore - z); while( n>0 && ISSPACE(z[n-1]) ) n--; if( n==0 ) break; if( pStmt==0 ){ printf("TRACE: %.*s (error: %s)\n", n, z, sqlite3_errmsg(db)); }else{ printf("TRACE: %.*s\n", n, z); } } |
︙ | ︙ | |||
753 754 755 756 757 758 759 | int x; zArg += 2; while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ | | | 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 | int x; zArg += 2; while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ while( ISDIGIT(zArg[0]) ){ v = v*10 + zArg[0] - '0'; zArg++; } } for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ v *= aMult[i].iMult; |
︙ | ︙ |
Changes to test/speedtest1.c.
︙ | ︙ | |||
43 44 45 46 47 48 49 50 51 52 53 54 55 56 | #include "sqlite3.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #if SQLITE_VERSION_NUMBER<3005000 # define sqlite3_int64 sqlite_int64 #endif #ifdef SQLITE_ENABLE_RBU # include "sqlite3rbu.h" #endif | > > | 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #include "sqlite3.h" #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #if SQLITE_VERSION_NUMBER<3005000 # define sqlite3_int64 sqlite_int64 #endif #ifdef SQLITE_ENABLE_RBU # include "sqlite3rbu.h" #endif |
︙ | ︙ | |||
311 312 313 314 315 316 317 | (int)(g.iTotal/1000), (int)(g.iTotal%1000)); } } /* Print an SQL statement to standard output */ static void printSql(const char *zSql){ int n = (int)strlen(zSql); | | | 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | (int)(g.iTotal/1000), (int)(g.iTotal%1000)); } } /* Print an SQL statement to standard output */ static void printSql(const char *zSql){ int n = (int)strlen(zSql); while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ){ n--; } if( g.bExplain ) printf("EXPLAIN "); printf("%.*s;\n", n, zSql); if( g.bExplain #if SQLITE_VERSION_NUMBER>=3007017 && ( sqlite3_strglob("CREATE *", zSql)==0 || sqlite3_strglob("DROP *", zSql)==0 || sqlite3_strglob("ALTER *", zSql)==0 |
︙ | ︙ | |||
410 411 412 413 414 415 416 | } speedtest1_shrink_memory(); } /* The sqlite3_trace() callback function */ static void traceCallback(void *NotUsed, const char *zSql){ int n = (int)strlen(zSql); | | | 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 | } speedtest1_shrink_memory(); } /* The sqlite3_trace() callback function */ static void traceCallback(void *NotUsed, const char *zSql){ int n = (int)strlen(zSql); while( n>0 && (zSql[n-1]==';' || ISSPACE(zSql[n-1])) ) n--; fprintf(stderr,"%.*s;\n", n, zSql); } /* Substitute random() function that gives the same random ** sequence on each run, for repeatability. */ static void randomFunc( sqlite3_context *context, |
︙ | ︙ |
Changes to test/wordcount.c.
︙ | ︙ | |||
76 77 78 79 80 81 82 83 84 85 86 87 88 89 | */ #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <stdarg.h> #include "sqlite3.h" /* Return the current wall-clock time */ static sqlite3_int64 realTime(void){ static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){ | > | 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | */ #include <stdio.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <stdarg.h> #include "sqlite3.h" #define ISALPHA(X) isalpha((unsigned char)(X)) /* Return the current wall-clock time */ static sqlite3_int64 realTime(void){ static sqlite3_vfs *clockVfs = 0; sqlite3_int64 t; if( clockVfs==0 ) clockVfs = sqlite3_vfs_find(0); if( clockVfs->iVersion>=1 && clockVfs->xCurrentTimeInt64!=0 ){ |
︙ | ︙ | |||
388 389 390 391 392 393 394 | if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n", sqlite3_errmsg(db)); } /* Process the input file */ while( fgets(zInput, sizeof(zInput), in) ){ for(i=0; zInput[i]; i++){ | | | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | if( rc ) fatal_error("Could not prepare the DELETE statement: %s\n", sqlite3_errmsg(db)); } /* Process the input file */ while( fgets(zInput, sizeof(zInput), in) ){ for(i=0; zInput[i]; i++){ if( !ISALPHA(zInput[i]) ) continue; for(j=i+1; ISALPHA(zInput[j]); j++){} /* Found a new word at zInput[i] that is j-i bytes long. ** Process it into the wordcount table. */ if( iMode==MODE_DELETE ){ sqlite3_bind_text(pDelete, 1, zInput+i, j-i, SQLITE_STATIC); if( sqlite3_step(pDelete)!=SQLITE_DONE ){ fatal_error("DELETE failed: %s\n", sqlite3_errmsg(db)); |
︙ | ︙ |
Changes to tool/addopcodes.tcl.
︙ | ︙ | |||
39 40 41 42 43 44 45 | UPLUS REGISTER } foreach x $extras { incr max puts [format "#define TK_%-29s %4d" $x $max] } | > > > > > > > > > > > > | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | UPLUS REGISTER } foreach x $extras { incr max puts [format "#define TK_%-29s %4d" $x $max] } # Some additional #defines related to token codes. # puts "\n/* The token codes above must all fit in 8 bits */" puts [format "#define %-20s %-6s" TKFLG_MASK 0xff] puts "\n/* Flags that can be added to a token code when it is not" puts "** being stored in a u8: */" foreach {fg val comment} { TKFLG_DONTFOLD 0x100 {/* Omit constant folding optimizations */} } { puts [format "#define %-20s %-6s %s" $fg $val $comment] } |
Changes to tool/build-all-msvc.bat.
︙ | ︙ | |||
90 91 92 93 94 95 96 97 98 99 100 101 102 103 | REM NMAKE_ARGS REM REM When set, the value is expanded and passed to the NMAKE command line, after REM its other arguments. This is used to specify additional NMAKE options, for REM example: REM REM SET NMAKE_ARGS=FOR_WINRT=1 REM SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO REM SET __ECHO3=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) | > > > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | REM NMAKE_ARGS REM REM When set, the value is expanded and passed to the NMAKE command line, after REM its other arguments. This is used to specify additional NMAKE options, for REM example: REM REM SET NMAKE_ARGS=FOR_WINRT=1 REM REM Using the above command before running this tool will cause the compiled REM binaries to target the WinRT environment, which provides a subset of the REM Win32 API. REM SETLOCAL REM SET __ECHO=ECHO REM SET __ECHO2=ECHO REM SET __ECHO3=ECHO IF NOT DEFINED _AECHO (SET _AECHO=REM) |
︙ | ︙ |
Changes to tool/fuzzershell.c.
︙ | ︙ | |||
63 64 65 66 67 68 69 70 71 72 73 74 75 76 | */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <ctype.h> #include "sqlite3.h" /* ** All global variables are gathered into the "g" singleton. */ struct GlobalVars { const char *zArgv0; /* Name of program */ sqlite3_mem_methods sOrigMem; /* Original memory methods */ | > | 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <ctype.h> #include "sqlite3.h" #define ISDIGIT(X) isdigit((unsigned char)(X)) /* ** All global variables are gathered into the "g" singleton. */ struct GlobalVars { const char *zArgv0; /* Name of program */ sqlite3_mem_methods sOrigMem; /* Original memory methods */ |
︙ | ︙ | |||
379 380 381 382 383 384 385 | int x; zArg += 2; while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ | | | 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 | int x; zArg += 2; while( (x = hexDigitValue(zArg[0]))>=0 ){ v = (v<<4) + x; zArg++; } }else{ while( ISDIGIT(zArg[0]) ){ v = v*10 + zArg[0] - '0'; zArg++; } } for(i=0; i<sizeof(aMult)/sizeof(aMult[0]); i++){ if( sqlite3_stricmp(aMult[i].zSuffix, zArg)==0 ){ v *= aMult[i].iMult; |
︙ | ︙ |
Changes to tool/lemon.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 15 16 17 18 19 20 21 | */ #include <stdio.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <assert.h> #ifndef __WIN32__ # if defined(_WIN32) || defined(WIN32) # define __WIN32__ # endif #endif | > > > > > > > > | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | */ #include <stdio.h> #include <stdarg.h> #include <string.h> #include <ctype.h> #include <stdlib.h> #include <assert.h> #define ISSPACE(X) isspace((unsigned char)(X)) #define ISDIGIT(X) isdigit((unsigned char)(X)) #define ISALNUM(X) isalnum((unsigned char)(X)) #define ISALPHA(X) isalpha((unsigned char)(X)) #define ISUPPER(X) isupper((unsigned char)(X)) #define ISLOWER(X) islower((unsigned char)(X)) #ifndef __WIN32__ # if defined(_WIN32) || defined(WIN32) # define __WIN32__ # endif #endif |
︙ | ︙ | |||
89 90 91 92 93 94 95 | char zTemp[50]; str[0] = 0; for(i=j=0; (c = zFormat[i])!=0; i++){ if( c=='%' ){ int iWidth = 0; lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); c = zFormat[++i]; | | | | 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | char zTemp[50]; str[0] = 0; for(i=j=0; (c = zFormat[i])!=0; i++){ if( c=='%' ){ int iWidth = 0; lemon_addtext(str, &nUsed, &zFormat[j], i-j, 0); c = zFormat[++i]; if( ISDIGIT(c) || (c=='-' && ISDIGIT(zFormat[i+1])) ){ if( c=='-' ) i++; while( ISDIGIT(zFormat[i]) ) iWidth = iWidth*10 + zFormat[i++] - '0'; if( c=='-' ) iWidth = -iWidth; c = zFormat[i]; } if( c=='d' ){ int v = va_arg(ap, int); if( v<0 ){ lemon_addtext(str, &nUsed, "-", 1, iWidth); |
︙ | ︙ | |||
1574 1575 1576 1577 1578 1579 1580 | lem.symbols = Symbol_arrayof(); for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); lem.nsymbol = i - 1; | | | 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 | lem.symbols = Symbol_arrayof(); for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; qsort(lem.symbols,lem.nsymbol,sizeof(struct symbol*), Symbolcmpp); for(i=0; i<lem.nsymbol; i++) lem.symbols[i]->index = i; while( lem.symbols[i-1]->type==MULTITERMINAL ){ i--; } assert( strcmp(lem.symbols[i-1]->name,"{default}")==0 ); lem.nsymbol = i - 1; for(i=1; ISUPPER(lem.symbols[i]->name[0]); i++); lem.nterminal = i; /* Generate a reprint of the grammar, if requested on the command line */ if( rpflag ){ Reprint(&lem); }else{ /* Initialize the size for all follow and first sets */ |
︙ | ︙ | |||
2117 2118 2119 2120 2121 2122 2123 | psp->preccounter = 0; psp->firstrule = psp->lastrule = 0; psp->gp->nrule = 0; /* Fall thru to next case */ case WAITING_FOR_DECL_OR_RULE: if( x[0]=='%' ){ psp->state = WAITING_FOR_DECL_KEYWORD; | | | 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 | psp->preccounter = 0; psp->firstrule = psp->lastrule = 0; psp->gp->nrule = 0; /* Fall thru to next case */ case WAITING_FOR_DECL_OR_RULE: if( x[0]=='%' ){ psp->state = WAITING_FOR_DECL_KEYWORD; }else if( ISLOWER(x[0]) ){ psp->lhs = Symbol_new(x); psp->nrhs = 0; psp->lhsalias = 0; psp->state = WAITING_FOR_ARROW; }else if( x[0]=='{' ){ if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, |
︙ | ︙ | |||
2147 2148 2149 2150 2151 2152 2153 | ErrorMsg(psp->filename,psp->tokenlineno, "Token \"%s\" should be either \"%%\" or a nonterminal name.", x); psp->errorcnt++; } break; case PRECEDENCE_MARK_1: | | | 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 | ErrorMsg(psp->filename,psp->tokenlineno, "Token \"%s\" should be either \"%%\" or a nonterminal name.", x); psp->errorcnt++; } break; case PRECEDENCE_MARK_1: if( !ISUPPER(x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "The precedence symbol must be a terminal."); psp->errorcnt++; }else if( psp->prevrule==0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "There is no prior rule to assign precedence \"[%s]\".",x); psp->errorcnt++; |
︙ | ︙ | |||
2187 2188 2189 2190 2191 2192 2193 | "Expected to see a \":\" following the LHS symbol \"%s\".", psp->lhs->name); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case LHS_ALIAS_1: | | | 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 | "Expected to see a \":\" following the LHS symbol \"%s\".", psp->lhs->name); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case LHS_ALIAS_1: if( ISALPHA(x[0]) ){ psp->lhsalias = x; psp->state = LHS_ALIAS_2; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "\"%s\" is not a valid alias for the LHS \"%s\"\n", x,psp->lhs->name); psp->errorcnt++; |
︙ | ︙ | |||
2256 2257 2258 2259 2260 2261 2262 | }else{ psp->lastrule->next = rp; psp->lastrule = rp; } psp->prevrule = rp; } psp->state = WAITING_FOR_DECL_OR_RULE; | | | 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 | }else{ psp->lastrule->next = rp; psp->lastrule = rp; } psp->prevrule = rp; } psp->state = WAITING_FOR_DECL_OR_RULE; }else if( ISALPHA(x[0]) ){ if( psp->nrhs>=MAXRHS ){ ErrorMsg(psp->filename,psp->tokenlineno, "Too many symbols on RHS of rule beginning at \"%s\".", x); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; }else{ |
︙ | ︙ | |||
2285 2286 2287 2288 2289 2290 2291 | msp->name = origsp->name; psp->rhs[psp->nrhs-1] = msp; } msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); | | | | 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 | msp->name = origsp->name; psp->rhs[psp->nrhs-1] = msp; } msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); msp->subsym[msp->nsubsym-1] = Symbol_new(&x[1]); if( ISLOWER(x[1]) || ISLOWER(msp->subsym[0]->name[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Cannot form a compound containing a non-terminal"); psp->errorcnt++; } }else if( x[0]=='(' && psp->nrhs>0 ){ psp->state = RHS_ALIAS_1; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Illegal character on RHS of rule: \"%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case RHS_ALIAS_1: if( ISALPHA(x[0]) ){ psp->alias[psp->nrhs-1] = x; psp->state = RHS_ALIAS_2; }else{ ErrorMsg(psp->filename,psp->tokenlineno, "\"%s\" is not a valid alias for the RHS symbol \"%s\"\n", x,psp->rhs[psp->nrhs-1]->name); psp->errorcnt++; |
︙ | ︙ | |||
2322 2323 2324 2325 2326 2327 2328 | ErrorMsg(psp->filename,psp->tokenlineno, "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case WAITING_FOR_DECL_KEYWORD: | | | 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 | ErrorMsg(psp->filename,psp->tokenlineno, "Missing \")\" following LHS alias name \"%s\".",psp->lhsalias); psp->errorcnt++; psp->state = RESYNC_AFTER_RULE_ERROR; } break; case WAITING_FOR_DECL_KEYWORD: if( ISALPHA(x[0]) ){ psp->declkeyword = x; psp->declargslot = 0; psp->decllinenoslot = 0; psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; if( strcmp(x,"name")==0 ){ psp->declargslot = &(psp->gp->name); |
︙ | ︙ | |||
2402 2403 2404 2405 2406 2407 2408 | ErrorMsg(psp->filename,psp->tokenlineno, "Illegal declaration keyword: \"%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_DESTRUCTOR_SYMBOL: | | | | 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 | ErrorMsg(psp->filename,psp->tokenlineno, "Illegal declaration keyword: \"%s\".",x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_DESTRUCTOR_SYMBOL: if( !ISALPHA(x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol name missing after %%destructor keyword"); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ struct symbol *sp = Symbol_new(x); psp->declargslot = &sp->destructor; psp->decllinenoslot = &sp->destLineno; psp->insertLineMacro = 1; psp->state = WAITING_FOR_DECL_ARG; } break; case WAITING_FOR_DATATYPE_SYMBOL: if( !ISALPHA(x[0]) ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol name missing after %%type keyword"); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ struct symbol *sp = Symbol_find(x); if((sp) && (sp->datatype)){ |
︙ | ︙ | |||
2441 2442 2443 2444 2445 2446 2447 | psp->state = WAITING_FOR_DECL_ARG; } } break; case WAITING_FOR_PRECEDENCE_SYMBOL: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; | | | | 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 | psp->state = WAITING_FOR_DECL_ARG; } } break; case WAITING_FOR_PRECEDENCE_SYMBOL: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( ISUPPER(x[0]) ){ struct symbol *sp; sp = Symbol_new(x); if( sp->prec>=0 ){ ErrorMsg(psp->filename,psp->tokenlineno, "Symbol \"%s\" has already be given a precedence.",x); psp->errorcnt++; }else{ sp->prec = psp->preccounter; sp->assoc = psp->declassoc; } }else{ ErrorMsg(psp->filename,psp->tokenlineno, "Can't assign a precedence to \"%s\".",x); psp->errorcnt++; } break; case WAITING_FOR_DECL_ARG: if( x[0]=='{' || x[0]=='\"' || ISALNUM(x[0]) ){ const char *zOld, *zNew; char *zBuf, *z; int nOld, n, nLine = 0, nNew, nBack; int addLineMacro; char zLine[50]; zNew = x; if( zNew[0]=='"' || zNew[0]=='{' ) zNew++; |
︙ | ︙ | |||
2520 2521 2522 2523 2524 2525 2526 | psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_FALLBACK_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; | | | | | | | 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 | psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } break; case WAITING_FOR_FALLBACK_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( !ISUPPER(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%fallback argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); if( psp->fallback==0 ){ psp->fallback = sp; }else if( sp->fallback ){ ErrorMsg(psp->filename, psp->tokenlineno, "More than one fallback assigned to token %s", x); psp->errorcnt++; }else{ sp->fallback = psp->fallback; psp->gp->has_fallback = 1; } } break; case WAITING_FOR_WILDCARD_ID: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( !ISUPPER(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%wildcard argument \"%s\" should be a token", x); psp->errorcnt++; }else{ struct symbol *sp = Symbol_new(x); if( psp->gp->wildcard==0 ){ psp->gp->wildcard = sp; }else{ ErrorMsg(psp->filename, psp->tokenlineno, "Extra wildcard to token: %s", x); psp->errorcnt++; } } break; case WAITING_FOR_CLASS_ID: if( !ISLOWER(x[0]) ){ ErrorMsg(psp->filename, psp->tokenlineno, "%%token_class must be followed by an identifier: ", x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else if( Symbol_find(x) ){ ErrorMsg(psp->filename, psp->tokenlineno, "Symbol \"%s\" already used", x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; }else{ psp->tkclass = Symbol_new(x); psp->tkclass->type = MULTITERMINAL; psp->state = WAITING_FOR_CLASS_TOKEN; } break; case WAITING_FOR_CLASS_TOKEN: if( x[0]=='.' ){ psp->state = WAITING_FOR_DECL_OR_RULE; }else if( ISUPPER(x[0]) || ((x[0]=='|' || x[0]=='/') && ISUPPER(x[1])) ){ struct symbol *msp = psp->tkclass; msp->nsubsym++; msp->subsym = (struct symbol **) realloc(msp->subsym, sizeof(struct symbol*)*msp->nsubsym); if( !ISUPPER(x[0]) ) x++; msp->subsym[msp->nsubsym-1] = Symbol_new(x); }else{ ErrorMsg(psp->filename, psp->tokenlineno, "%%token_class argument \"%s\" should be a token", x); psp->errorcnt++; psp->state = RESYNC_AFTER_DECL_ERROR; } |
︙ | ︙ | |||
2614 2615 2616 2617 2618 2619 2620 | int exclude = 0; int start = 0; int lineno = 1; int start_lineno = 1; for(i=0; z[i]; i++){ if( z[i]=='\n' ) lineno++; if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; | | | | | | | 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 | int exclude = 0; int start = 0; int lineno = 1; int start_lineno = 1; for(i=0; z[i]; i++){ if( z[i]=='\n' ) lineno++; if( z[i]!='%' || (i>0 && z[i-1]!='\n') ) continue; if( strncmp(&z[i],"%endif",6)==0 && ISSPACE(z[i+6]) ){ if( exclude ){ exclude--; if( exclude==0 ){ for(j=start; j<i; j++) if( z[j]!='\n' ) z[j] = ' '; } } for(j=i; z[j] && z[j]!='\n'; j++) z[j] = ' '; }else if( (strncmp(&z[i],"%ifdef",6)==0 && ISSPACE(z[i+6])) || (strncmp(&z[i],"%ifndef",7)==0 && ISSPACE(z[i+7])) ){ if( exclude ){ exclude++; }else{ for(j=i+7; ISSPACE(z[j]); j++){} for(n=0; z[j+n] && !ISSPACE(z[j+n]); n++){} exclude = 1; for(k=0; k<nDefine; k++){ if( strncmp(azDefine[k],&z[j],n)==0 && lemonStrlen(azDefine[k])==n ){ exclude = 0; break; } } |
︙ | ︙ | |||
2708 2709 2710 2711 2712 2713 2714 | /* Make an initial pass through the file to handle %ifdef and %ifndef */ preprocess_input(filebuf); /* Now scan the text of the input file */ lineno = 1; for(cp=filebuf; (c= *cp)!=0; ){ if( c=='\n' ) lineno++; /* Keep track of the line number */ | | | 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 | /* Make an initial pass through the file to handle %ifdef and %ifndef */ preprocess_input(filebuf); /* Now scan the text of the input file */ lineno = 1; for(cp=filebuf; (c= *cp)!=0; ){ if( c=='\n' ) lineno++; /* Keep track of the line number */ if( ISSPACE(c) ){ cp++; continue; } /* Skip all white space */ if( c=='/' && cp[1]=='/' ){ /* Skip C++ style comments */ cp+=2; while( (c= *cp)!=0 && c!='\n' ) cp++; continue; } if( c=='/' && cp[1]=='*' ){ /* Skip C style comments */ cp+=2; |
︙ | ︙ | |||
2778 2779 2780 2781 2782 2783 2784 | ErrorMsg(ps.filename,ps.tokenlineno, "C code starting on this line is not terminated before the end of the file."); ps.errorcnt++; nextcp = cp; }else{ nextcp = cp+1; } | | | | | | 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 | ErrorMsg(ps.filename,ps.tokenlineno, "C code starting on this line is not terminated before the end of the file."); ps.errorcnt++; nextcp = cp; }else{ nextcp = cp+1; } }else if( ISALNUM(c) ){ /* Identifiers */ while( (c= *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++; nextcp = cp; }else if( c==':' && cp[1]==':' && cp[2]=='=' ){ /* The operator "::=" */ cp += 3; nextcp = cp; }else if( (c=='/' || c=='|') && ISALPHA(cp[1]) ){ cp += 2; while( (c = *cp)!=0 && (ISALNUM(c) || c=='_') ) cp++; nextcp = cp; }else{ /* All other (one character) operators */ cp++; nextcp = cp; } c = *cp; *cp = 0; /* Null terminate the token */ |
︙ | ︙ | |||
3237 3238 3239 3240 3241 3242 3243 | char line[LINESIZE]; while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ (*lineno)++; iStart = 0; if( name ){ for(i=0; line[i]; i++){ if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 | | | 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 | char line[LINESIZE]; while( fgets(line,LINESIZE,in) && (line[0]!='%' || line[1]!='%') ){ (*lineno)++; iStart = 0; if( name ){ for(i=0; line[i]; i++){ if( line[i]=='P' && strncmp(&line[i],"Parse",5)==0 && (i==0 || !ISALPHA(line[i-1])) ){ if( i>iStart ) fprintf(out,"%.*s",i-iStart,&line[iStart]); fprintf(out,"%s",name); i += 4; iStart = i+1; } } |
︙ | ︙ | |||
3474 3475 3476 3477 3478 3479 3480 | rp->line = rp->ruleline; } append_str(0,0,0,0); /* This const cast is wrong but harmless, if we're careful. */ for(cp=(char *)rp->code; *cp; cp++){ | | | | 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 | rp->line = rp->ruleline; } append_str(0,0,0,0); /* This const cast is wrong but harmless, if we're careful. */ for(cp=(char *)rp->code; *cp; cp++){ if( ISALPHA(*cp) && (cp==rp->code || (!ISALNUM(cp[-1]) && cp[-1]!='_')) ){ char saved; for(xp= &cp[1]; ISALNUM(*xp) || *xp=='_'; xp++); saved = *xp; *xp = 0; if( rp->lhsalias && strcmp(cp,rp->lhsalias)==0 ){ append_str("yygotominor.yy%d",0,rp->lhs->dtnum,0); cp = xp; lhsused = 1; }else{ |
︙ | ︙ | |||
3641 3642 3643 3644 3645 3646 3647 | if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){ sp->dtnum = 0; continue; } cp = sp->datatype; if( cp==0 ) cp = lemp->vartype; j = 0; | | | | 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 | if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){ sp->dtnum = 0; continue; } cp = sp->datatype; if( cp==0 ) cp = lemp->vartype; j = 0; while( ISSPACE(*cp) ) cp++; while( *cp ) stddt[j++] = *cp++; while( j>0 && ISSPACE(stddt[j-1]) ) j--; stddt[j] = 0; if( lemp->tokentype && strcmp(stddt, lemp->tokentype)==0 ){ sp->dtnum = 0; continue; } hash = 0; for(j=0; stddt[j]; j++){ |
︙ | ︙ | |||
3853 3854 3855 3856 3857 3858 3859 | fprintf(out, "#endif\n"); lineno++; if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ i = lemonStrlen(lemp->arg); | | | | 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 | fprintf(out, "#endif\n"); lineno++; if( mhflag ){ fprintf(out,"#if INTERFACE\n"); lineno++; } name = lemp->name ? lemp->name : "Parse"; if( lemp->arg && lemp->arg[0] ){ i = lemonStrlen(lemp->arg); while( i>=1 && ISSPACE(lemp->arg[i-1]) ) i--; while( i>=1 && (ISALNUM(lemp->arg[i-1]) || lemp->arg[i-1]=='_') ) i--; fprintf(out,"#define %sARG_SDECL %s;\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_PDECL ,%s\n",name,lemp->arg); lineno++; fprintf(out,"#define %sARG_FETCH %s = yypParser->%s\n", name,lemp->arg,&lemp->arg[i]); lineno++; fprintf(out,"#define %sARG_STORE yypParser->%s = %s\n", name,&lemp->arg[i],&lemp->arg[i]); lineno++; }else{ |
︙ | ︙ | |||
4662 4663 4664 4665 4666 4667 4668 | struct symbol *sp; sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); | | | 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 | struct symbol *sp; sp = Symbol_find(x); if( sp==0 ){ sp = (struct symbol *)calloc(1, sizeof(struct symbol) ); MemoryCheck(sp); sp->name = Strsafe(x); sp->type = ISUPPER(*x) ? TERMINAL : NONTERMINAL; sp->rule = 0; sp->fallback = 0; sp->prec = -1; sp->assoc = UNK; sp->firstset = 0; sp->lambda = LEMON_FALSE; sp->destructor = 0; |
︙ | ︙ |
Changes to tool/mkautoconfamal.sh.
︙ | ︙ | |||
52 53 54 55 56 57 58 | cat $TMPSPACE/configure.ac | sed "s/AC_INIT(sqlite, .*, http:\/\/www.sqlite.org)/AC_INIT(sqlite, $VERSION, http:\/\/www.sqlite.org)/" > $TMPSPACE/tmp mv $TMPSPACE/tmp $TMPSPACE/configure.ac cd $TMPSPACE aclocal autoconf | | | 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | cat $TMPSPACE/configure.ac | sed "s/AC_INIT(sqlite, .*, http:\/\/www.sqlite.org)/AC_INIT(sqlite, $VERSION, http:\/\/www.sqlite.org)/" > $TMPSPACE/tmp mv $TMPSPACE/tmp $TMPSPACE/configure.ac cd $TMPSPACE aclocal autoconf automake --add-missing mkdir -p tea/generic echo "#ifdef USE_SYSTEM_SQLITE" > tea/generic/tclsqlite3.c echo "# include <sqlite3.h>" >> tea/generic/tclsqlite3.c echo "#else" >> tea/generic/tclsqlite3.c echo "#include \"sqlite3.c\"" >> tea/generic/tclsqlite3.c echo "#endif" >> tea/generic/tclsqlite3.c |
︙ | ︙ |
Changes to tool/showdb.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** A utility for printing all or part of an SQLite database file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if !defined(_MSC_VER) #include <unistd.h> #else | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /* ** A utility for printing all or part of an SQLite database file. */ #include <stdio.h> #include <ctype.h> #define ISDIGIT(X) isdigit((unsigned char)(X)) #define ISPRINT(X) isprint((unsigned char)(X)) #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if !defined(_MSC_VER) #include <unistd.h> #else |
︙ | ︙ | |||
213 214 215 216 217 218 219 | fprintf(stdout,"%02x ", aData[i+j]); } } for(j=0; j<g.perLine; j++){ if( i+j>nByte ){ fprintf(stdout, " "); }else{ | | | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | fprintf(stdout,"%02x ", aData[i+j]); } } for(j=0; j<g.perLine; j++){ if( i+j>nByte ){ fprintf(stdout, " "); }else{ fprintf(stdout,"%c", ISPRINT(aData[i+j]) ? aData[i+j] : '.'); } } fprintf(stdout,"\n"); } return aData; } |
︙ | ︙ | |||
596 597 598 599 600 601 602 | zConst[1] = '\''; for(ii=2, jj=0; jj<szCol[i] && ii<24; jj++, ii+=2){ sprintf(zConst+ii, "%02x", pData[jj]); } }else{ zConst[0] = '\''; for(ii=1, jj=0; jj<szCol[i] && ii<24; jj++, ii++){ | | | 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 | zConst[1] = '\''; for(ii=2, jj=0; jj<szCol[i] && ii<24; jj++, ii+=2){ sprintf(zConst+ii, "%02x", pData[jj]); } }else{ zConst[0] = '\''; for(ii=1, jj=0; jj<szCol[i] && ii<24; jj++, ii++){ zConst[ii] = ISPRINT(pData[jj]) ? pData[jj] : '.'; } zConst[ii] = 0; } if( jj<szCol[i] ){ memcpy(zConst+ii, "...'", 5); }else{ memcpy(zConst+ii, "'", 2); |
︙ | ︙ | |||
649 650 651 652 653 654 655 | case 13: zType = "table leaf"; break; } while( zArgs[0] ){ switch( zArgs[0] ){ case 'c': showCellContent = 1; break; case 'm': showMap = 1; break; case 'd': { | | | | 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 | case 13: zType = "table leaf"; break; } while( zArgs[0] ){ switch( zArgs[0] ){ case 'c': showCellContent = 1; break; case 'm': showMap = 1; break; case 'd': { if( !ISDIGIT(zArgs[1]) ){ cellToDecode = -1; }else{ cellToDecode = 0; while( ISDIGIT(zArgs[1]) ){ zArgs++; cellToDecode = cellToDecode*10 + zArgs[0] - '0'; } } break; } } |
︙ | ︙ | |||
1119 1120 1121 1122 1123 1124 1125 | ptrmap_coverage_report(azArg[1]); continue; } if( strcmp(azArg[i], "help")==0 ){ usage(zPrg); continue; } | | | 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 | ptrmap_coverage_report(azArg[1]); continue; } if( strcmp(azArg[i], "help")==0 ){ usage(zPrg); continue; } if( !ISDIGIT(azArg[i][0]) ){ fprintf(stderr, "%s: unknown option: [%s]\n", zPrg, azArg[i]); continue; } iStart = strtol(azArg[i], &zLeft, 0); if( zLeft && strcmp(zLeft,"..end")==0 ){ iEnd = g.mxPage; }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){ |
︙ | ︙ |
Changes to tool/showstat4.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | /* ** This utility program decodes and displays the content of the ** sqlite_stat4 table in the database file named on the command ** line. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include "sqlite3.h" typedef sqlite3_int64 i64; /* 64-bit signed integer type */ /* ** Convert the var-int format into i64. Return the number of bytes ** in the var-int. Write the var-int value into *pVal. | > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** This utility program decodes and displays the content of the ** sqlite_stat4 table in the database file named on the command ** line. */ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include "sqlite3.h" #define ISPRINT(X) isprint((unsigned char)(X)) typedef sqlite3_int64 i64; /* 64-bit signed integer type */ /* ** Convert the var-int format into i64. Return the number of bytes ** in the var-int. Write the var-int value into *pVal. |
︙ | ︙ | |||
127 128 129 130 131 132 133 | printf("%02x", aSample[y+j]); } printf("'"); }else{ printf("%s\"", zSep); for(j=0; j<sz; j++){ char c = (char)aSample[y+j]; | | | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | printf("%02x", aSample[y+j]); } printf("'"); }else{ printf("%s\"", zSep); for(j=0; j<sz; j++){ char c = (char)aSample[y+j]; if( ISPRINT(c) ){ if( c=='"' || c=='\\' ) putchar('\\'); putchar(c); }else if( c=='\n' ){ printf("\\n"); }else if( c=='\t' ){ printf("\\t"); }else if( c=='\r' ){ |
︙ | ︙ |
Changes to tool/showwal.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | /* ** A utility for printing content from a write-ahead log file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #if !defined(_MSC_VER) #include <unistd.h> #else #include <io.h> #endif #include <stdlib.h> | > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** A utility for printing content from a write-ahead log file. */ #include <stdio.h> #include <ctype.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #define ISDIGIT(X) isdigit((unsigned char)(X)) #define ISPRINT(X) isprint((unsigned char)(X)) #if !defined(_MSC_VER) #include <unistd.h> #else #include <io.h> #endif #include <stdlib.h> |
︙ | ︙ | |||
155 156 157 158 159 160 161 | fprintf(stdout,"%02x ", aData[i+j]); } } for(j=0; j<perLine; j++){ if( i+j>nByte ){ fprintf(stdout, " "); }else{ | | | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | fprintf(stdout,"%02x ", aData[i+j]); } } for(j=0; j<perLine; j++){ if( i+j>nByte ){ fprintf(stdout, " "); }else{ fprintf(stdout,"%c", ISPRINT(aData[i+j]) ? aData[i+j] : '.'); } } fprintf(stdout,"\n"); } } /* Print a line of decode output showing a 4-byte integer. |
︙ | ︙ | |||
546 547 548 549 550 551 552 | for(i=2; i<argc; i++){ int iStart, iEnd; char *zLeft; if( strcmp(argv[i], "header")==0 ){ print_wal_header(0); continue; } | | | 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 | for(i=2; i<argc; i++){ int iStart, iEnd; char *zLeft; if( strcmp(argv[i], "header")==0 ){ print_wal_header(0); continue; } if( !ISDIGIT(argv[i][0]) ){ fprintf(stderr, "%s: unknown option: [%s]\n", argv[0], argv[i]); continue; } iStart = strtol(argv[i], &zLeft, 0); if( zLeft && strcmp(zLeft,"..end")==0 ){ iEnd = mxFrame; }else if( zLeft && zLeft[0]=='.' && zLeft[1]=='.' ){ |
︙ | ︙ |
Changes to tool/speedtest16.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include "sqlite3.h" /* ** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ #include "hwtime.h" /* | > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <stdio.h> #include <string.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include "sqlite3.h" #define ISSPACE(X) isspace((unsigned char)(X)) /* ** hwtime.h contains inline assembler code for implementing ** high-performance timing routines. */ #include "hwtime.h" /* |
︙ | ︙ | |||
136 137 138 139 140 141 142 | int isComplete; char c = zSql[j+1]; zSql[j+1] = 0; isComplete = sqlite3_complete(&zSql[i]); zSql[j+1] = c; if( isComplete ){ zSql[j] = 0; | | | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | int isComplete; char c = zSql[j+1]; zSql[j+1] = 0; isComplete = sqlite3_complete(&zSql[i]); zSql[j+1] = c; if( isComplete ){ zSql[j] = 0; while( i<j && ISSPACE(zSql[i]) ){ i++; } if( i<j ){ nStmt++; nByte += j-i; prepareAndRun(db, &zSql[i]); } zSql[j] = ';'; i = j+1; |
︙ | ︙ |
Changes to tool/speedtest8inst1.c.
︙ | ︙ | |||
25 26 27 28 29 30 31 32 33 34 35 36 37 38 | #include <string.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <stdarg.h> #include "sqlite3.h" #include "test_osinst.c" /* ** Prepare and run a single statement of SQL. */ static void prepareAndRun(sqlite3_vfs *pInstVfs, sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; | > > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | #include <string.h> #include <stdlib.h> #include <ctype.h> #include <unistd.h> #include <stdarg.h> #include "sqlite3.h" #define ISSPACE(X) isspace((unsigned char)(X)) #include "test_osinst.c" /* ** Prepare and run a single statement of SQL. */ static void prepareAndRun(sqlite3_vfs *pInstVfs, sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; |
︙ | ︙ | |||
193 194 195 196 197 198 199 | int isComplete; char c = zSql[j+1]; zSql[j+1] = 0; isComplete = sqlite3_complete(&zSql[i]); zSql[j+1] = c; if( isComplete ){ zSql[j] = 0; | | | 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 | int isComplete; char c = zSql[j+1]; zSql[j+1] = 0; isComplete = sqlite3_complete(&zSql[i]); zSql[j+1] = c; if( isComplete ){ zSql[j] = 0; while( i<j && ISSPACE(zSql[i]) ){ i++; } if( i<j ){ prepareAndRun(pInstVfs, db, &zSql[i]); } zSql[j] = ';'; i = j+1; } } |
︙ | ︙ |