Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Difference From 49777032f29517d2 To 2537db6f6b9df009
2023-05-13
| ||
15:00 | Merge the latest 3.42.0 beta changes into the wal2 branch. check-in: 771361e19e user: drh tags: wal2 | |
2023-05-04
| ||
14:41 | Merge latest wal2 changes into this branch. check-in: b2e0800b24 user: dan tags: bedrock | |
14:31 | Update this branch with latest changes from trunk. check-in: 49777032f2 user: dan tags: wal2 | |
11:29 | Fix a bug in cursor hints that can cause references to tables that have not been opened. Cursor hints are intended for use by COMDB2 only and should not appear in production builds, so this should not be a factor for the vast majority of users. check-in: d3370d59cf user: drh tags: trunk | |
2023-05-02
| ||
19:58 | Merge the latest trunk enhancements into the wal2 branch. check-in: 0215dcc76d user: drh tags: wal2 | |
2023-02-18
| ||
21:42 | Merge the latest trunk enhancements into the wal2 branch. check-in: a36de0c803 user: drh tags: wal2 | |
2023-02-07
| ||
11:39 | Merge the latest trunk enhancements into the bedrock branch. check-in: b7d9f14d78 user: drh tags: bedrock | |
11:19 | Fix a dropped error code in wal.c. check-in: 2537db6f6b user: dan tags: wal2 | |
10:58 | Fix an assert() in sqlite3WalFindFrame() so that it matches the equivalent assert() on trunk. check-in: f5bf91d9bf user: dan tags: wal2 | |
Changes to Makefile.in.
︙ | ︙ | |||
585 586 587 588 589 590 591 | # Standard options to testfixture # TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # | < | | | < | | < | < | | | | < < < < < | < < < | < < < < < < < < < < < < < | < | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 | # Standard options to testfixture # TESTOPTS = --verbose=file --output=test-out.txt # Extra compiler options for various shell tools # SHELL_OPT = -DSQLITE_ENABLE_FTS4 #SHELL_OPT += -DSQLITE_ENABLE_FTS5 SHELL_OPT += -DSQLITE_ENABLE_RTREE SHELL_OPT += -DSQLITE_ENABLE_EXPLAIN_COMMENTS SHELL_OPT += -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION SHELL_OPT += -DSQLITE_ENABLE_STMTVTAB SHELL_OPT += -DSQLITE_ENABLE_DBPAGE_VTAB SHELL_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB SHELL_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB SHELL_OPT += -DSQLITE_ENABLE_OFFSET_SQL_FUNC FUZZERSHELL_OPT = FUZZCHECK_OPT += -I$(TOP)/test FUZZCHECK_OPT += -I$(TOP)/ext/recover FUZZCHECK_OPT += -DSQLITE_OMIT_LOAD_EXTENSION FUZZCHECK_OPT += -DSQLITE_ENABLE_MEMSYS5 -DSQLITE_OSS_FUZZ FUZZCHECK_OPT += -DSQLITE_MAX_MEMORY=50000000 FUZZCHECK_OPT += -DSQLITE_PRINTF_PRECISION_LIMIT=1000 FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS4 FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS3_PARENTHESIS FUZZCHECK_OPT += -DSQLITE_ENABLE_FTS5 FUZZCHECK_OPT += -DSQLITE_ENABLE_RTREE FUZZCHECK_OPT += -DSQLITE_ENABLE_GEOPOLY FUZZCHECK_OPT += -DSQLITE_ENABLE_DBSTAT_VTAB FUZZCHECK_OPT += -DSQLITE_ENABLE_BYTECODE_VTAB FUZZCHECK_SRC += $(TOP)/test/fuzzcheck.c FUZZCHECK_SRC += $(TOP)/test/ossfuzz.c FUZZCHECK_SRC += $(TOP)/test/fuzzinvariants.c FUZZCHECK_SRC += $(TOP)/ext/recover/dbdata.c FUZZCHECK_SRC += $(TOP)/ext/recover/sqlite3recover.c FUZZCHECK_SRC += $(TOP)/test/vt02.c DBFUZZ_OPT = ST_OPT = -DSQLITE_OS_KV_OPTIONAL # This is the default Makefile target. The objects listed here # are what get build when you type just "make" with no arguments. # all: sqlite3.h libsqlite3.la sqlite3$(TEXE) $(HAVE_TCL:1=libtclsqlite3.la) Makefile: $(TOP)/Makefile.in ./config.status sqlite3.pc: $(TOP)/sqlite3.pc.in ./config.status |
︙ | ︙ | |||
694 695 696 697 698 699 700 | fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS) | < < < | 668 669 670 671 672 673 674 675 676 677 678 679 680 681 | fuzzershell$(TEXE): $(TOP)/tool/fuzzershell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZERSHELL_OPT) \ $(TOP)/tool/fuzzershell.c sqlite3.c $(TLIBS) fuzzcheck$(TEXE): $(FUZZCHECK_SRC) sqlite3.c sqlite3.h $(FUZZCHECK_DEP) $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(FUZZCHECK_SRC) sqlite3.c $(TLIBS) ossshell$(TEXE): $(TOP)/test/ossfuzz.c $(TOP)/test/ossshell.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(FUZZCHECK_OPT) $(TOP)/test/ossshell.c \ $(TOP)/test/ossfuzz.c sqlite3.c $(TLIBS) sessionfuzz$(TEXE): $(TOP)/test/sessionfuzz.c sqlite3.c sqlite3.h $(LTLINK) -o $@ $(TOP)/test/sessionfuzz.c $(TLIBS) |
︙ | ︙ |
Changes to Makefile.msc.
︙ | ︙ | |||
1522 1523 1524 1525 1526 1527 1528 | $(TOP)\src\test_vfs.c \ $(TOP)\src\test_windirent.c \ $(TOP)\src\test_window.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\rbu\test_rbu.c \ | | | 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 | $(TOP)\src\test_vfs.c \ $(TOP)\src\test_windirent.c \ $(TOP)\src\test_window.c \ $(TOP)\src\test_wsd.c \ $(TOP)\ext\fts3\fts3_term.c \ $(TOP)\ext\fts3\fts3_test.c \ $(TOP)\ext\rbu\test_rbu.c \ $(TOP)\ext\session\test_session.c # Statically linked extensions. # TESTEXT = \ $(TOP)\ext\expert\sqlite3expert.c \ $(TOP)\ext\expert\test_expert.c \ $(TOP)\ext\misc\amatch.c \ |
︙ | ︙ | |||
1654 1655 1656 1657 1658 1659 1660 | $(TOP)\test\fuzzdata8.db # <</mark>> # Additional compiler options for the shell. These are only effective # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 | $(TOP)\test\fuzzdata8.db # <</mark>> # Additional compiler options for the shell. These are only effective # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1 !ENDIF # <<mark>> # Extra compiler options for various test tools. # MPTESTER_COMPILE_OPTS = -DSQLITE_ENABLE_FTS5 FUZZERSHELL_COMPILE_OPTS = FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -I$(TOP)\test -I$(TOP)\ext\recover FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_MEMSYS5 FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_OSS_FUZZ FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_MAX_MEMORY=50000000 FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_PRINTF_PRECISION_LIMIT=1000 FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_OMIT_LOAD_EXTENSION FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS4 FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_FTS5 FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_RTREE FUZZCHECK_OPTS = $(FUZZCHECK_OPTS) -DSQLITE_ENABLE_GEOPOLY |
︙ | ︙ | |||
1813 1814 1815 1816 1817 1818 1819 | dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) | < < < | 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | dbfuzz.exe: $(TOP)\test\dbfuzz.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(DBFUZZ_COMPILE_OPTS) $(TOP)\test\dbfuzz.c $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) fuzzcheck.exe: $(FUZZCHECK_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(FUZZCHECK_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) ossshell.exe: $(OSSSHELL_SRC) $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) $(FUZZCHECK_OPTS) $(OSSSHELL_SRC) $(SQLITE3C) /link $(LDFLAGS) $(LTLINKOPTS) sessionfuzz.exe: zlib $(TOP)\test\sessionfuzz.c $(SQLITE3C) $(SQLITE3H) $(LTLINK) $(NO_WARN) -I$(ZLIBINCDIR) $(TOP)\test\sessionfuzz.c /link $(LDFLAGS) $(LTLINKOPTS) /LIBPATH:$(ZLIBLIBDIR) $(ZLIBLIB) mptester.exe: $(TOP)\mptest\mptest.c $(SQLITE3C) $(SQLITE3H) |
︙ | ︙ |
Changes to README.md.
1 2 3 4 5 6 7 8 9 | <h1 align="center">SQLite Source Repository</h1> This repository contains the complete source code for the [SQLite database engine](https://sqlite.org/). Some test scripts are also included. However, many other test scripts and most of the documentation are managed separately. ## Version Control | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <h1 align="center">SQLite Source Repository</h1> This repository contains the complete source code for the [SQLite database engine](https://sqlite.org/). Some test scripts are also included. However, many other test scripts and most of the documentation are managed separately. ## Version Control SQLite sources are managed using the [Fossil](https://www.fossil-scm.org/), a distributed version control system that was specifically designed and written to support SQLite development. The [Fossil repository](https://sqlite.org/src/timeline) contains the urtext. If you are reading this on GitHub or some other Git repository or service, then you are looking at a mirror. The names of check-ins and other artifacts in a Git mirror are different from the official |
︙ | ︙ |
Changes to VERSION.
|
| | | 1 | 3.41.0 |
Changes to autoconf/Makefile.msc.
︙ | ︙ | |||
951 952 953 954 955 956 957 | !ENDIF # Additional compiler options for the shell. These are only effective # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 | < | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | !ENDIF # Additional compiler options for the shell. These are only effective # when the shell is not being dynamically linked. # !IF $(DYNAMIC_SHELL)==0 && $(FOR_WIN10)==0 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_FTS4=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_EXPLAIN_COMMENTS=1 SHELL_COMPILE_OPTS = $(SHELL_COMPILE_OPTS) -DSQLITE_ENABLE_OFFSET_SQL_FUNC=1 !ENDIF # This is the default Makefile target. The objects listed here |
︙ | ︙ |
Changes to autoconf/tea/configure.ac.
︙ | ︙ | |||
15 16 17 18 19 20 21 | # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME> # so that we create the export library with the dll. #----------------------------------------------------------------------- | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | # This initializes the environment with PACKAGE_NAME and PACKAGE_VERSION # set as provided. These will also be added as -D defs in your Makefile # so you can encode the package version directly into the source files. # This will also define a special symbol for Windows (BUILD_<PACKAGE_NAME> # so that we create the export library with the dll. #----------------------------------------------------------------------- AC_INIT([sqlite],[3.40.0]) #-------------------------------------------------------------------- # Call TEA_INIT as the first TEA_ macro to set up initial vars. # This will define a ${TEA_PLATFORM} variable == "unix" or "windows" # as well as PKG_LIB_FILE and PKG_STUB_LIB_FILE. #-------------------------------------------------------------------- |
︙ | ︙ |
Changes to configure.
1 2 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. | | | 1 2 3 4 5 6 7 8 9 10 | #! /bin/sh # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.69 for sqlite 3.41.0. # # # Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. # # # This configure script is free software; the Free Software Foundation # gives unlimited permission to copy, distribute and modify it. |
︙ | ︙ | |||
722 723 724 725 726 727 728 | subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' | | | | 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 | subdirs= MFLAGS= MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sqlite' PACKAGE_TARNAME='sqlite' PACKAGE_VERSION='3.41.0' PACKAGE_STRING='sqlite 3.41.0' PACKAGE_BUGREPORT='' PACKAGE_URL='' # Factoring default headers for most tests. ac_includes_default="\ #include <stdio.h> #ifdef HAVE_SYS_TYPES_H |
︙ | ︙ | |||
796 797 798 799 800 801 802 | SQLITE_OS_WIN SQLITE_OS_UNIX BUILD_EXEEXT TEMP_STORE ALLOWRELEASE SQLITE_THREADSAFE BUILD_CC | < | 796 797 798 799 800 801 802 803 804 805 806 807 808 809 | SQLITE_OS_WIN SQLITE_OS_UNIX BUILD_EXEEXT TEMP_STORE ALLOWRELEASE SQLITE_THREADSAFE BUILD_CC RELEASE VERSION program_prefix TCLLIBDIR TCLSH_CMD INSTALL_DATA INSTALL_SCRIPT |
︙ | ︙ | |||
889 890 891 892 893 894 895 | enable_shared enable_static with_pic enable_fast_install with_gnu_ld enable_libtool_lock enable_largefile | < | 888 889 890 891 892 893 894 895 896 897 898 899 900 901 | enable_shared enable_static with_pic enable_fast_install with_gnu_ld enable_libtool_lock enable_largefile enable_threadsafe enable_releasemode enable_tempstore enable_tcl with_tcl enable_editline enable_readline |
︙ | ︙ | |||
1466 1467 1468 1469 1470 1471 1472 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF | | | 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 | # # Report the --help message. # if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF \`configure' configures sqlite 3.41.0 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... To assign environment variables (e.g., CC, CFLAGS...), specify them as VAR=VALUE. See below for descriptions of some of the useful variables. Defaults for the options are specified in brackets. |
︙ | ︙ | |||
1531 1532 1533 1534 1535 1536 1537 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in | | | 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | --build=BUILD configure for building on BUILD [guessed] --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi if test -n "$ac_init_help"; then case $ac_init_help in short | recursive ) echo "Configuration of sqlite 3.41.0:";; esac cat <<\_ACEOF Optional Features: --disable-option-checking ignore unrecognized --enable/--with options --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) --enable-FEATURE[=ARG] include FEATURE [ARG=yes] |
︙ | ︙ | |||
1577 1578 1579 1580 1581 1582 1583 | Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] | < < | 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 | Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-pic try to use only PIC/non-PIC objects [default=use both] --with-gnu-ld assume the C compiler uses GNU ld [default=no] --with-tcl=DIR directory containing tcl configuration (tclConfig.sh) --with-readline-lib specify readline library --with-readline-inc specify readline include paths Some influential environment variables: CC C compiler command |
︙ | ︙ | |||
1661 1662 1663 1664 1665 1666 1667 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF | | | 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 | cd "$ac_pwd" || { ac_status=$?; break; } done fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF sqlite configure 3.41.0 generated by GNU Autoconf 2.69 Copyright (C) 2012 Free Software Foundation, Inc. This configure script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it. _ACEOF exit |
︙ | ︙ | |||
2080 2081 2082 2083 2084 2085 2086 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. | | | 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 | eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno } # ac_fn_c_check_header_mongrel cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. It was created by sqlite $as_me 3.41.0, which was generated by GNU Autoconf 2.69. Invocation command line was $ $0 $@ _ACEOF exec 5>>config.log { |
︙ | ︙ | |||
3938 3939 3940 3941 3942 3943 3944 | { $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 | | | | | 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 | { $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:3941: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 (eval echo "\"\$as_me:3944: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 (eval echo "\"\$as_me:3947: 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 |
︙ | ︙ | |||
5150 5151 5152 5153 5154 5155 5156 | ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. | | | 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 | ;; esac fi rm -rf conftest* ;; *-*-irix6*) # Find out which ABI we are using. echo '#line 5153 "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 |
︙ | ︙ | |||
6675 6676 6677 6678 6679 6680 6681 | # 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:'` | | | | 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 | # 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:6678: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:6682: \$? = $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 |
︙ | ︙ | |||
7014 7015 7016 7017 7018 7019 7020 | # 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:'` | | | | 7010 7011 7012 7013 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 | # 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:7017: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 echo "$as_me:7021: \$? = $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 |
︙ | ︙ | |||
7119 7120 7121 7122 7123 7124 7125 | # (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:'` | | | | 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 | # (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:7122: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7126: \$? = $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 |
︙ | ︙ | |||
7174 7175 7176 7177 7178 7179 7180 | # (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:'` | | | | 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 | # (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:7177: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 echo "$as_me:7181: \$? = $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 |
︙ | ︙ | |||
9554 9555 9556 9557 9558 9559 9560 | 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 | | | 9550 9551 9552 9553 9554 9555 9556 9557 9558 9559 9560 9561 9562 9563 9564 | 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 9557 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> |
︙ | ︙ | |||
9650 9651 9652 9653 9654 9655 9656 | 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 | | | 9646 9647 9648 9649 9650 9651 9652 9653 9654 9655 9656 9657 9658 9659 9660 | 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 9653 "configure" #include "confdefs.h" #if HAVE_DLFCN_H #include <dlfcn.h> #endif #include <stdio.h> |
︙ | ︙ | |||
10391 10392 10393 10394 10395 10396 10397 | VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'` { $as_echo "$as_me:${as_lineno-$LINENO}: Version set to $VERSION" >&5 $as_echo "$as_me: Version set to $VERSION" >&6;} RELEASE=`cat $srcdir/VERSION` { $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5 $as_echo "$as_me: Release set to $RELEASE" >&6;} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 10387 10388 10389 10390 10391 10392 10393 10394 10395 10396 10397 10398 10399 10400 | VERSION=`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'` { $as_echo "$as_me:${as_lineno-$LINENO}: Version set to $VERSION" >&5 $as_echo "$as_me: Version set to $VERSION" >&6;} RELEASE=`cat $srcdir/VERSION` { $as_echo "$as_me:${as_lineno-$LINENO}: Release set to $RELEASE" >&5 $as_echo "$as_me: Release set to $RELEASE" >&6;} ######### # Locate a compiler for the build machine. This compiler should # generate command-line programs that run on the build machine. # if test x"$cross_compiling" = xno; then |
︙ | ︙ | |||
11329 11330 11331 11332 11333 11334 11335 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: release" >&5 $as_echo "release" >&6; } fi ######### # See whether we should use the amalgamation to build | < | 11263 11264 11265 11266 11267 11268 11269 11270 11271 11272 11273 11274 11275 11276 | { $as_echo "$as_me:${as_lineno-$LINENO}: result: release" >&5 $as_echo "release" >&6; } fi ######### # See whether we should use the amalgamation to build # Check whether --enable-amalgamation was given. if test "${enable_amalgamation+set}" = set; then : enableval=$enable_amalgamation; fi if test "${enable_amalgamation}" = "no" ; then USE_AMALGAMATION=0 |
︙ | ︙ | |||
12453 12454 12455 12456 12457 12458 12459 | test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" | | | 12386 12387 12388 12389 12390 12391 12392 12393 12394 12395 12396 12397 12398 12399 12400 | test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # Save the log message, to keep $0 and so on meaningful, and to # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" This file was extended by sqlite $as_me 3.41.0, which was generated by GNU Autoconf 2.69. Invocation command line was CONFIG_FILES = $CONFIG_FILES CONFIG_HEADERS = $CONFIG_HEADERS CONFIG_LINKS = $CONFIG_LINKS CONFIG_COMMANDS = $CONFIG_COMMANDS $ $0 $@ |
︙ | ︙ | |||
12519 12520 12521 12522 12523 12524 12525 | Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ | | | 12452 12453 12454 12455 12456 12457 12458 12459 12460 12461 12462 12463 12464 12465 12466 | Report bugs to the package provider." _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ sqlite config.status 3.41.0 configured by $0, generated by GNU Autoconf 2.69, with options \\"\$ac_cs_config\\" Copyright (C) 2012 Free Software Foundation, Inc. This config.status script is free software; the Free Software Foundation gives unlimited permission to copy, distribute and modify it." |
︙ | ︙ |
Changes to configure.ac.
︙ | ︙ | |||
66 67 68 69 70 71 72 | # # TARGET_EXEEXT # # The filename extension for executables on the # target platform. "" for Unix and ".exe" for windows. # # This configure.in file is easy to reuse on other projects. Just | | | | | 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 | # # TARGET_EXEEXT # # The filename extension for executables on the # target platform. "" for Unix and ".exe" for windows. # # This configure.in file is easy to reuse on other projects. Just # change the argument to AC_INIT(). And disable any features that # you don't need (for example BLT) by erasing or commenting out # the corresponding code. # AC_INIT(sqlite, m4_esyscmd([cat VERSION | tr -d '\n'])) dnl Make sure the local VERSION file matches this configure script sqlite_version_sanity_check=`cat $srcdir/VERSION | tr -d '\n'` if test "$PACKAGE_VERSION" != "$sqlite_version_sanity_check" ; then AC_MSG_ERROR([configure script is out of date: configure \$PACKAGE_VERSION = $PACKAGE_VERSION top level VERSION file = $sqlite_version_sanity_check please regen with autoconf]) fi ######### # Programs needed # AC_PROG_LIBTOOL AC_PROG_INSTALL ######### # Enable large file support (if special flags are necessary) # AC_SYS_LARGEFILE |
︙ | ︙ | |||
153 154 155 156 157 158 159 | VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`] AC_MSG_NOTICE(Version set to $VERSION) AC_SUBST(VERSION) RELEASE=`cat $srcdir/VERSION` AC_MSG_NOTICE(Release set to $RELEASE) AC_SUBST(RELEASE) | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | VERSION=[`cat $srcdir/VERSION | sed 's/^\([0-9]*\.*[0-9]*\).*/\1/'`] AC_MSG_NOTICE(Version set to $VERSION) AC_SUBST(VERSION) RELEASE=`cat $srcdir/VERSION` AC_MSG_NOTICE(Release set to $RELEASE) AC_SUBST(RELEASE) ######### # Locate a compiler for the build machine. This compiler should # generate command-line programs that run on the build machine. # if test x"$cross_compiling" = xno; then BUILD_CC=$CC |
︙ | ︙ | |||
225 226 227 228 229 230 231 | fi AC_SUBST(BUILD_CC) ########## # Do we want to support multithreaded use of sqlite # AC_ARG_ENABLE(threadsafe, | | | | | 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 | fi AC_SUBST(BUILD_CC) ########## # Do we want to support multithreaded use of sqlite # AC_ARG_ENABLE(threadsafe, AC_HELP_STRING([--disable-threadsafe],[Disable mutexing])) AC_MSG_CHECKING([whether to support threadsafe operation]) if test "$enable_threadsafe" = "no"; then SQLITE_THREADSAFE=0 AC_MSG_RESULT([no]) else SQLITE_THREADSAFE=1 AC_MSG_RESULT([yes]) fi AC_SUBST(SQLITE_THREADSAFE) if test "$SQLITE_THREADSAFE" = "1"; then AC_SEARCH_LIBS(pthread_create, pthread) AC_SEARCH_LIBS(pthread_mutexattr_init, pthread) fi ########## # Do we want to support release # AC_ARG_ENABLE(releasemode, AC_HELP_STRING([--enable-releasemode],[Support libtool link to release mode]),,enable_releasemode=no) AC_MSG_CHECKING([whether to support shared library linked as release mode or not]) if test "$enable_releasemode" = "no"; then ALLOWRELEASE="" AC_MSG_RESULT([no]) else ALLOWRELEASE="-release `cat $srcdir/VERSION`" AC_MSG_RESULT([yes]) fi AC_SUBST(ALLOWRELEASE) ########## # Do we want temporary databases in memory # AC_ARG_ENABLE(tempstore, AC_HELP_STRING([--enable-tempstore],[Use an in-ram database for temporary tables (never,no,yes,always)]),,enable_tempstore=no) AC_MSG_CHECKING([whether to use an in-ram database for temporary tables]) case "$enable_tempstore" in never ) TEMP_STORE=0 AC_MSG_RESULT([never]) ;; no ) |
︙ | ︙ | |||
300 301 302 303 304 305 306 | if test "$config_BUILD_EXEEXT" = ".exe"; then CYGWIN=yes AC_MSG_RESULT(yes) else AC_MSG_RESULT(unknown) fi if test "$CYGWIN" != "yes"; then | < < < < < < | < < | 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | if test "$config_BUILD_EXEEXT" = ".exe"; then CYGWIN=yes AC_MSG_RESULT(yes) else AC_MSG_RESULT(unknown) fi if test "$CYGWIN" != "yes"; then AC_CYGWIN fi if test "$CYGWIN" = "yes"; then BUILD_EXEEXT=.exe else BUILD_EXEEXT=$EXEEXT fi if test x"$cross_compiling" = xno; then |
︙ | ︙ | |||
343 344 345 346 347 348 349 | # Figure out all the parameters needed to compile against Tcl. # # This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG # macros in the in the tcl.m4 file of the standard TCL distribution. # Those macros could not be used directly since we have to make some # minor changes to accomodate systems that do not have TCL installed. # | | | | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | # Figure out all the parameters needed to compile against Tcl. # # This code is derived from the SC_PATH_TCLCONFIG and SC_LOAD_TCLCONFIG # macros in the in the tcl.m4 file of the standard TCL distribution. # Those macros could not be used directly since we have to make some # minor changes to accomodate systems that do not have TCL installed. # AC_ARG_ENABLE(tcl, AC_HELP_STRING([--disable-tcl],[do not build TCL extension]), [use_tcl=$enableval],[use_tcl=yes]) if test "${use_tcl}" = "yes" ; then AC_ARG_WITH(tcl, AC_HELP_STRING([--with-tcl=DIR],[directory containing tcl configuration (tclConfig.sh)]), with_tclconfig=${withval}) AC_MSG_CHECKING([for Tcl configuration]) AC_CACHE_VAL(ac_cv_c_tclconfig,[ # First check to see if --with-tcl was specified. if test x"${with_tclconfig}" != x ; then if test -f "${with_tclconfig}/tclConfig.sh" ; then ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` else |
︙ | ︙ | |||
528 529 530 531 532 533 534 | # that use "readline()" library. # TARGET_READLINE_LIBS="" TARGET_READLINE_INC="" TARGET_HAVE_READLINE=0 TARGET_HAVE_EDITLINE=0 AC_ARG_ENABLE([editline], | | | | | | 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | # 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"]) if test "x$with_readline_lib" = xauto; then save_LIBS="$LIBS" LIBS="" AC_SEARCH_LIBS(tgetent, [readline ncurses curses termcap], [term_LIBS="$LIBS"], [term_LIBS=""]) AC_CHECK_LIB([readline], [readline], [TARGET_READLINE_LIBS="-lreadline"], [found="no"]) TARGET_READLINE_LIBS="$TARGET_READLINE_LIBS $term_LIBS" LIBS="$save_LIBS" else TARGET_READLINE_LIBS="$with_readline_lib" fi AC_ARG_WITH([readline-inc], [AC_HELP_STRING([--with-readline-inc],[specify readline include paths])], [with_readline_inc=$withval], [with_readline_inc="auto"]) if test "x$with_readline_inc" = xauto; then AC_CHECK_HEADER(readline.h, [found="yes"], [ found="no" if test "$cross_compiling" != yes; then for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do |
︙ | ︙ | |||
608 609 610 611 612 613 614 | # Figure out what C libraries are required to compile programs # that use "fdatasync()" function. # AC_SEARCH_LIBS(fdatasync, [rt]) ######### # check for debug enabled | | < | | | | | | | | | | | | | | | 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 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 | # Figure out what C libraries are required to compile programs # that use "fdatasync()" function. # AC_SEARCH_LIBS(fdatasync, [rt]) ######### # check for debug enabled AC_ARG_ENABLE(debug, AC_HELP_STRING([--enable-debug],[enable debugging & verbose explain])) AC_MSG_CHECKING([build type]) if test "${enable_debug}" = "yes" ; then TARGET_DEBUG="-DSQLITE_DEBUG=1 -DSQLITE_ENABLE_SELECTTRACE -DSQLITE_ENABLE_WHERETRACE -O0" AC_MSG_RESULT([debug]) else TARGET_DEBUG="-DNDEBUG" AC_MSG_RESULT([release]) fi AC_SUBST(TARGET_DEBUG) ######### # See whether we should use the amalgamation to build AC_ARG_ENABLE(amalgamation, AC_HELP_STRING([--disable-amalgamation], [Disable the amalgamation and instead build all files separately])) if test "${enable_amalgamation}" = "no" ; then USE_AMALGAMATION=0 fi AC_SUBST(USE_AMALGAMATION) ######### # Look for zlib. Only needed by extensions and by the sqlite3.exe shell AC_CHECK_HEADERS(zlib.h) AC_SEARCH_LIBS(deflate, z, [HAVE_ZLIB="-DSQLITE_HAVE_ZLIB=1"], [HAVE_ZLIB=""]) AC_SUBST(HAVE_ZLIB) ######### # See whether we should allow loadable extensions AC_ARG_ENABLE(load-extension, AC_HELP_STRING([--disable-load-extension], [Disable loading of external extensions]),,[enable_load_extension=yes]) if test "${enable_load_extension}" = "yes" ; then OPT_FEATURE_FLAGS="" AC_SEARCH_LIBS(dlopen, dl) else OPT_FEATURE_FLAGS="-DSQLITE_OMIT_LOAD_EXTENSION=1" fi ########## # Do we want to support math functions # AC_ARG_ENABLE(math, AC_HELP_STRING([--disable-math],[Disable math functions])) AC_MSG_CHECKING([whether to support math functions]) if test "$enable_math" = "no"; then AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MATH_FUNCTIONS" AC_SEARCH_LIBS(ceil, m) fi ########## # Do we want to support JSON functions # AC_ARG_ENABLE(json, AC_HELP_STRING([--disable-json],[Disable JSON functions])) AC_MSG_CHECKING([whether to support JSON functions]) if test "$enable_json" = "no"; then AC_MSG_RESULT([no]) OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_OMIT_JSON" else AC_MSG_RESULT([yes]) fi ######## # The --enable-all argument is short-hand to enable # multiple extensions. AC_ARG_ENABLE(all, AC_HELP_STRING([--enable-all], [Enable FTS4, FTS5, Geopoly, RTree, Sessions])) ########## # Do we want to support memsys3 and/or memsys5 # AC_ARG_ENABLE(memsys5, AC_HELP_STRING([--enable-memsys5],[Enable MEMSYS5])) AC_MSG_CHECKING([whether to support MEMSYS5]) if test "${enable_memsys5}" = "yes"; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS5" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi AC_ARG_ENABLE(memsys3, AC_HELP_STRING([--enable-memsys3],[Enable MEMSYS3])) AC_MSG_CHECKING([whether to support MEMSYS3]) if test "${enable_memsys3}" = "yes" -a "${enable_memsys5}" = "no"; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_MEMSYS3" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ######### # See whether we should enable Full Text Search extensions AC_ARG_ENABLE(fts3, AC_HELP_STRING([--enable-fts3], [Enable the FTS3 extension])) AC_MSG_CHECKING([whether to support FTS3]) if test "${enable_fts3}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS3" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi AC_ARG_ENABLE(fts4, AC_HELP_STRING([--enable-fts4], [Enable the FTS4 extension])) AC_MSG_CHECKING([whether to support FTS4]) if test "${enable_fts4}" = "yes" -o "${enable_all}" = "yes" ; then AC_MSG_RESULT([yes]) OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS4" AC_SEARCH_LIBS([log],[m]) else AC_MSG_RESULT([no]) fi AC_ARG_ENABLE(fts5, AC_HELP_STRING([--enable-fts5], [Enable the FTS5 extension])) AC_MSG_CHECKING([whether to support FTS5]) if test "${enable_fts5}" = "yes" -o "${enable_all}" = "yes" ; then AC_MSG_RESULT([yes]) OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_FTS5" AC_SEARCH_LIBS([log],[m]) else AC_MSG_RESULT([no]) fi ######### # See whether we should enable the LIMIT clause on UPDATE and DELETE # statements. AC_ARG_ENABLE(update-limit, AC_HELP_STRING([--enable-update-limit], [Enable the UPDATE/DELETE LIMIT clause])) AC_MSG_CHECKING([whether to support LIMIT on UPDATE and DELETE statements]) if test "${enable_update_limit}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ######### # See whether we should enable GEOPOLY AC_ARG_ENABLE(geopoly, AC_HELP_STRING([--enable-geopoly], [Enable the GEOPOLY extension]), [enable_geopoly=yes],[enable_geopoly=no]) AC_MSG_CHECKING([whether to support GEOPOLY]) if test "${enable_geopoly}" = "yes" -o "${enable_all}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_GEOPOLY" enable_rtree=yes AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ######### # See whether we should enable RTREE AC_ARG_ENABLE(rtree, AC_HELP_STRING([--enable-rtree], [Enable the RTREE extension])) AC_MSG_CHECKING([whether to support RTREE]) if test "${enable_rtree}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_RTREE" AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) fi ######### # See whether we should enable the SESSION extension AC_ARG_ENABLE(session, AC_HELP_STRING([--enable-session], [Enable the SESSION extension])) AC_MSG_CHECKING([whether to support SESSION]) if test "${enable_session}" = "yes" -o "${enable_all}" = "yes" ; then OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_SESSION" OPT_FEATURE_FLAGS="${OPT_FEATURE_FLAGS} -DSQLITE_ENABLE_PREUPDATE_HOOK" AC_MSG_RESULT([yes]) else |
︙ | ︙ | |||
838 839 840 841 842 843 844 | esac done BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS ######### # See whether we should use GCOV | | | 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 | esac done BUILD_CFLAGS=$ac_temp_BUILD_CFLAGS ######### # See whether we should use GCOV AC_ARG_ENABLE(gcov, AC_HELP_STRING([--enable-gcov], [Enable coverage testing using gcov])) if test "${use_gcov}" = "yes" ; then USE_GCOV=1 else USE_GCOV=0 fi AC_SUBST(USE_GCOV) |
︙ | ︙ | |||
867 868 869 870 871 872 873 | # Output the config header AC_CONFIG_HEADERS(sqlite_cfg.h) ######### # Generate the output files. # AC_SUBST(BUILD_CFLAGS) | | < | 808 809 810 811 812 813 814 815 816 817 818 | # Output the config header AC_CONFIG_HEADERS(sqlite_cfg.h) ######### # Generate the output files. # AC_SUBST(BUILD_CFLAGS) AC_OUTPUT([ Makefile sqlite3.pc ]) |
Changes to ext/fts3/fts3_write.c.
︙ | ︙ | |||
2663 2664 2665 2666 2667 2668 2669 | ** trying to resize the buffer, return SQLITE_NOMEM. */ static int fts3MsrBufferData( Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ char *pList, i64 nList ){ | | | | < < | 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 | ** trying to resize the buffer, return SQLITE_NOMEM. */ static int fts3MsrBufferData( Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ char *pList, i64 nList ){ if( nList>pMsr->nBuffer ){ char *pNew; pMsr->nBuffer = nList*2; pNew = (char *)sqlite3_realloc64(pMsr->aBuffer, pMsr->nBuffer); if( !pNew ) return SQLITE_NOMEM; pMsr->aBuffer = pNew; } assert( nList>0 ); memcpy(pMsr->aBuffer, pList, nList); return SQLITE_OK; } int sqlite3Fts3MsrIncrNext( Fts3Table *p, /* Virtual table handle */ Fts3MultiSegReader *pMsr, /* Multi-segment-reader handle */ sqlite3_int64 *piDocid, /* OUT: Docid value */ |
︙ | ︙ |
Changes to ext/fts5/fts5Int.h.
︙ | ︙ | |||
195 196 197 198 199 200 201 | char *zContentExprlist; Fts5Tokenizer *pTok; fts5_tokenizer *pTokApi; int bLock; /* True when table is preparing statement */ int ePattern; /* FTS_PATTERN_XXX constant */ /* Values loaded from the %_config table */ | < < | < < | < | 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 | char *zContentExprlist; Fts5Tokenizer *pTok; fts5_tokenizer *pTokApi; int bLock; /* True when table is preparing statement */ int ePattern; /* FTS_PATTERN_XXX constant */ /* Values loaded from the %_config table */ int iCookie; /* Incremented when %_config is modified */ int pgsz; /* Approximate page size used in %_data */ int nAutomerge; /* 'automerge' setting */ int nCrisisMerge; /* Maximum allowed segments per level */ int nUsermerge; /* 'usermerge' setting */ int nHashSize; /* Bytes of memory for in-memory hash */ char *zRank; /* Name of rank function */ char *zRankArgs; /* Arguments to rank function */ /* If non-NULL, points to sqlite3_vtab.base.zErrmsg. Often NULL. */ char **pzErrmsg; #ifdef SQLITE_DEBUG int bPrefixIndex; /* True to use prefix-indexes */ #endif }; /* Current expected value of %_config table 'version' field */ #define FTS5_CURRENT_VERSION 4 #define FTS5_CONTENT_NORMAL 0 #define FTS5_CONTENT_NONE 1 #define FTS5_CONTENT_EXTERNAL 2 #define FTS5_DETAIL_FULL 0 #define FTS5_DETAIL_NONE 1 |
︙ | ︙ | |||
384 385 386 387 388 389 390 | #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ /* The following are used internally by the fts5_index.c module. They are ** defined here only to make it easier to avoid clashes with the flags ** above. */ #define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 #define FTS5INDEX_QUERY_NOOUTPUT 0x0020 | < | 379 380 381 382 383 384 385 386 387 388 389 390 391 392 | #define FTS5INDEX_QUERY_SCAN 0x0008 /* Scan query (fts5vocab) */ /* The following are used internally by the fts5_index.c module. They are ** defined here only to make it easier to avoid clashes with the flags ** above. */ #define FTS5INDEX_QUERY_SKIPEMPTY 0x0010 #define FTS5INDEX_QUERY_NOOUTPUT 0x0020 /* ** Create/destroy an Fts5Index object. */ int sqlite3Fts5IndexOpen(Fts5Config *pConfig, int bCreate, Fts5Index**, char**); int sqlite3Fts5IndexClose(Fts5Index *p); |
︙ | ︙ | |||
539 540 541 542 543 544 545 | ** Interface to code in fts5_varint.c. */ int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v); int sqlite3Fts5GetVarintLen(u32 iVal); u8 sqlite3Fts5GetVarint(const unsigned char*, u64*); int sqlite3Fts5PutVarint(unsigned char *p, u64 v); | | | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 | ** Interface to code in fts5_varint.c. */ int sqlite3Fts5GetVarint32(const unsigned char *p, u32 *v); int sqlite3Fts5GetVarintLen(u32 iVal); u8 sqlite3Fts5GetVarint(const unsigned char*, u64*); int sqlite3Fts5PutVarint(unsigned char *p, u64 v); #define fts5GetVarint32(a,b) sqlite3Fts5GetVarint32(a,(u32*)&b) #define fts5GetVarint sqlite3Fts5GetVarint #define fts5FastGetVarint32(a, iOff, nVal) { \ nVal = (a)[iOff++]; \ if( nVal & 0x80 ){ \ iOff--; \ iOff += fts5GetVarint32(&(a)[iOff], nVal); \ |
︙ | ︙ |
Changes to ext/fts5/fts5_aux.c.
︙ | ︙ | |||
159 160 161 162 163 164 165 | int iPos; UNUSED_PARAM2(pToken, nToken); if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK; iPos = p->iPos++; | | | | | 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 | int iPos; UNUSED_PARAM2(pToken, nToken); if( tflags & FTS5_TOKEN_COLOCATED ) return SQLITE_OK; iPos = p->iPos++; if( p->iRangeEnd>0 ){ if( iPos<p->iRangeStart || iPos>p->iRangeEnd ) return SQLITE_OK; if( p->iRangeStart && iPos==p->iRangeStart ) p->iOff = iStartOff; } if( iPos==p->iter.iStart ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iStartOff - p->iOff); fts5HighlightAppend(&rc, p, p->zOpen, -1); p->iOff = iStartOff; } if( iPos==p->iter.iEnd ){ if( p->iRangeEnd && p->iter.iStart<p->iRangeStart ){ fts5HighlightAppend(&rc, p, p->zOpen, -1); } fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); fts5HighlightAppend(&rc, p, p->zClose, -1); p->iOff = iEndOff; if( rc==SQLITE_OK ){ rc = fts5CInstIterNext(&p->iter); } } if( p->iRangeEnd>0 && iPos==p->iRangeEnd ){ fts5HighlightAppend(&rc, p, &p->zIn[p->iOff], iEndOff - p->iOff); p->iOff = iEndOff; if( iPos>=p->iter.iStart && iPos<p->iter.iEnd ){ fts5HighlightAppend(&rc, p, p->zClose, -1); } } |
︙ | ︙ | |||
217 218 219 220 221 222 223 | return; } iCol = sqlite3_value_int(apVal[0]); memset(&ctx, 0, sizeof(HighlightContext)); ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); | < | 217 218 219 220 221 222 223 224 225 226 227 228 229 230 | return; } iCol = sqlite3_value_int(apVal[0]); memset(&ctx, 0, sizeof(HighlightContext)); ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]); ctx.zClose = (const char*)sqlite3_value_text(apVal[2]); rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn); if( ctx.zIn ){ if( rc==SQLITE_OK ){ rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter); } |
︙ | ︙ | |||
403 404 405 406 407 408 409 | } nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); ctx.zOpen = fts5ValueToText(apVal[1]); ctx.zClose = fts5ValueToText(apVal[2]); | < | 402 403 404 405 406 407 408 409 410 411 412 413 414 415 | } nCol = pApi->xColumnCount(pFts); memset(&ctx, 0, sizeof(HighlightContext)); iCol = sqlite3_value_int(apVal[0]); ctx.zOpen = fts5ValueToText(apVal[1]); ctx.zClose = fts5ValueToText(apVal[2]); zEllips = fts5ValueToText(apVal[3]); nToken = sqlite3_value_int(apVal[4]); iBestCol = (iCol>=0 ? iCol : 0); nPhrase = pApi->xPhraseCount(pFts); aSeen = sqlite3_malloc(nPhrase); if( aSeen==0 ){ |
︙ | ︙ |
Changes to ext/fts5/fts5_config.c.
︙ | ︙ | |||
546 547 548 549 550 551 552 | pRet->bPrefixIndex = 1; #endif if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){ *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName); rc = SQLITE_ERROR; } | < | 546 547 548 549 550 551 552 553 554 555 556 557 558 559 | pRet->bPrefixIndex = 1; #endif if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){ *pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName); rc = SQLITE_ERROR; } for(i=3; rc==SQLITE_OK && i<nArg; i++){ const char *zOrig = azArg[i]; const char *z; char *zOne = 0; char *zTwo = 0; int bOption = 0; int bMustBeCol = 0; |
︙ | ︙ | |||
900 901 902 903 904 905 906 | sqlite3_free(pConfig->zRankArgs); pConfig->zRank = zRank; pConfig->zRankArgs = zRankArgs; }else if( rc==SQLITE_ERROR ){ rc = SQLITE_OK; *pbBadkey = 1; } | < < < < < < < < < < < < | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | sqlite3_free(pConfig->zRankArgs); pConfig->zRank = zRank; pConfig->zRankArgs = zRankArgs; }else if( rc==SQLITE_ERROR ){ rc = SQLITE_OK; *pbBadkey = 1; } }else{ *pbBadkey = 1; } return rc; } /* |
︙ | ︙ | |||
956 957 958 959 960 961 962 | int bDummy = 0; sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, &bDummy); } } rc = sqlite3_finalize(p); } | < | < < | | | < < | 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 | int bDummy = 0; sqlite3Fts5ConfigSetValue(pConfig, zK, pVal, &bDummy); } } rc = sqlite3_finalize(p); } if( rc==SQLITE_OK && iVersion!=FTS5_CURRENT_VERSION ){ rc = SQLITE_ERROR; if( pConfig->pzErrmsg ){ assert( 0==*pConfig->pzErrmsg ); *pConfig->pzErrmsg = sqlite3_mprintf( "invalid fts5 file format (found %d, expected %d) - run 'rebuild'", iVersion, FTS5_CURRENT_VERSION ); } } if( rc==SQLITE_OK ){ pConfig->iCookie = iCookie; } return rc; } |
Changes to ext/fts5/fts5_expr.c.
︙ | ︙ | |||
285 286 287 288 289 290 291 | } sqlite3_free(sParse.apPhrase); *pzErr = sParse.zErr; return sParse.rc; } | < < < < < < < < < < < < < | 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | } sqlite3_free(sParse.apPhrase); *pzErr = sParse.zErr; return sParse.rc; } /* ** This function is only called when using the special 'trigram' tokenizer. ** Argument zText contains the text of a LIKE or GLOB pattern matched ** against column iCol. This function creates and compiles an FTS5 MATCH ** expression that will match a superset of the rows matched by the LIKE or ** GLOB. If successful, SQLITE_OK is returned. Otherwise, an SQLite error ** code. |
︙ | ︙ | |||
335 336 337 338 339 340 341 | aSpec[2] = '['; } while( i<=nText ){ if( i==nText || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2] ){ | | < | 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | aSpec[2] = '['; } while( i<=nText ){ if( i==nText || zText[i]==aSpec[0] || zText[i]==aSpec[1] || zText[i]==aSpec[2] ){ if( i-iFirst>=3 ){ int jj; zExpr[iOut++] = '"'; for(jj=iFirst; jj<i; jj++){ zExpr[iOut++] = zText[jj]; if( zText[jj]=='"' ) zExpr[iOut++] = '"'; } zExpr[iOut++] = '"'; |
︙ | ︙ | |||
403 404 405 406 407 408 409 | } } int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ Fts5Parse sParse; memset(&sParse, 0, sizeof(sParse)); | | | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | } } int sqlite3Fts5ExprAnd(Fts5Expr **pp1, Fts5Expr *p2){ Fts5Parse sParse; memset(&sParse, 0, sizeof(sParse)); if( *pp1 ){ Fts5Expr *p1 = *pp1; int nPhrase = p1->nPhrase + p2->nPhrase; p1->pRoot = sqlite3Fts5ParseNode(&sParse, FTS5_AND, p1->pRoot, p2->pRoot,0); p2->pRoot = 0; if( sParse.rc==SQLITE_OK ){ |
︙ | ︙ | |||
428 429 430 431 432 433 434 | } p1->nPhrase = nPhrase; p1->apExprPhrase = ap; } } sqlite3_free(p2->apExprPhrase); sqlite3_free(p2); | | | 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 | } p1->nPhrase = nPhrase; p1->apExprPhrase = ap; } } sqlite3_free(p2->apExprPhrase); sqlite3_free(p2); }else{ *pp1 = p2; } return sParse.rc; } /* |
︙ | ︙ |
Changes to ext/fts5/fts5_index.c.
︙ | ︙ | |||
298 299 300 301 302 303 304 | sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; int nRead; /* Total number of blocks read */ | < < | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | sqlite3_stmt *pWriter; /* "INSERT ... %_data VALUES(?,?)" */ sqlite3_stmt *pDeleter; /* "DELETE FROM %_data ... id>=? AND id<=?" */ sqlite3_stmt *pIdxWriter; /* "INSERT ... %_idx VALUES(?,?,?,?)" */ sqlite3_stmt *pIdxDeleter; /* "DELETE FROM %_idx WHERE segid=?" */ sqlite3_stmt *pIdxSelect; int nRead; /* Total number of blocks read */ sqlite3_stmt *pDataVersion; i64 iStructVersion; /* data_version when pStruct read */ Fts5Structure *pStruct; /* Current db structure (or NULL) */ }; struct Fts5DoclistIter { u8 *aEof; /* Pointer to 1 byte past end of doclist */ |
︙ | ︙ | |||
392 393 394 395 396 397 398 399 400 401 402 403 404 405 | ** ** iLeafPgno: ** Current leaf page number within segment. ** ** iLeafOffset: ** Byte offset within the current leaf that is the first byte of the ** position list data (one byte passed the position-list size field). ** ** pLeaf: ** Buffer containing current leaf page data. Set to NULL at EOF. ** ** iTermLeafPgno, iTermLeafOffset: ** Leaf page number containing the last term read from the segment. And ** the offset immediately following the term data. | > > > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 | ** ** iLeafPgno: ** Current leaf page number within segment. ** ** iLeafOffset: ** Byte offset within the current leaf that is the first byte of the ** position list data (one byte passed the position-list size field). ** rowid field of the current entry. Usually this is the size field of the ** position list data. The exception is if the rowid for the current entry ** is the last thing on the leaf page. ** ** pLeaf: ** Buffer containing current leaf page data. Set to NULL at EOF. ** ** iTermLeafPgno, iTermLeafOffset: ** Leaf page number containing the last term read from the segment. And ** the offset immediately following the term data. |
︙ | ︙ | |||
950 951 952 953 954 955 956 | pLvl->nSeg = nTotal; for(iSeg=0; iSeg<nTotal; iSeg++){ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; if( i>=nData ){ rc = FTS5_CORRUPT; break; } | < | 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | pLvl->nSeg = nTotal; for(iSeg=0; iSeg<nTotal; iSeg++){ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; if( i>=nData ){ rc = FTS5_CORRUPT; break; } i += fts5GetVarint32(&pData[i], pSeg->iSegid); i += fts5GetVarint32(&pData[i], pSeg->pgnoFirst); i += fts5GetVarint32(&pData[i], pSeg->pgnoLast); if( pSeg->pgnoLast<pSeg->pgnoFirst ){ rc = FTS5_CORRUPT; break; } |
︙ | ︙ | |||
981 982 983 984 985 986 987 | /* ** Add a level to the Fts5Structure.aLevel[] array of structure object ** (*ppStruct). */ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ fts5StructureMakeWritable(pRc, ppStruct); | < | 981 982 983 984 985 986 987 988 989 990 991 992 993 994 | /* ** Add a level to the Fts5Structure.aLevel[] array of structure object ** (*ppStruct). */ static void fts5StructureAddLevel(int *pRc, Fts5Structure **ppStruct){ fts5StructureMakeWritable(pRc, ppStruct); if( *pRc==SQLITE_OK ){ Fts5Structure *pStruct = *ppStruct; int nLevel = pStruct->nLevel; sqlite3_int64 nByte = ( sizeof(Fts5Structure) + /* Main structure */ sizeof(Fts5StructureLevel) * (nLevel+1) /* aLevel[] array */ ); |
︙ | ︙ | |||
1440 1441 1442 1443 1444 1445 1446 | int iOff = pLvl->iOff; assert( pLvl->bEof==0 ); if( iOff<=pLvl->iFirstOff ){ pLvl->bEof = 1; }else{ u8 *a = pLvl->pData->p; | | | < | | | > > > > > > > > | > > > > | | < | > > > | > > > > > | | > | < | < | 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 | int iOff = pLvl->iOff; assert( pLvl->bEof==0 ); if( iOff<=pLvl->iFirstOff ){ pLvl->bEof = 1; }else{ u8 *a = pLvl->pData->p; i64 iVal; int iLimit; int ii; int nZero = 0; /* Currently iOff points to the first byte of a varint. This block ** decrements iOff until it points to the first byte of the previous ** varint. Taking care not to read any memory locations that occur ** before the buffer in memory. */ iLimit = (iOff>9 ? iOff-9 : 0); for(iOff--; iOff>iLimit; iOff--){ if( (a[iOff-1] & 0x80)==0 ) break; } fts5GetVarint(&a[iOff], (u64*)&iVal); pLvl->iRowid -= iVal; pLvl->iLeafPgno--; /* Skip backwards past any 0x00 varints. */ for(ii=iOff-1; ii>=pLvl->iFirstOff && a[ii]==0x00; ii--){ nZero++; } if( ii>=pLvl->iFirstOff && (a[ii] & 0x80) ){ /* The byte immediately before the last 0x00 byte has the 0x80 bit ** set. So the last 0x00 is only a varint 0 if there are 8 more 0x80 ** bytes before a[ii]. */ int bZero = 0; /* True if last 0x00 counts */ if( (ii-8)>=pLvl->iFirstOff ){ int j; for(j=1; j<=8 && (a[ii-j] & 0x80); j++); bZero = (j>8); } if( bZero==0 ) nZero--; } pLvl->iLeafPgno -= nZero; pLvl->iOff = iOff - nZero; } return pLvl->bEof; } static int fts5DlidxIterPrevR(Fts5Index *p, Fts5DlidxIter *pIter, int iLvl){ Fts5DlidxLvl *pLvl = &pIter->aLvl[iLvl]; |
︙ | ︙ | |||
1654 1655 1656 1657 1658 1659 1660 | } static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ i64 iOff = pIter->iLeafOffset; ASSERT_SZLEAF_OK(pIter->pLeaf); | | | 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 | } static void fts5SegIterLoadRowid(Fts5Index *p, Fts5SegIter *pIter){ u8 *a = pIter->pLeaf->p; /* Buffer to read data from */ i64 iOff = pIter->iLeafOffset; ASSERT_SZLEAF_OK(pIter->pLeaf); if( iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( pIter->pLeaf==0 ){ if( p->rc==SQLITE_OK ) p->rc = FTS5_CORRUPT; return; } iOff = 4; a = pIter->pLeaf->p; |
︙ | ︙ | |||
1753 1754 1755 1756 1757 1758 1759 | } if( p->rc==SQLITE_OK ){ memset(pIter, 0, sizeof(*pIter)); fts5SegIterSetNext(p, pIter); pIter->pSeg = pSeg; pIter->iLeafPgno = pSeg->pgnoFirst-1; | < | < | | 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 | } if( p->rc==SQLITE_OK ){ memset(pIter, 0, sizeof(*pIter)); fts5SegIterSetNext(p, pIter); pIter->pSeg = pSeg; pIter->iLeafPgno = pSeg->pgnoFirst-1; fts5SegIterNextPage(p, pIter); } if( p->rc==SQLITE_OK ){ pIter->iLeafOffset = 4; assert( pIter->pLeaf!=0 ); assert_nc( pIter->pLeaf->nn>4 ); assert_nc( fts5LeafFirstTermOff(pIter->pLeaf)==4 ); pIter->iPgidxOff = pIter->pLeaf->szLeaf+1; fts5SegIterLoadTerm(p, pIter, 0); fts5SegIterLoadNPos(p, pIter); |
︙ | ︙ | |||
1952 1953 1954 1955 1956 1957 1958 | assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 ); assert( p->pConfig->eDetail==FTS5_DETAIL_NONE ); ASSERT_SZLEAF_OK(pIter->pLeaf); iOff = pIter->iLeafOffset; /* Next entry is on the next page */ | | | 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 | assert( (pIter->flags & FTS5_SEGITER_REVERSE)==0 ); assert( p->pConfig->eDetail==FTS5_DETAIL_NONE ); ASSERT_SZLEAF_OK(pIter->pLeaf); iOff = pIter->iLeafOffset; /* Next entry is on the next page */ if( pIter->pSeg && iOff>=pIter->pLeaf->szLeaf ){ fts5SegIterNextPage(p, pIter); if( p->rc || pIter->pLeaf==0 ) return; pIter->iRowid = 0; iOff = 4; } if( iOff<pIter->iEndofDoclist ){ |
︙ | ︙ | |||
2145 2146 2147 2148 2149 2150 2151 | ** the doclist. */ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ Fts5DlidxIter *pDlidx = pIter->pDlidx; Fts5Data *pLast = 0; int pgnoLast = 0; | | | 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 | ** the doclist. */ static void fts5SegIterReverse(Fts5Index *p, Fts5SegIter *pIter){ Fts5DlidxIter *pDlidx = pIter->pDlidx; Fts5Data *pLast = 0; int pgnoLast = 0; if( pDlidx ){ int iSegid = pIter->pSeg->iSegid; pgnoLast = fts5DlidxIterPgno(pDlidx); pLast = fts5LeafRead(p, FTS5_SEGMENT_ROWID(iSegid, pgnoLast)); }else{ Fts5Data *pLeaf = pIter->pLeaf; /* Current leaf data */ /* Currently, Fts5SegIter.iLeafOffset points to the first byte of |
︙ | ︙ | |||
2706 2707 2708 2709 2710 2711 2712 | pRes->iFirst = (u16)iRes; return 0; } /* ** Move the seg-iter so that it points to the first rowid on page iLeafPgno. | | < > > | < < < < | | > > | | | | | | < < | 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 | pRes->iFirst = (u16)iRes; return 0; } /* ** Move the seg-iter so that it points to the first rowid on page iLeafPgno. ** It is an error if leaf iLeafPgno does not exist or contains no rowids. */ static void fts5SegIterGotoPage( Fts5Index *p, /* FTS5 backend object */ Fts5SegIter *pIter, /* Iterator to advance */ int iLeafPgno ){ assert( iLeafPgno>pIter->iLeafPgno ); if( iLeafPgno>pIter->pSeg->pgnoLast ){ p->rc = FTS5_CORRUPT; }else{ fts5DataRelease(pIter->pNextLeaf); pIter->pNextLeaf = 0; pIter->iLeafPgno = iLeafPgno-1; fts5SegIterNextPage(p, pIter); assert( p->rc!=SQLITE_OK || pIter->iLeafPgno==iLeafPgno ); if( p->rc==SQLITE_OK && ALWAYS(pIter->pLeaf!=0) ){ int iOff; u8 *a = pIter->pLeaf->p; int n = pIter->pLeaf->szLeaf; iOff = fts5LeafFirstRowidOff(pIter->pLeaf); if( iOff<4 || iOff>=n ){ p->rc = FTS5_CORRUPT; }else{ iOff += fts5GetVarint(&a[iOff], (u64*)&pIter->iRowid); pIter->iLeafOffset = iOff; fts5SegIterLoadNPos(p, pIter); } } } } /* ** Advance the iterator passed as the second argument until it is at or |
︙ | ︙ | |||
3453 3454 3455 3456 3457 3458 3459 | assert( (pTerm==0 && nTerm==0) || iLevel<0 ); /* Allocate space for the new multi-seg-iterator. */ if( p->rc==SQLITE_OK ){ if( iLevel<0 ){ assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); nSeg = pStruct->nSegment; | | | | 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 | assert( (pTerm==0 && nTerm==0) || iLevel<0 ); /* Allocate space for the new multi-seg-iterator. */ if( p->rc==SQLITE_OK ){ if( iLevel<0 ){ assert( pStruct->nSegment==fts5StructureCountSegments(pStruct) ); nSeg = pStruct->nSegment; nSeg += (p->pHash ? 1 : 0); }else{ nSeg = MIN(pStruct->aLevel[iLevel].nSeg, nSegment); } } *ppOut = pNew = fts5MultiIterAlloc(p, nSeg); if( pNew==0 ){ assert( p->rc!=SQLITE_OK ); goto fts5MultiIterNew_post_check; } pNew->bRev = (0!=(flags & FTS5INDEX_QUERY_DESC)); pNew->bSkipEmpty = (0!=(flags & FTS5INDEX_QUERY_SKIPEMPTY)); pNew->pColset = pColset; if( (flags & FTS5INDEX_QUERY_NOOUTPUT)==0 ){ fts5IterSetOutputCb(&p->rc, pNew); } /* Initialize each of the component segment iterators. */ if( p->rc==SQLITE_OK ){ if( iLevel<0 ){ Fts5StructureLevel *pEnd = &pStruct->aLevel[pStruct->nLevel]; if( p->pHash ){ /* Add a segment iterator for the current contents of the hash table. */ Fts5SegIter *pIter = &pNew->aSeg[iIter++]; fts5SegIterHashInit(p, pTerm, nTerm, flags, pIter); } for(pLvl=&pStruct->aLevel[0]; pLvl<pEnd; pLvl++){ for(iSeg=pLvl->nSeg-1; iSeg>=0; iSeg--){ Fts5StructureSegment *pSeg = &pLvl->aSeg[iSeg]; |
︙ | ︙ | |||
4229 4230 4231 4232 4233 4234 4235 | p->rc = FTS5_CORRUPT; }else{ fts5BufferZero(&buf); fts5BufferGrow(&p->rc, &buf, pData->nn); fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr); fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n); fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p); | | | 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 | p->rc = FTS5_CORRUPT; }else{ fts5BufferZero(&buf); fts5BufferGrow(&p->rc, &buf, pData->nn); fts5BufferAppendBlob(&p->rc, &buf, sizeof(aHdr), aHdr); fts5BufferAppendVarint(&p->rc, &buf, pSeg->term.n); fts5BufferAppendBlob(&p->rc, &buf, pSeg->term.n, pSeg->term.p); fts5BufferAppendBlob(&p->rc, &buf, pData->szLeaf-iOff,&pData->p[iOff]); if( p->rc==SQLITE_OK ){ /* Set the szLeaf field */ fts5PutU16(&buf.p[2], (u16)buf.n); } /* Set up the new page-index array */ fts5BufferAppendVarint(&p->rc, &buf, 4); |
︙ | ︙ | |||
4507 4508 4509 4510 4511 4512 4513 | static void fts5IndexCrisismerge( Fts5Index *p, /* FTS5 backend object */ Fts5Structure **ppStruct /* IN/OUT: Current structure of index */ ){ const int nCrisis = p->pConfig->nCrisisMerge; Fts5Structure *pStruct = *ppStruct; | < | > > | | | | | | | < | 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 | static void fts5IndexCrisismerge( Fts5Index *p, /* FTS5 backend object */ Fts5Structure **ppStruct /* IN/OUT: Current structure of index */ ){ const int nCrisis = p->pConfig->nCrisisMerge; Fts5Structure *pStruct = *ppStruct; int iLvl = 0; assert( p->rc!=SQLITE_OK || pStruct->nLevel>0 ); while( p->rc==SQLITE_OK && pStruct->aLevel[iLvl].nSeg>=nCrisis ){ fts5IndexMergeLevel(p, &pStruct, iLvl, 0); assert( p->rc!=SQLITE_OK || pStruct->nLevel>(iLvl+1) ); fts5StructurePromote(p, iLvl+1, pStruct); iLvl++; } *ppStruct = pStruct; } static int fts5IndexReturn(Fts5Index *p){ int rc = p->rc; p->rc = SQLITE_OK; return rc; } |
︙ | ︙ | |||
4549 4550 4551 4552 4553 4554 4555 | int i = fts5GetVarint32(&aBuf[ret], dummy); if( (ret + i) > nMax ) break; ret += i; } } return ret; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 | int i = fts5GetVarint32(&aBuf[ret], dummy); if( (ret + i) > nMax ) break; ret += i; } } return ret; } /* ** Flush the contents of in-memory hash table iHash to a new level-0 ** segment on disk. Also update the corresponding structure record. ** ** If an error occurs, set the Fts5Index.rc error code. If an error has ** already occurred, this function is a no-op. |
︙ | ︙ | |||
4979 4980 4981 4982 4983 4984 4985 | pStruct = fts5StructureRead(p); iSegid = fts5AllocateSegid(p, pStruct); fts5StructureInvalidate(p); if( iSegid ){ const int pgsz = p->pConfig->pgsz; int eDetail = p->pConfig->eDetail; | < | 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 | pStruct = fts5StructureRead(p); iSegid = fts5AllocateSegid(p, pStruct); fts5StructureInvalidate(p); if( iSegid ){ const int pgsz = p->pConfig->pgsz; int eDetail = p->pConfig->eDetail; Fts5StructureSegment *pSeg; /* New segment within pStruct */ Fts5Buffer *pBuf; /* Buffer in which to assemble leaf page */ Fts5Buffer *pPgidx; /* Buffer in which to assemble pgidx */ Fts5SegWriter writer; fts5WriteInit(p, &writer, iSegid); |
︙ | ︙ | |||
5002 5003 5004 5005 5006 5007 5008 | /* Begin scanning through hash table entries. This loop runs once for each ** term/doclist currently stored within the hash table. */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); } while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ const char *zTerm; /* Buffer containing term */ | < | < < | | < | | | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > | < < | 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 | /* Begin scanning through hash table entries. This loop runs once for each ** term/doclist currently stored within the hash table. */ if( p->rc==SQLITE_OK ){ p->rc = sqlite3Fts5HashScanInit(pHash, 0, 0); } while( p->rc==SQLITE_OK && 0==sqlite3Fts5HashScanEof(pHash) ){ const char *zTerm; /* Buffer containing term */ const u8 *pDoclist; /* Pointer to doclist for this term */ int nDoclist; /* Size of doclist in bytes */ /* Write the term for this entry to disk. */ sqlite3Fts5HashScanEntry(pHash, &zTerm, &pDoclist, &nDoclist); fts5WriteAppendTerm(p, &writer, (int)strlen(zTerm), (const u8*)zTerm); if( p->rc!=SQLITE_OK ) break; assert( writer.bFirstRowidInPage==0 ); if( pgsz>=(pBuf->n + pPgidx->n + nDoclist + 1) ){ /* The entire doclist will fit on the current leaf. */ fts5BufferSafeAppendBlob(pBuf, pDoclist, nDoclist); }else{ i64 iRowid = 0; u64 iDelta = 0; int iOff = 0; /* The entire doclist will not fit on this leaf. The following ** loop iterates through the poslists that make up the current ** doclist. */ while( p->rc==SQLITE_OK && iOff<nDoclist ){ iOff += fts5GetVarint(&pDoclist[iOff], &iDelta); iRowid += iDelta; if( writer.bFirstRowidInPage ){ fts5PutU16(&pBuf->p[0], (u16)pBuf->n); /* first rowid on page */ pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iRowid); writer.bFirstRowidInPage = 0; fts5WriteDlidxAppend(p, &writer, iRowid); if( p->rc!=SQLITE_OK ) break; }else{ pBuf->n += sqlite3Fts5PutVarint(&pBuf->p[pBuf->n], iDelta); } assert( pBuf->n<=pBuf->nSpace ); if( eDetail==FTS5_DETAIL_NONE ){ if( iOff<nDoclist && pDoclist[iOff]==0 ){ pBuf->p[pBuf->n++] = 0; iOff++; if( iOff<nDoclist && pDoclist[iOff]==0 ){ pBuf->p[pBuf->n++] = 0; |
︙ | ︙ | |||
5131 5132 5133 5134 5135 5136 5137 | /* pBuf->p[pBuf->n++] = '\0'; */ assert( pBuf->n<=pBuf->nSpace ); if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); } sqlite3Fts5HashClear(pHash); fts5WriteFinish(p, &writer, &pgnoLast); | < < | | | | | | | | | | | | | | < | 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 | /* pBuf->p[pBuf->n++] = '\0'; */ assert( pBuf->n<=pBuf->nSpace ); if( p->rc==SQLITE_OK ) sqlite3Fts5HashScanNext(pHash); } sqlite3Fts5HashClear(pHash); fts5WriteFinish(p, &writer, &pgnoLast); /* Update the Fts5Structure. It is written back to the database by the ** fts5StructureRelease() call below. */ if( pStruct->nLevel==0 ){ fts5StructureAddLevel(&p->rc, &pStruct); } fts5StructureExtendLevel(&p->rc, pStruct, 0, 1, 0); if( p->rc==SQLITE_OK ){ pSeg = &pStruct->aLevel[0].aSeg[ pStruct->aLevel[0].nSeg++ ]; pSeg->iSegid = iSegid; pSeg->pgnoFirst = 1; pSeg->pgnoLast = pgnoLast; pStruct->nSegment++; } fts5StructurePromote(p, 0, pStruct); } fts5IndexAutomerge(p, &pStruct, pgnoLast); fts5IndexCrisismerge(p, &pStruct); fts5StructureWrite(p, pStruct); fts5StructureRelease(pStruct); } |
︙ | ︙ | |||
5203 5204 5205 5206 5207 5208 5209 | nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel); pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ Fts5StructureLevel *pLvl; nByte = nSeg * sizeof(Fts5StructureSegment); | | | | 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 | nByte += (pStruct->nLevel+1) * sizeof(Fts5StructureLevel); pNew = (Fts5Structure*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pNew ){ Fts5StructureLevel *pLvl; nByte = nSeg * sizeof(Fts5StructureSegment); pNew->nLevel = pStruct->nLevel+1; pNew->nRef = 1; pNew->nWriteCounter = pStruct->nWriteCounter; pLvl = &pNew->aLevel[MIN(pStruct->nLevel, FTS5_MAX_LEVEL-1)]; pLvl->aSeg = (Fts5StructureSegment*)sqlite3Fts5MallocZero(&p->rc, nByte); if( pLvl->aSeg ){ int iLvl, iSeg; int iSegOut = 0; /* Iterate through all segments, from oldest to newest. Add them to ** the new Fts5Level object so that pLvl->aSeg[0] is the oldest ** segment in the data structure. */ |
︙ | ︙ | |||
5888 5889 5890 5891 5892 5893 5894 | fts5StructureInvalidate(p); sqlite3_finalize(p->pWriter); sqlite3_finalize(p->pDeleter); sqlite3_finalize(p->pIdxWriter); sqlite3_finalize(p->pIdxDeleter); sqlite3_finalize(p->pIdxSelect); sqlite3_finalize(p->pDataVersion); | < | 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 | fts5StructureInvalidate(p); sqlite3_finalize(p->pWriter); sqlite3_finalize(p->pDeleter); sqlite3_finalize(p->pIdxWriter); sqlite3_finalize(p->pIdxDeleter); sqlite3_finalize(p->pIdxSelect); sqlite3_finalize(p->pDataVersion); sqlite3Fts5HashFree(p->pHash); sqlite3_free(p->zDataTbl); sqlite3_free(p); } return rc; } |
︙ | ︙ | |||
6519 6520 6521 6522 6523 6524 6525 | } static void fts5IndexIntegrityCheckSegment( Fts5Index *p, /* FTS5 backend object */ Fts5StructureSegment *pSeg /* Segment to check internal consistency */ ){ Fts5Config *pConfig = p->pConfig; | < | 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 | } static void fts5IndexIntegrityCheckSegment( Fts5Index *p, /* FTS5 backend object */ Fts5StructureSegment *pSeg /* Segment to check internal consistency */ ){ Fts5Config *pConfig = p->pConfig; sqlite3_stmt *pStmt = 0; int rc2; int iIdxPrevLeaf = pSeg->pgnoFirst-1; int iDlidxPrevLeaf = pSeg->pgnoLast; if( pSeg->pgnoFirst==0 ) return; |
︙ | ︙ | |||
6555 6556 6557 6558 6559 6560 6561 | if( pLeaf==0 ) break; /* Check that the leaf contains at least one term, and that it is equal ** to or larger than the split-key in zIdxTerm. Also check that if there ** is also a rowid pointer within the leaf page header, it points to a ** location before the term. */ if( pLeaf->nn<=pLeaf->szLeaf ){ | < < < < < < < < < < | < < | 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 | if( pLeaf==0 ) break; /* Check that the leaf contains at least one term, and that it is equal ** to or larger than the split-key in zIdxTerm. Also check that if there ** is also a rowid pointer within the leaf page header, it points to a ** location before the term. */ if( pLeaf->nn<=pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; }else{ int iOff; /* Offset of first term on leaf */ int iRowidOff; /* Offset of first rowid on leaf */ int nTerm; /* Size of term on leaf in bytes */ int res; /* Comparison of term and split-key */ iOff = fts5LeafFirstTermOff(pLeaf); |
︙ | ︙ | |||
6631 6632 6633 6634 6635 6636 6637 | pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ i64 iRowid; int iRowidOff = fts5LeafFirstRowidOff(pLeaf); ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; | | < < | < | 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 | pLeaf = fts5DataRead(p, iKey); if( pLeaf ){ i64 iRowid; int iRowidOff = fts5LeafFirstRowidOff(pLeaf); ASSERT_SZLEAF_OK(pLeaf); if( iRowidOff>=pLeaf->szLeaf ){ p->rc = FTS5_CORRUPT; }else{ fts5GetVarint(&pLeaf->p[iRowidOff], (u64*)&iRowid); if( iRowid!=fts5DlidxIterRowid(pDlidx) ) p->rc = FTS5_CORRUPT; } fts5DataRelease(pLeaf); } } iDlidxPrevLeaf = iPg; fts5DlidxIterFree(pDlidx); |
︙ | ︙ |
Changes to ext/fts5/fts5_main.c.
︙ | ︙ | |||
1619 1620 1621 1622 1623 1624 1625 | sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; Fts5Config *pConfig = pTab->p.pConfig; int eType0; /* value_type() of apVal[0] */ int rc = SQLITE_OK; /* Return code */ | < < < < < < < | 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 | sqlite3_value **apVal, /* Array of arguments */ sqlite_int64 *pRowid /* OUT: The affected (or effected) rowid */ ){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; Fts5Config *pConfig = pTab->p.pConfig; int eType0; /* value_type() of apVal[0] */ int rc = SQLITE_OK; /* Return code */ /* A transaction must be open when this is called. */ assert( pTab->ts.eState==1 || pTab->ts.eState==2 ); assert( pVtab->zErrMsg==0 ); assert( nArg==1 || nArg==(2+pConfig->nCol+2) ); assert( sqlite3_value_type(apVal[0])==SQLITE_INTEGER || sqlite3_value_type(apVal[0])==SQLITE_NULL ); assert( pTab->p.pConfig->pzErrmsg==0 ); pTab->p.pConfig->pzErrmsg = &pTab->p.base.zErrMsg; /* Put any active cursors into REQUIRE_SEEK state. */ fts5TripCursors(pTab); eType0 = sqlite3_value_type(apVal[0]); if( eType0==SQLITE_NULL |
︙ | ︙ | |||
1688 1689 1690 1691 1692 1693 1694 | rc = SQLITE_ERROR; } /* DELETE */ else if( nArg==1 ){ i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0); | < < | 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 | rc = SQLITE_ERROR; } /* DELETE */ else if( nArg==1 ){ i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel, 0); } /* INSERT or UPDATE */ else{ int eType1 = sqlite3_value_numeric_type(apVal[1]); if( eType1!=SQLITE_INTEGER && eType1!=SQLITE_NULL ){ rc = SQLITE_MISMATCH; } else if( eType0!=SQLITE_INTEGER ){ /* If this is a REPLACE, first remove the current entry (if any) */ if( eConflict==SQLITE_REPLACE && eType1==SQLITE_INTEGER ){ i64 iNew = sqlite3_value_int64(apVal[1]); /* Rowid to delete */ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iNew, 0); } fts5StorageInsert(&rc, pTab, apVal, pRowid); } /* UPDATE */ else{ i64 iOld = sqlite3_value_int64(apVal[0]); /* Old rowid */ |
︙ | ︙ | |||
1733 1734 1735 1736 1737 1738 1739 | rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid); } } }else{ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); fts5StorageInsert(&rc, pTab, apVal, pRowid); } | < < < < < < < < < < < < < < | 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 | rc = sqlite3Fts5StorageIndexInsert(pTab->pStorage, apVal,*pRowid); } } }else{ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iOld, 0); fts5StorageInsert(&rc, pTab, apVal, pRowid); } } } } pTab->p.pConfig->pzErrmsg = 0; return rc; } |
︙ | ︙ | |||
2610 2611 2612 2613 2614 2615 2616 | ** Discard the contents of the pending terms table. */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); | < | 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 | ** Discard the contents of the pending terms table. */ static int fts5RollbackToMethod(sqlite3_vtab *pVtab, int iSavepoint){ Fts5FullTable *pTab = (Fts5FullTable*)pVtab; UNUSED_PARAM(iSavepoint); /* Call below is a no-op for NDEBUG builds */ fts5CheckTransactionState(pTab, FTS5_ROLLBACKTO, iSavepoint); fts5TripCursors(pTab); return sqlite3Fts5StorageRollback(pTab->pStorage); } /* ** Register a new auxiliary function with global context pGlobal. */ static int fts5CreateAux( |
︙ | ︙ |
Changes to ext/fts5/test/fts5_common.tcl.
︙ | ︙ | |||
590 591 592 593 594 595 596 | nearset_rf $aCol {*}$args if {[lsearch $args -col]>=0} { set ::expr_not_ok 1 } list } | < < < < | 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | nearset_rf $aCol {*}$args if {[lsearch $args -col]>=0} { set ::expr_not_ok 1 } list } #------------------------------------------------------------------------- # Code for a simple Tcl tokenizer that supports synonyms at query time. # proc tclnum_tokenize {mode tflags text} { foreach {w iStart iEnd} [fts5_tokenize_split $text] { sqlite3_fts5_token $w $iStart $iEnd |
︙ | ︙ |
Changes to ext/fts5/test/fts5af.test.
︙ | ︙ | |||
188 189 190 191 192 193 194 | SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ""'); } {{[x a a a a a...}} do_execsql_test 5.6 { SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ' || x'DB'); } {{[x a a a a a...}} } ;# foreach_detail_mode | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 188 189 190 191 192 193 194 195 196 | SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ""'); } {{[x a a a a a...}} do_execsql_test 5.6 { SELECT snippet(p1, 0, '[', NULL, '...', 6) FROM p1('x OR ' || x'DB'); } {{[x a a a a a...}} } ;# foreach_detail_mode finish_test |
Changes to ext/fts5/test/fts5ak.test.
︙ | ︙ | |||
150 151 152 153 154 155 156 | {a b c x c d e} {a b c c d e} {a b c d e} } } | < < < < < < < < < < < < < < < < < < < < < < < < < < | 150 151 152 153 154 155 156 157 | {a b c x c d e} {a b c c d e} {a b c d e} } } finish_test |
Deleted ext/fts5/test/fts5corrupt7.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/fts5/test/fts5misc.test.
︙ | ︙ | |||
438 439 440 441 442 443 444 | do_execsql_test 16.5 { COMMIT } do_execsql_test -db db2 16.6 { SELECT * FROM x1 } {abc def} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 438 439 440 441 442 443 444 445 446 447 | do_execsql_test 16.5 { COMMIT } do_execsql_test -db db2 16.6 { SELECT * FROM x1 } {abc def} finish_test |
Changes to ext/fts5/test/fts5optimize2.test.
︙ | ︙ | |||
17 18 19 20 21 22 23 | # If SQLITE_ENABLE_FTS5 is defined, omit this file. ifcapable !fts5 { finish_test return } | < < | | | | | 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 | # If SQLITE_ENABLE_FTS5 is defined, omit this file. ifcapable !fts5 { finish_test return } do_execsql_test 1.0 { CREATE VIRTUAL TABLE t1 USING fts5(x); INSERT INTO t1(t1, rank) VALUES('pgsz', 32); } do_test 1.1 { for {set ii 0} {$ii < 1500} {incr ii} { execsql { INSERT INTO t1 VALUES('abc def ghi'); INSERT INTO t1 VALUES('jkl mno pqr'); INSERT INTO t1(t1) VALUES('optimize'); } } } {} do_execsql_test 1.2 { SELECT count(*) FROM t1('mno') } {1500} do_execsql_test 2.0 { CREATE VIRTUAL TABLE t2 USING fts5(x); INSERT INTO t2(t2, rank) VALUES('pgsz', 32); } do_test 2.1 { for {set ii 0} {$ii < 1500} {incr ii} { execsql { INSERT INTO t2 VALUES('abc def ghi'); INSERT INTO t2 VALUES('jkl mno pqr'); INSERT INTO t2(t2, rank) VALUES('merge', -1); } } } {} do_execsql_test 2.2 { SELECT count(*) FROM t2('mno') } {1500} finish_test |
Deleted ext/fts5/test/fts5secure.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/fts5/test/fts5secure2.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/fts5/test/fts5secure3.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/fts5/test/fts5secure4.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/fts5/test/fts5secure5.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/fts5/test/fts5secure6.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted ext/fts5/test/fts5securefault.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/fts5/test/fts5trigram.test.
︙ | ︙ | |||
51 52 53 54 55 56 57 | 2 {cDef%} {} 3 {%f%} 1 4 {%f_h%} 1 5 {%f_g%} {} 6 {abc%klm} 1 7 {ABCDEFG%} 1 8 {%รุงเ%} 2 | < | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 2 {cDef%} {} 3 {%f%} 1 4 {%f_h%} 1 5 {%f_g%} {} 6 {abc%klm} 1 7 {ABCDEFG%} 1 8 {%รุงเ%} 2 } { do_execsql_test 1.3.$tn { SELECT rowid FROM t1 WHERE y LIKE $like } $res } #------------------------------------------------------------------------- |
︙ | ︙ | |||
194 195 196 197 198 199 200 | do_eqp_test 6.3 { SELECT * FROM ci1 WHERE x LIKE ? } {{SCAN ci1 VIRTUAL TABLE INDEX 0:}} do_eqp_test 6.4 { SELECT * FROM ci1 WHERE x GLOB ? } {VIRTUAL TABLE INDEX 0:G0} | < < < < < < < < < < < < < < < < < | 193 194 195 196 197 198 199 200 | do_eqp_test 6.3 { SELECT * FROM ci1 WHERE x LIKE ? } {{SCAN ci1 VIRTUAL TABLE INDEX 0:}} do_eqp_test 6.4 { SELECT * FROM ci1 WHERE x GLOB ? } {VIRTUAL TABLE INDEX 0:G0} finish_test |
Changes to ext/fts5/test/fts5version.test.
︙ | ︙ | |||
34 35 36 37 38 39 40 | do_execsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'a'; } {1} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.4 { | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | do_execsql_test 1.3 { SELECT rowid FROM t1 WHERE t1 MATCH 'a'; } {1} sqlite3_db_config db DEFENSIVE 0 do_execsql_test 1.4 { UPDATE t1_config set v=5 WHERE k='version'; } do_test 1.5 { db close sqlite3 db test.db catchsql { SELECT * FROM t1 WHERE t1 MATCH 'a' } } {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} do_test 1.6 { db close sqlite3 db test.db catchsql { INSERT INTO t1 VALUES('x y z') } } {1 {invalid fts5 file format (found 5, expected 4) - run 'rebuild'}} do_test 1.7 { sqlite3_db_config db DEFENSIVE 0 execsql { DELETE FROM t1_config WHERE k='version' } db close sqlite3 db test.db catchsql { SELECT * FROM t1 WHERE t1 MATCH 'a' } } {1 {invalid fts5 file format (found 0, expected 4) - run 'rebuild'}} finish_test |
Changes to ext/misc/base64.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 | #define PAD_CHAR '=' #ifndef U8_TYPEDEF typedef unsigned char u8; #define U8_TYPEDEF #endif | < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | #define PAD_CHAR '=' #ifndef U8_TYPEDEF typedef unsigned char u8; #define U8_TYPEDEF #endif static const u8 b64DigitValues[128] = { /* HT LF VT FF CR */ ND,ND,ND,ND, ND,ND,ND,ND, ND,WS,WS,WS, WS,WS,ND,ND, /* US */ ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,ND, /*sp + / */ WS,ND,ND,ND, ND,ND,ND,ND, ND,ND,ND,62, ND,ND,ND,63, |
︙ | ︙ | |||
144 145 146 147 148 149 150 | *pOut++ = '\n'; } *pOut = 0; return pOut; } /* Skip over text which is not base64 numeral(s). */ | | | | | 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 | *pOut++ = '\n'; } *pOut = 0; return pOut; } /* Skip over text which is not base64 numeral(s). */ static char * skipNonB64( char *s ){ char c; while( (c = *s) && !IS_BX_DIGIT(BX_DV_PROTO(c)) ) ++s; return s; } /* Decode base64 text into a byte buffer. */ static u8* fromBase64( char *pIn, int ncIn, u8 *pOut ){ if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; while( ncIn>0 && *pIn!=PAD_CHAR ){ static signed char nboi[] = { 0, 0, 1, 2, 3 }; char *pUse = skipNonB64(pIn); unsigned long qv = 0L; int nti, nbo, nac; ncIn -= (pUse - pIn); pIn = pUse; nti = (ncIn>4)? 4 : ncIn; ncIn -= nti; nbo = nboi[nti]; |
︙ | ︙ | |||
215 216 217 218 219 220 221 | nb = nv; nc = 4*(nv+2/3); /* quads needed */ nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */ if( nvMax < nc ){ sqlite3_result_error(context, "blob expanded to base64 too big", -1); return; } | < < < < < < < < > < < < < < < < < > | 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 | nb = nv; nc = 4*(nv+2/3); /* quads needed */ nc += (nc+(B64_DARK_MAX-1))/B64_DARK_MAX + 1; /* LFs and a 0-terminator */ if( nvMax < nc ){ sqlite3_result_error(context, "blob expanded to base64 too big", -1); return; } cBuf = sqlite3_malloc(nc); if( !cBuf ) goto memFail; bBuf = (u8*)sqlite3_value_blob(av[0]); nc = (int)(toBase64(bBuf, nb, cBuf) - cBuf); sqlite3_result_text(context, cBuf, nc, sqlite3_free); break; case SQLITE_TEXT: nc = nv; nb = 3*((nv+3)/4); /* may overestimate due to LF and padding */ if( nvMax < nb ){ sqlite3_result_error(context, "blob from base64 may be too big", -1); return; }else if( nb<1 ){ nb = 1; } bBuf = sqlite3_malloc(nb); if( !bBuf ) goto memFail; cBuf = (char *)sqlite3_value_text(av[0]); nb = (int)(fromBase64(cBuf, nc, bBuf) - bBuf); sqlite3_result_blob(context, bBuf, nb, sqlite3_free); break; default: sqlite3_result_error(context, "base64 accepts only blob or text", -1); return; } |
︙ | ︙ |
Changes to ext/misc/base85.c.
︙ | ︙ | |||
136 137 138 139 140 141 142 | } #endif /* Width of base64 lines. Should be an integer multiple of 5. */ #define B85_DARK_MAX 80 | | | | 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | } #endif /* Width of base64 lines. Should be an integer multiple of 5. */ #define B85_DARK_MAX 80 static char * skipNonB85( char *s ){ char c; while( (c = *s) && !IS_B85(c) ) ++s; return s; } /* Convert small integer, known to be in 0..84 inclusive, to base85 numeral. * Do not use the macro form with argument expression having a side-effect.*/ #if 0 static char base85Numeral( u8 b ){ |
︙ | ︙ | |||
208 209 210 211 212 213 214 | } /* Decode base85 text into a byte buffer. */ static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){ if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; while( ncIn>0 ){ static signed char nboi[] = { 0, 0, 1, 2, 3, 4 }; | | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | } /* Decode base85 text into a byte buffer. */ static u8* fromBase85( char *pIn, int ncIn, u8 *pOut ){ if( ncIn>0 && pIn[ncIn-1]=='\n' ) --ncIn; while( ncIn>0 ){ static signed char nboi[] = { 0, 0, 1, 2, 3, 4 }; char *pUse = skipNonB85(pIn); unsigned long qv = 0L; int nti, nbo; ncIn -= (pUse - pIn); pIn = pUse; nti = (ncIn>5)? 5 : ncIn; nbo = nboi[nti]; if( nbo==0 ) break; |
︙ | ︙ | |||
293 294 295 296 297 298 299 | nb = nv; /* ulongs tail newlines tailenc+nul*/ nc = 5*(nv/4) + nv%4 + nv/64+1 + 2; if( nvMax < nc ){ sqlite3_result_error(context, "blob expanded to base85 too big", -1); return; } | < < < < < < < < > < < < < < < < < > | 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 | nb = nv; /* ulongs tail newlines tailenc+nul*/ nc = 5*(nv/4) + nv%4 + nv/64+1 + 2; if( nvMax < nc ){ sqlite3_result_error(context, "blob expanded to base85 too big", -1); return; } cBuf = sqlite3_malloc(nc); if( !cBuf ) goto memFail; bBuf = (u8*)sqlite3_value_blob(av[0]); nc = (int)(toBase85(bBuf, nb, cBuf, "\n") - cBuf); sqlite3_result_text(context, cBuf, nc, sqlite3_free); break; case SQLITE_TEXT: nc = nv; nb = 4*(nv/5) + nv%5; /* may overestimate */ if( nvMax < nb ){ sqlite3_result_error(context, "blob from base85 may be too big", -1); return; }else if( nb<1 ){ nb = 1; } bBuf = sqlite3_malloc(nb); if( !bBuf ) goto memFail; cBuf = (char *)sqlite3_value_text(av[0]); nb = (int)(fromBase85(cBuf, nc, bBuf) - bBuf); sqlite3_result_blob(context, bBuf, nb, sqlite3_free); break; default: sqlite3_result_error(context, "base85 accepts only blob or text.", -1); return; } |
︙ | ︙ |
Deleted ext/misc/randomjson.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/misc/series.c.
1 | /* | | | < < < < < < < < < < < < < < < < < < < < < < < | 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 | /* ** 2015-08-18 ** ** 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 demonstrates how to create a table-valued-function using ** a virtual table. This demo implements the generate_series() function ** which gives similar results to the eponymous function in PostgreSQL. ** Examples: ** ** SELECT * FROM generate_series(0,100,5); ** ** The query above returns integers from 0 through 100 counting by steps ** of 5. ** ** SELECT * FROM generate_series(0,100); ** ** Integers from 0 through 100 with a step size of 1. ** ** SELECT * FROM generate_series(20) LIMIT 10; ** ** Integers 20 through 29. ** ** HOW IT WORKS ** ** The generate_series "function" is really a virtual table with the ** following schema: ** ** CREATE TABLE generate_series( ** value, ** start HIDDEN, ** stop HIDDEN, ** step HIDDEN ** ); ** ** Function arguments in queries against this virtual table are translated ** into equality constraints against successive hidden columns. In other ** words, the following pairs of queries are equivalent to each other: ** ** SELECT * FROM generate_series(0,100,5); ** SELECT * FROM generate_series WHERE start=0 AND stop=100 AND step=5; ** |
︙ | ︙ | |||
91 92 93 94 95 96 97 | ** encourages the query planner to order joins such that the bounds of the ** series are well-defined. */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> | < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | > > > > > | 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 | ** encourages the query planner to order joins such that the bounds of the ** series are well-defined. */ #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <assert.h> #include <string.h> #ifndef SQLITE_OMIT_VIRTUALTABLE /* series_cursor is a subclass of sqlite3_vtab_cursor which will ** serve as the underlying representation of a cursor that scans ** over rows of the result */ typedef struct series_cursor series_cursor; struct series_cursor { sqlite3_vtab_cursor base; /* Base class - must be first */ int isDesc; /* True to count down rather than up */ sqlite3_int64 iRowid; /* The rowid */ sqlite3_int64 iValue; /* Current value ("value") */ sqlite3_int64 mnValue; /* Mimimum value ("start") */ sqlite3_int64 mxValue; /* Maximum value ("stop") */ sqlite3_int64 iStep; /* Increment ("step") */ }; /* ** The seriesConnect() method is invoked to create a new ** series_vtab that describes the generate_series virtual table. ** ** Think of this routine as the constructor for series_vtab objects. |
︙ | ︙ | |||
271 272 273 274 275 276 277 | /* ** Advance a series_cursor to its next row of output. */ static int seriesNext(sqlite3_vtab_cursor *cur){ series_cursor *pCur = (series_cursor*)cur; | | > > > > > | | | | | | > > > | | > | | | | | | | | | | | > | | | < > | > > > > | | | 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 | /* ** Advance a series_cursor to its next row of output. */ static int seriesNext(sqlite3_vtab_cursor *cur){ series_cursor *pCur = (series_cursor*)cur; if( pCur->isDesc ){ pCur->iValue -= pCur->iStep; }else{ pCur->iValue += pCur->iStep; } pCur->iRowid++; return SQLITE_OK; } /* ** Return values of columns for the row at which the series_cursor ** is currently pointing. */ static int seriesColumn( sqlite3_vtab_cursor *cur, /* The cursor */ sqlite3_context *ctx, /* First argument to sqlite3_result_...() */ int i /* Which column to return */ ){ series_cursor *pCur = (series_cursor*)cur; sqlite3_int64 x = 0; switch( i ){ case SERIES_COLUMN_START: x = pCur->mnValue; break; case SERIES_COLUMN_STOP: x = pCur->mxValue; break; case SERIES_COLUMN_STEP: x = pCur->iStep; break; default: x = pCur->iValue; break; } sqlite3_result_int64(ctx, x); return SQLITE_OK; } /* ** Return the rowid for the current row. In this implementation, the ** first row returned is assigned rowid value 1, and each subsequent ** row a value 1 more than that of the previous. */ static int seriesRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ series_cursor *pCur = (series_cursor*)cur; *pRowid = pCur->iRowid; return SQLITE_OK; } /* ** Return TRUE if the cursor has been moved off of the last ** row of output. */ static int seriesEof(sqlite3_vtab_cursor *cur){ series_cursor *pCur = (series_cursor*)cur; if( pCur->isDesc ){ return pCur->iValue < pCur->mnValue; }else{ return pCur->iValue > pCur->mxValue; } } /* True to cause run-time checking of the start=, stop=, and/or step= ** parameters. The only reason to do this is for testing the ** constraint checking logic for virtual tables in the SQLite core. */ #ifndef SQLITE_SERIES_CONSTRAINT_VERIFY # define SQLITE_SERIES_CONSTRAINT_VERIFY 0 #endif /* ** This method is called to "rewind" the series_cursor object back ** to the first row of output. This method is always called at least ** once prior to any call to seriesColumn() or seriesRowid() or ** seriesEof(). ** ** The query plan selected by seriesBestIndex is passed in the idxNum ** parameter. (idxStr is not used in this implementation.) idxNum ** is a bitmask showing which constraints are available: ** ** 1: start=VALUE ** 2: stop=VALUE ** 4: step=VALUE ** ** Also, if bit 8 is set, that means that the series should be output ** in descending order rather than in ascending order. If bit 16 is ** set, then output must appear in ascending order. ** ** This routine should initialize the cursor and position it so that it ** is pointing at the first row, or pointing off the end of the table ** (so that seriesEof() will return true) if the table is empty. */ static int seriesFilter( sqlite3_vtab_cursor *pVtabCursor, int idxNum, const char *idxStrUnused, int argc, sqlite3_value **argv ){ series_cursor *pCur = (series_cursor *)pVtabCursor; int i = 0; (void)idxStrUnused; if( idxNum & 1 ){ pCur->mnValue = sqlite3_value_int64(argv[i++]); }else{ pCur->mnValue = 0; } if( idxNum & 2 ){ pCur->mxValue = sqlite3_value_int64(argv[i++]); }else{ pCur->mxValue = 0xffffffff; } if( idxNum & 4 ){ pCur->iStep = sqlite3_value_int64(argv[i++]); if( pCur->iStep==0 ){ pCur->iStep = 1; }else if( pCur->iStep<0 ){ pCur->iStep = -pCur->iStep; if( (idxNum & 16)==0 ) idxNum |= 8; } }else{ pCur->iStep = 1; } for(i=0; i<argc; i++){ if( sqlite3_value_type(argv[i])==SQLITE_NULL ){ /* If any of the constraints have a NULL value, then return no rows. ** See ticket https://www.sqlite.org/src/info/fac496b61722daf2 */ pCur->mnValue = 1; pCur->mxValue = 0; break; } } if( idxNum & 8 ){ pCur->isDesc = 1; pCur->iValue = pCur->mxValue; if( pCur->iStep>0 ){ pCur->iValue -= (pCur->mxValue - pCur->mnValue)%pCur->iStep; } }else{ pCur->isDesc = 0; pCur->iValue = pCur->mnValue; } pCur->iRowid = 1; return SQLITE_OK; } /* ** SQLite will invoke this method one or more times while planning a query ** that uses the generate_series virtual table. This routine needs to create ** a query plan for each invocation and compute an estimated cost for that |
︙ | ︙ |
Changes to ext/misc/shathree.c.
1 2 3 4 5 6 7 8 9 10 11 12 | /* ** 2017-03-08 ** ** 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 20 | /* ** 2017-03-08 ** ** 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 SQLite extension implements functions that compute SHA3 hashes. ** Two SQL functions are implemented: ** ** sha3(X,SIZE) ** sha3_query(Y,SIZE) ** ** The sha3(X) function computes the SHA3 hash of the input X, or NULL if ** X is NULL. |
︙ | ︙ |
Changes to ext/misc/zipfile.c.
︙ | ︙ | |||
1093 1094 1095 1096 1097 1098 1099 | } sqlite3_free(aFree); }else{ /* Figure out if this is a directory or a zero-sized file. Consider ** it to be a directory either if the mode suggests so, or if ** the final character in the name is '/'. */ u32 mode = pCDS->iExternalAttr >> 16; | | < < < | 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 | } sqlite3_free(aFree); }else{ /* Figure out if this is a directory or a zero-sized file. Consider ** it to be a directory either if the mode suggests so, or if ** the final character in the name is '/'. */ u32 mode = pCDS->iExternalAttr >> 16; if( !(mode & S_IFDIR) && pCDS->zFile[pCDS->nFile-1]!='/' ){ sqlite3_result_blob(ctx, "", 0, SQLITE_STATIC); } } } break; } case 6: /* method */ |
︙ | ︙ | |||
1533 1534 1535 1536 1537 1538 1539 | /* ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry ** linked list. Remove it from the list and free the object. */ static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){ if( pOld ){ | < < < < | | | < < < < < < | 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 | /* ** Unless it is NULL, entry pOld is currently part of the pTab->pFirstEntry ** linked list. Remove it from the list and free the object. */ static void zipfileRemoveEntryFromList(ZipfileTab *pTab, ZipfileEntry *pOld){ if( pOld ){ ZipfileEntry **pp; for(pp=&pTab->pFirstEntry; (*pp)!=pOld; pp=&((*pp)->pNext)); *pp = (*pp)->pNext; zipfileEntryFree(pOld); } } /* ** xUpdate method. */ |
︙ | ︙ |
Changes to ext/rbu/rbu_common.tcl.
︙ | ︙ | |||
16 17 18 19 20 21 22 | source $testdir/tester.tcl proc if_no_rbu_support {tcl} { set bOk 1 ifcapable !rbu { set bOk 0 } if {[permutation]=="journaltest"} { set bOk 0 } if {$bOk==0} { | | < | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | source $testdir/tester.tcl proc if_no_rbu_support {tcl} { set bOk 1 ifcapable !rbu { set bOk 0 } if {[permutation]=="journaltest"} { set bOk 0 } if {$bOk==0} { uplevel $tcl } } proc check_prestep_state {target state} { set oal_exists [file exists $target-oal] set wal_exists [file exists $target-wal] set progress [rbu progress] |
︙ | ︙ |
Changes to ext/rbu/rbuexlock.test.
︙ | ︙ | |||
203 204 205 206 207 208 209 | create_rbu rbu1.db do_test 3.4.0 { sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db rbu step } SQLITE_OK rbu close | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 203 204 205 206 207 208 209 210 211 | create_rbu rbu1.db do_test 3.4.0 { sqlite3rbu rbu file:test.db?rbu_exclusive_checkpoint=0 rbu1.db rbu step } SQLITE_OK rbu close finish_test |
Changes to ext/rbu/rbufault4.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE INDEX i1b ON t1(b); CREATE INDEX i1c ON t1(c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); } | < | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | do_execsql_test 1.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); CREATE INDEX i1b ON t1(b); CREATE INDEX i1c ON t1(c); INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t1 VALUES(4, 5, 6); } forcedelete test.db2 sqlite3rbu_vacuum rbu test.db test.db2 for {set i 0} {$i < $tn} {incr i} { rbu step } set rc [rbu close] if {$rc!="SQLITE_OK"} { if {$rc!="SQLITE_DONE"} {error $rc} |
︙ | ︙ | |||
50 51 52 53 54 55 56 | faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 SQLITE_IOERR_NOMEM} sqlite3rbu_vacuum rbu test.db test.db2 while {[rbu step]=="SQLITE_OK"} {} set trc [rbu close] if {$trc!="SQLITE_DONE"} { error "Got $trc instead of SQLITE_DONE!" } | < < | 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | faultsim_test_result {0 {}} {1 SQLITE_NOMEM} {1 SQLITE_IOERR_NOMEM} sqlite3rbu_vacuum rbu test.db test.db2 while {[rbu step]=="SQLITE_OK"} {} set trc [rbu close] if {$trc!="SQLITE_DONE"} { error "Got $trc instead of SQLITE_DONE!" } set rc [db one {PRAGMA integrity_check}] if {$rc!="ok"} { error "Got $rc instead of ok!" } } } finish_test |
Changes to ext/rbu/rburesume.test.
︙ | ︙ | |||
96 97 98 99 100 101 102 | if {$rc == "SQLITE_DONE"} break } if {$rc == "SQLITE_DONE"} { rbu close break } | | | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | if {$rc == "SQLITE_DONE"} break } if {$rc == "SQLITE_DONE"} { rbu close break } foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} { set f2 [string map [list test.db test.db2] $f] if {[file exists $f]} { forcecopy $f $f2 } else { forcedelete $f2 } } |
︙ | ︙ | |||
155 156 157 158 159 160 161 | if {$rc == "SQLITE_DONE"} break } if {$rc == "SQLITE_DONE"} { rbu close break } | | | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 | if {$rc == "SQLITE_DONE"} break } if {$rc == "SQLITE_DONE"} { rbu close break } foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} { set f2 [string map [list test.db test.db2] $f] if {[file exists $f]} { forcecopy $f $f2 } else { forcedelete $f2 } } |
︙ | ︙ | |||
222 223 224 225 226 227 228 | if {$rc == "SQLITE_DONE"} break } if {$rc == "SQLITE_DONE"} { rbu close break } | | | 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | if {$rc == "SQLITE_DONE"} break } if {$rc == "SQLITE_DONE"} { rbu close break } foreach f {test.db test.db-oal test.db-wal test.db-shm test.db-vacuum} { set f2 [string map [list test.db test.db2] $f] if {[file exists $f]} { forcecopy $f $f2 } else { forcedelete $f2 } } |
︙ | ︙ |
Changes to ext/rbu/sqlite3rbu.c.
︙ | ︙ | |||
3137 3138 3139 3140 3141 3142 3143 | p->rc = pWal->pMethods->xRead(pWal, p->aBuf, p->pgsz, iOff); if( p->rc ) return; iOff = (i64)(pFrame->iDbPage-1) * p->pgsz; p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff); } | < < < < < < < < | < | 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 | p->rc = pWal->pMethods->xRead(pWal, p->aBuf, p->pgsz, iOff); if( p->rc ) return; iOff = (i64)(pFrame->iDbPage-1) * p->pgsz; p->rc = pDb->pMethods->xWrite(pDb, p->aBuf, p->pgsz, iOff); } /* ** Take an EXCLUSIVE lock on the database file. Return SQLITE_OK if ** successful, or an SQLite error code otherwise. */ static int rbuLockDatabase(sqlite3 *db){ int rc = SQLITE_OK; sqlite3_file *fd = 0; sqlite3_file_control(db, "main", SQLITE_FCNTL_FILE_POINTER, &fd); if( fd->pMethods ){ rc = fd->pMethods->xLock(fd, SQLITE_LOCK_SHARED); if( rc==SQLITE_OK ){ rc = fd->pMethods->xLock(fd, SQLITE_LOCK_EXCLUSIVE); } } |
︙ | ︙ |
Changes to ext/recover/dbdata.c.
︙ | ︙ | |||
163 164 165 166 167 168 169 | ){ DbdataTable *pTab = 0; int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA); (void)argc; (void)argv; (void)pzErr; | < | 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | ){ DbdataTable *pTab = 0; int rc = sqlite3_declare_vtab(db, pAux ? DBPTR_SCHEMA : DBDATA_SCHEMA); (void)argc; (void)argv; (void)pzErr; if( rc==SQLITE_OK ){ pTab = (DbdataTable*)sqlite3_malloc64(sizeof(DbdataTable)); if( pTab==0 ){ rc = SQLITE_NOMEM; }else{ memset(pTab, 0, sizeof(DbdataTable)); pTab->db = db; |
︙ | ︙ | |||
509 510 511 512 513 514 515 | int bNextPage = 0; if( pCsr->aPage==0 ){ while( 1 ){ if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK; rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage); if( rc!=SQLITE_OK ) return rc; | | < < < < | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 | int bNextPage = 0; if( pCsr->aPage==0 ){ while( 1 ){ if( pCsr->bOnePage==0 && pCsr->iPgno>pCsr->szDb ) return SQLITE_OK; rc = dbdataLoadPage(pCsr, pCsr->iPgno, &pCsr->aPage, &pCsr->nPage); if( rc!=SQLITE_OK ) return rc; if( pCsr->aPage ) break; if( pCsr->bOnePage ) return SQLITE_OK; pCsr->iPgno++; } pCsr->iCell = pTab->bPtr ? -2 : 0; pCsr->nCell = get_uint16(&pCsr->aPage[iOff+3]); } if( pTab->bPtr ){ if( pCsr->aPage[iOff]!=0x02 && pCsr->aPage[iOff]!=0x05 ){ pCsr->iCell = pCsr->nCell; |
︙ | ︙ | |||
751 752 753 754 755 756 757 | ** and return SQLITE_OK. Otherwise, return an SQLite error code. */ static int dbdataGetEncoding(DbdataCursor *pCsr){ int rc = SQLITE_OK; int nPg1 = 0; u8 *aPg1 = 0; rc = dbdataLoadPage(pCsr, 1, &aPg1, &nPg1); | > | | 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 | ** and return SQLITE_OK. Otherwise, return an SQLite error code. */ static int dbdataGetEncoding(DbdataCursor *pCsr){ int rc = SQLITE_OK; int nPg1 = 0; u8 *aPg1 = 0; rc = dbdataLoadPage(pCsr, 1, &aPg1, &nPg1); assert( rc!=SQLITE_OK || nPg1==0 || nPg1>=512 ); if( rc==SQLITE_OK && nPg1>0 ){ pCsr->enc = get_uint32(&aPg1[56]); } sqlite3_free(aPg1); return rc; } |
︙ | ︙ | |||
809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 | "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1, &pCsr->pStmt, 0 ); } } if( rc==SQLITE_OK ){ rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT); } /* Try to determine the encoding of the db by inspecting the header ** field on page 1. */ if( rc==SQLITE_OK ){ rc = dbdataGetEncoding(pCsr); } | > > < < < < | 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | "SELECT data FROM sqlite_dbpage(?) WHERE pgno=?", -1, &pCsr->pStmt, 0 ); } } if( rc==SQLITE_OK ){ rc = sqlite3_bind_text(pCsr->pStmt, 1, zSchema, -1, SQLITE_TRANSIENT); }else{ pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); } /* Try to determine the encoding of the db by inspecting the header ** field on page 1. */ if( rc==SQLITE_OK ){ rc = dbdataGetEncoding(pCsr); } if( rc==SQLITE_OK ){ rc = dbdataNext(pCursor); } return rc; } /* |
︙ | ︙ |
Changes to ext/recover/recover1.test.
︙ | ︙ | |||
312 313 314 315 316 317 318 | list [catch { $R finish } msg] $msg } {1 {cannot start a transaction within a transaction}} do_execsql_test 16.9 { SELECT * FROM t1; COMMIT; } {1 2 3 4} | < < < < < < < < < < < < < | 312 313 314 315 316 317 318 319 320 | list [catch { $R finish } msg] $msg } {1 {cannot start a transaction within a transaction}} do_execsql_test 16.9 { SELECT * FROM t1; COMMIT; } {1 2 3 4} finish_test |
Deleted ext/recover/recoverbuild.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/recover/sqlite3recover.c.
︙ | ︙ | |||
1102 1103 1104 1105 1106 1107 1108 | recoverFinalize(p, pStmt); pStmt = recoverPreparePrintf(p, p->dbOut, "PRAGMA index_xinfo(%Q)", zName); while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ int iField = sqlite3_column_int(pStmt, 0); int iCol = sqlite3_column_int(pStmt, 1); | | | 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 | recoverFinalize(p, pStmt); pStmt = recoverPreparePrintf(p, p->dbOut, "PRAGMA index_xinfo(%Q)", zName); while( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ int iField = sqlite3_column_int(pStmt, 0); int iCol = sqlite3_column_int(pStmt, 1); assert( iField<pNew->nCol && iCol<pNew->nCol ); pNew->aCol[iCol].iField = iField; pNew->bIntkey = 0; iPk = -2; } recoverFinalize(p, pStmt); |
︙ | ︙ |
Changes to ext/rtree/rtree.c.
︙ | ︙ | |||
467 468 469 470 471 472 473 | ** ** For best performance, an attempt is made to guess at the byte-order ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined ** at run-time. */ #ifndef SQLITE_BYTEORDER | | | | | | | < | | | | | 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 | ** ** For best performance, an attempt is made to guess at the byte-order ** using C-preprocessor macros. If that is unsuccessful, or if ** -DSQLITE_RUNTIME_BYTEORDER=1 is set, then byte-order is determined ** at run-time. */ #ifndef SQLITE_BYTEORDER #if defined(i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ defined(_M_AMD64) || defined(_M_ARM) || defined(__x86) || \ defined(__arm__) # define SQLITE_BYTEORDER 1234 #elif defined(sparc) || defined(__ppc__) # define SQLITE_BYTEORDER 4321 #else # define SQLITE_BYTEORDER 0 /* 0 means "unknown at compile-time" */ #endif #endif /* What version of MSVC is being used. 0 means MSVC is not being used */ #ifndef MSVC_VERSION #if defined(_MSC_VER) && !defined(SQLITE_DISABLE_INTRINSIC) # define MSVC_VERSION _MSC_VER |
︙ | ︙ |
Changes to ext/rtree/rtree6.test.
︙ | ︙ | |||
100 101 102 103 104 105 106 | } do_eqp_test rtree6.2.4.1 { SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10 } { QUERY PLAN |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1 | < < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 | } do_eqp_test rtree6.2.4.1 { SELECT * FROM t1,t2 WHERE v=+ii and x1<10 and x2>10 } { QUERY PLAN |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1 `--SEARCH t2 USING AUTOMATIC COVERING INDEX (v=?) } do_eqp_test rtree6.2.4.2 { SELECT * FROM t1,t2 WHERE v=10 and x1<10 and x2>10 } { QUERY PLAN |--SCAN t1 VIRTUAL TABLE INDEX 2:C0E1 `--SEARCH t2 USING AUTOMATIC PARTIAL COVERING INDEX (v=?) } do_eqp_test rtree6.2.5 { SELECT * FROM t1,t2 WHERE k=ii AND x1<v } { QUERY PLAN |
︙ | ︙ |
Changes to ext/session/session2.test.
︙ | ︙ | |||
187 188 189 190 191 192 193 | CREATE TABLE t1(a int PRIMARY KEY, b); CREATE TABLE t2(a, b INTEGER PRIMARY KEY); CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); CREATE TABLE t4(a, b, PRIMARY KEY(b, a)); } foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] { | | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | CREATE TABLE t1(a int PRIMARY KEY, b); CREATE TABLE t2(a, b INTEGER PRIMARY KEY); CREATE TABLE t3(a, b, c, PRIMARY KEY(a, b)); CREATE TABLE t4(a, b, PRIMARY KEY(b, a)); } foreach {tn sql} [string map {%T1% t1 %T2% t2 %T3% t3 %T4% t4} $set_of_tests] { do_then_apply_sql $sql do_test 2.$tn { compare_db db db2 } {} } # The following block of tests is similar to the last, except that the # session object is recording changes made to an attached database. The # main database contains a table of the same name as the table being # modified within the attached db. |
︙ | ︙ | |||
594 595 596 597 598 599 600 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e, f); WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<32 ) INSERT INTO t1 SELECT NULL, 0, 0, 0, 0, 0 FROM s } | | | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c, d, e, f); WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<32 ) INSERT INTO t1 SELECT NULL, 0, 0, 0, 0, 0 FROM s } do_then_apply_sql { UPDATE t1 SET f=f+1 WHERE a=1; UPDATE t1 SET e=e+1 WHERE a=2; UPDATE t1 SET e=e+1, f=f+1 WHERE a=3; UPDATE t1 SET d=d+1 WHERE a=4; UPDATE t1 SET d=d+1, f=f+1 WHERE a=5; UPDATE t1 SET d=d+1, e=e+1 WHERE a=6; UPDATE t1 SET d=d+1, e=e+1, f=f+1 WHERE a=7; |
︙ | ︙ |
Changes to ext/session/sessionD.test.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 | lappend cols "quote($x(name))" } set cols [join $cols ,] append txt [db eval "SELECT $cols FROM $tab ORDER BY $cols"] } return [md5 $txt] } # Ensure that the diff produced by comparing the current contents of [db] # with itself is empty. proc do_empty_diff_test {tn} { forcedelete test.db2 forcecopy test.db test.db2 | > > > > > > > > > > > > > > > > > > > > > > > > | 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 | lappend cols "quote($x(name))" } set cols [join $cols ,] append txt [db eval "SELECT $cols FROM $tab ORDER BY $cols"] } return [md5 $txt] } proc do_diff_test {tn setup} { reset_db forcedelete test.db2 execsql { ATTACH 'test.db2' AS aux } execsql $setup sqlite3session S db main foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { S attach $tbl S diff aux $tbl } set C [S changeset] S delete sqlite3 db2 test.db2 sqlite3changeset_apply db2 $C "" uplevel do_test $tn.1 [list {execsql { PRAGMA integrity_check } db2}] ok db2 close set cksum [scksum db main] uplevel do_test $tn.2 [list {scksum db aux}] [list $cksum] } # Ensure that the diff produced by comparing the current contents of [db] # with itself is empty. proc do_empty_diff_test {tn} { forcedelete test.db2 forcecopy test.db test.db2 |
︙ | ︙ |
Changes to ext/session/sessionG.test.
︙ | ︙ | |||
30 31 32 33 34 35 36 | do_test 1.0 { do_common_sql { CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t1 VALUES(3, 'three'); } | | | | | 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 | do_test 1.0 { do_common_sql { CREATE TABLE t1(a PRIMARY KEY, b UNIQUE); INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); INSERT INTO t1 VALUES(3, 'three'); } do_then_apply_sql { DELETE FROM t1 WHERE a=1; INSERT INTO t1 VALUES(4, 'one'); } compare_db db db2 } {} do_test 1.1 { do_then_apply_sql { DELETE FROM t1 WHERE a=4; INSERT INTO t1 VALUES(1, 'one'); } compare_db db db2 } {} do_test 1.2 { execsql { INSERT INTO t1 VALUES(5, 'five') } db2 do_then_apply_sql { INSERT INTO t1 VALUES(11, 'eleven'); INSERT INTO t1 VALUES(12, 'five'); } execsql { SELECT * FROM t1 } db2 } {2 two 3 three 1 one 5 five 11 eleven} do_test 1.3 { |
︙ | ︙ | |||
78 79 80 81 82 83 84 | } } {} do_test 2.2.1 { # It is not possible to apply the changeset generated by the following # SQL, as none of the three updated rows may be updated as part of the # first pass. | | | 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | } } {} do_test 2.2.1 { # It is not possible to apply the changeset generated by the following # SQL, as none of the three updated rows may be updated as part of the # first pass. do_then_apply_sql { UPDATE t1 SET b=0 WHERE a=1; UPDATE t1 SET b=1 WHERE a=2; UPDATE t1 SET b=2 WHERE a=3; UPDATE t1 SET b=3 WHERE a=1; } db2 eval { SELECT a, b FROM t1 } } {1 1 2 2 3 3} |
︙ | ︙ | |||
105 106 107 108 109 110 111 | INSERT INTO t1 VALUES(1, 1, 1); INSERT INTO t1 VALUES(2, 2, 2); INSERT INTO t1 VALUES(3, 3, 3); } } {} do_test 3.3 { | | | | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | INSERT INTO t1 VALUES(1, 1, 1); INSERT INTO t1 VALUES(2, 2, 2); INSERT INTO t1 VALUES(3, 3, 3); } } {} do_test 3.3 { do_then_apply_sql { UPDATE t1 SET b=4 WHERE a=3; UPDATE t1 SET b=3 WHERE a=2; UPDATE t1 SET b=2 WHERE a=1; } compare_db db db2 } {} do_test 3.4 { do_then_apply_sql { UPDATE t1 SET b=1 WHERE a=1; UPDATE t1 SET b=2 WHERE a=2; UPDATE t1 SET b=3 WHERE a=3; } compare_db db db2 } {} |
︙ | ︙ | |||
144 145 146 147 148 149 150 | INSERT INTO t2 VALUES(1, 1); INSERT INTO t2 VALUES(2, 2); INSERT INTO t2 VALUES(3, 3); } } {} do_test 4.2 { | | | | 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 | INSERT INTO t2 VALUES(1, 1); INSERT INTO t2 VALUES(2, 2); INSERT INTO t2 VALUES(3, 3); } } {} do_test 4.2 { do_then_apply_sql { UPDATE t1 SET b=4 WHERE a=3; UPDATE t1 SET b=3 WHERE a=2; UPDATE t1 SET b=2 WHERE a=1; UPDATE t2 SET b=0 WHERE a=1; UPDATE t2 SET b=1 WHERE a=2; UPDATE t2 SET b=2 WHERE a=3; } compare_db db db2 } {} do_test 4.3 { do_then_apply_sql { UPDATE t1 SET b=1 WHERE a=1; UPDATE t1 SET b=2 WHERE a=2; UPDATE t1 SET b=3 WHERE a=3; UPDATE t2 SET b=3 WHERE a=3; UPDATE t2 SET b=2 WHERE a=2; UPDATE t2 SET b=1 WHERE a=1; |
︙ | ︙ | |||
187 188 189 190 191 192 193 | do_execsql_test -db db2 5.0.2 { CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE TABLE t2(a, b, c); CREATE TABLE t3(a, b PRIMARY KEY, c); } do_test 5.1 { | | | 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | do_execsql_test -db db2 5.0.2 { CREATE TABLE t1(a PRIMARY KEY, b, c); CREATE TABLE t2(a, b, c); CREATE TABLE t3(a, b PRIMARY KEY, c); } do_test 5.1 { do_then_apply_sql { INSERT INTO t1 VALUES(1, 2, 3); INSERT INTO t2 VALUES(4, 5, 6); INSERT INTO t3 VALUES(7, 8, 9); } db2 eval { SELECT * FROM t1; |
︙ | ︙ |
Changes to ext/session/sessionH.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | forcedelete test.db2 sqlite3 db2 test.db2 do_test 1.0 { do_common_sql { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); } | | | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | forcedelete test.db2 sqlite3 db2 test.db2 do_test 1.0 { do_common_sql { CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); } do_then_apply_sql { WITH s(i) AS ( VALUES(1) UNION ALL SELECT i+1 FROM s WHERe i<10000 ) INSERT INTO t1 SELECT 'abcde', randomblob(16), i FROM s; } compare_db db db2 } {} |
︙ | ︙ |
Changes to ext/session/session_common.tcl.
︙ | ︙ | |||
48 49 50 51 52 53 54 | proc xConflict {args} [subst -nocommands { lappend ::xConflict [set args] return $O(-policy) }] proc bgerror {args} { set ::background_error $args } sqlite3session S db main | < | 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | proc xConflict {args} [subst -nocommands { lappend ::xConflict [set args] return $O(-policy) }] proc bgerror {args} { set ::background_error $args } sqlite3session S db main foreach t $O(-tables) { S attach $t } execsql $O(-sql) set ::xConflict [list] sqlite3changeset_apply db2 [S changeset] xConflict set conflicts [list] |
︙ | ︙ | |||
78 79 80 81 82 83 84 | proc changeset_from_sql {sql {dbname main}} { if {$dbname == "main"} { return [sql_exec_changeset db $sql] } set rc [catch { sqlite3session S db $dbname | < | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | proc changeset_from_sql {sql {dbname main}} { if {$dbname == "main"} { return [sql_exec_changeset db $sql] } set rc [catch { sqlite3session S db $dbname db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { S attach $name } db eval $sql S changeset } changeset] catch { S delete } |
︙ | ︙ | |||
110 111 112 113 114 115 116 | if {$rc} { error $patchset } return $patchset } | < < | < < < < < < < < < < < < < < < < < < < < | < < | < | < < < < < < < < < < < | 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 | if {$rc} { error $patchset } return $patchset } proc do_then_apply_sql {sql {dbname main}} { proc xConflict args { return "OMIT" } set rc [catch { sqlite3session S db $dbname db eval "SELECT name FROM $dbname.sqlite_master WHERE type = 'table'" { S attach $name } db eval $sql sqlite3changeset_apply db2 [S changeset] xConflict } msg] catch { S delete } if {$rc} {error $msg} } proc do_iterator_test {tn tbl_list sql res} { sqlite3session S db main if {[llength $tbl_list]==0} { S attach * } foreach t $tbl_list {S attach $t} execsql $sql set r [list] foreach v $res { lappend r $v } set x [list] sqlite3session_foreach c [S changeset] { lappend x $c } uplevel do_test $tn [list [list set {} $x]] [list $r] S delete } # Compare the contents of all tables in [db1] and [db2]. Throw an error if |
︙ | ︙ | |||
247 248 249 250 251 252 253 | if {$n>0} { append txt " [lindex $::ones $n]" } set txt [string trim $txt] if {$txt==""} {set txt zero} return $txt } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 209 210 211 212 213 214 215 | if {$n>0} { append txt " [lindex $::ones $n]" } set txt [string trim $txt] if {$txt==""} {set txt zero} return $txt } |
Changes to ext/session/sessionat.test.
︙ | ︙ | |||
106 107 108 109 110 111 112 | do_execsql_test $tn.3.0 { CREATE TABLE t3(a, b, PRIMARY KEY(b)) %WR%; } do_execsql_test -db db2 $tn.3.1 { CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%; } do_test $tn.3.2 { | | | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | do_execsql_test $tn.3.0 { CREATE TABLE t3(a, b, PRIMARY KEY(b)) %WR%; } do_execsql_test -db db2 $tn.3.1 { CREATE TABLE t3(a, b, c DEFAULT 'D', PRIMARY KEY(b)) %WR%; } do_test $tn.3.2 { do_then_apply_sql { INSERT INTO t3 VALUES(1, 2); INSERT INTO t3 VALUES(3, 4); INSERT INTO t3 VALUES(5, 6); }; db2 eval {SELECT * FROM t3} } {1 2 D 3 4 D 5 6 D} do_test $tn.3.3 { do_then_apply_sql { UPDATE t3 SET a=45 WHERE b=4; DELETE FROM t3 WHERE a=5; }; db2 eval {SELECT * FROM t3} } {1 2 D 45 4 D} #----------------------------------------------------------------------- |
︙ | ︙ | |||
249 250 251 252 253 254 255 | do_execsql_test $tn.7.0 { CREATE TABLE t8(a PRIMARY KEY, b, c); } do_execsql_test -db db2 $tn.7.1 { CREATE TABLE t8(a PRIMARY KEY, b, c, d DEFAULT 'D', e DEFAULT 'E'); } | | | | | | 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 | do_execsql_test $tn.7.0 { CREATE TABLE t8(a PRIMARY KEY, b, c); } do_execsql_test -db db2 $tn.7.1 { CREATE TABLE t8(a PRIMARY KEY, b, c, d DEFAULT 'D', e DEFAULT 'E'); } do_then_apply_sql { INSERT INTO t8 VALUES(1, 2, 3); INSERT INTO t8 VALUES(4, 5, 6); } do_execsql_test $tn.7.2.1 { SELECT * FROM t8 } {1 2 3 4 5 6} do_execsql_test -db db2 $tn.7.2.2 { SELECT * FROM t8 } {1 2 3 D E 4 5 6 D E} do_then_apply_sql { UPDATE t8 SET c=45 WHERE a=4; } do_execsql_test $tn.7.3.1 { SELECT * FROM t8 } {1 2 3 4 5 45} do_execsql_test -db db2 $tn.7.3.2 { SELECT * FROM t8 } {1 2 3 D E 4 5 45 D E} #----------------------------------------------------------------------- reset_test do_execsql_test $tn.8.0 { CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h); } do_execsql_test -db db2 $tn.8.1 { CREATE TABLE t9(a PRIMARY KEY, b, c, d, e, f, g, h, i, j, k, l); } do_then_apply_sql { INSERT INTO t9 VALUES(1, 2, 3, 4, 5, 6, 7, 8); } do_then_apply_sql { UPDATE t9 SET h=450 WHERE a=1 } do_execsql_test -db db2 $tn.8.2 { SELECT * FROM t9 } {1 2 3 4 5 6 7 450 {} {} {} {}} do_then_apply_sql { UPDATE t9 SET h=NULL } do_execsql_test -db db2 $tn.8.2 { SELECT * FROM t9 } {1 2 3 4 5 6 7 {} {} {} {} {}} }] } |
︙ | ︙ |
Changes to ext/session/sessionbig.test.
︙ | ︙ | |||
39 40 41 42 43 44 45 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } do_execsql_test -db db2 1.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } do_test 1.2 { | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } do_execsql_test -db db2 1.1 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } do_test 1.2 { do_then_apply_sql { INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); |
︙ | ︙ | |||
67 68 69 70 71 72 73 | do_test 1.3 { execsql { DELETE FROM t1 } execsql2 { DELETE FROM t1 } } {} do_test 1.4 { set rc [catch { | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | do_test 1.3 { execsql { DELETE FROM t1 } execsql2 { DELETE FROM t1 } } {} do_test 1.4 { set rc [catch { do_then_apply_sql { INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); INSERT INTO t1(b) VALUES( zeroblob(100*1000*1000) ); |
︙ | ︙ |
Changes to ext/session/sessionfault.test.
︙ | ︙ | |||
40 41 42 43 44 45 46 | # do_faultsim_test 1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { | | | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | # do_faultsim_test 1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { do_then_apply_sql { INSERT INTO t1 VALUES('a string value', 8, 9); UPDATE t1 SET c = 10 WHERE a = 1; DELETE FROM t1 WHERE a = 4; } } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} faultsim_integrity_check |
︙ | ︙ |
Changes to ext/session/sessionfault2.test.
︙ | ︙ | |||
128 129 130 131 132 133 134 | do_faultsim_test 1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { | | | 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | do_faultsim_test 1.1 -faults oom-* -prep { catch {db2 close} catch {db close} faultsim_restore_and_reopen sqlite3 db2 test.db2 } -body { do_then_apply_sql { INSERT INTO sqlite_stat1 VALUES('x', 'y', 45); UPDATE sqlite_stat1 SET stat = 123 WHERE tbl='t1' AND idx='i1'; UPDATE sqlite_stat1 SET stat = 456 WHERE tbl='t2'; } } -test { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} faultsim_integrity_check |
︙ | ︙ |
Deleted ext/session/sessionnoop2.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/session/sessionrebase.test.
︙ | ︙ | |||
80 81 82 83 84 85 86 | forcedelete test.db2 test.db2-journal test.db2-wal forcecopy test.db test.db2 sqlite3 db2 test.db2 db eval BEGIN sqlite3session S1 db main | < < < | 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 | forcedelete test.db2 test.db2-journal test.db2-wal forcecopy test.db test.db2 sqlite3 db2 test.db2 db eval BEGIN sqlite3session S1 db main S1 attach * execsql $sql1 db set c1 [S1 changeset] S1 delete if {$i==1} { sqlite3session S2 db2 main S2 attach * execsql $sql2 db2 set c2 [S2 changeset] S2 delete } else { set c2 [list] foreach sql [split $sql2 ";"] { if {[string is space $sql]} continue sqlite3session S2 db2 main S2 attach * execsql $sql db2 lappend c2 [S2 changeset] S2 delete } } |
︙ | ︙ | |||
339 340 341 342 343 344 345 | do_rebase_test 2.2.3 { UPDATE t2 SET x=1, y='one' WHERE z='B' } { UPDATE t2 SET y='two' WHERE z='B'; } { OMIT } { SELECT * FROM t2 WHERE z='B' } { 1 one B } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 336 337 338 339 340 341 342 343 344 345 346 347 348 349 | do_rebase_test 2.2.3 { UPDATE t2 SET x=1, y='one' WHERE z='B' } { UPDATE t2 SET y='two' WHERE z='B'; } { OMIT } { SELECT * FROM t2 WHERE z='B' } { 1 one B } #------------------------------------------------------------------------- reset_db do_execsql_test 3.0 { CREATE TABLE t3(a, b, c, PRIMARY KEY(b, c)); CREATE TABLE abcdefghijkl(x PRIMARY KEY, y, z); |
︙ | ︙ |
Deleted ext/session/sessionrowid.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/session/sessionsize.test.
︙ | ︙ | |||
109 110 111 112 113 114 115 | do_execsql_test 3.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } do_test 3.1 { sqlite3session S db main | | | | | | | | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | do_execsql_test 3.0 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b); } do_test 3.1 { sqlite3session S db main S object_config_size -1 } 1 do_test 3.2.1 { S object_config_size 0 } 0 do_test 3.2.2 { S object_config_size -1 } 0 do_test 3.2.3 { S object_config_size 1 } 1 do_test 3.2.4 { S object_config_size -1 } 1 do_test 3.3 { S attach t1 } {} do_test 3.4 { S object_config_size 1 } {SQLITE_MISUSE} do_test 3.4 { S object_config_size -1 } {1} S delete finish_test |
Changes to ext/session/sessionstat1.test.
︙ | ︙ | |||
78 79 80 81 82 83 84 | CREATE INDEX t1b ON t1(b); CREATE INDEX t1c ON t1(c); ANALYZE; } } {} do_test 2.1 { | | | | | 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 | CREATE INDEX t1b ON t1(b); CREATE INDEX t1c ON t1(c); ANALYZE; } } {} do_test 2.1 { do_then_apply_sql { WITH s(i) AS ( SELECT 0 UNION ALL SELECT i+1 FROM s WHERE (i+1)<32 ) INSERT INTO t1 SELECT i, i%8, i%2 FROM s; ANALYZE; } } {} do_execsql_test -db db2 2.2 { SELECT * FROM sqlite_stat1 } { t1 sqlite_autoindex_t1_1 {32 1} t1 t1b {32 4} t1 t1c {32 16} } do_test 2.3 { do_then_apply_sql { DROP INDEX t1c } } {} do_execsql_test -db db2 2.4 { SELECT * FROM sqlite_stat1 } { t1 sqlite_autoindex_t1_1 {32 1} t1 t1b {32 4} } do_test 2.3 { do_then_apply_sql { DROP TABLE t1 } } {} do_execsql_test -db db2 2.4 { SELECT * FROM sqlite_stat1 } { } |
︙ | ︙ | |||
149 150 151 152 153 154 155 | db null null db2 null null do_execsql_test 3.2 { SELECT * FROM sqlite_stat1; } {t1 null 4} do_test 3.3 { execsql { DELETE FROM sqlite_stat1 } | | | | | 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | db null null db2 null null do_execsql_test 3.2 { SELECT * FROM sqlite_stat1; } {t1 null 4} do_test 3.3 { execsql { DELETE FROM sqlite_stat1 } do_then_apply_sql { ANALYZE } execsql { SELECT * FROM sqlite_stat1 } db2 } {t1 null 4} do_test 3.4 { execsql { INSERT INTO t1 VALUES(5,5,5) } do_then_apply_sql { ANALYZE } execsql { SELECT * FROM sqlite_stat1 } db2 } {t1 null 5} do_test 3.5 { do_then_apply_sql { DROP TABLE t1 } execsql { SELECT * FROM sqlite_stat1 } db2 } {} do_test 3.6.1 { execsql { CREATE TABLE t1(a, b, c); CREATE TABLE t2(x, y, z); |
︙ | ︙ |
Changes to ext/session/sqlite3session.c.
︙ | ︙ | |||
21 22 23 24 25 26 27 | # ifdef SQLITE_TEST # define SESSIONS_STRM_CHUNK_SIZE 64 # else # define SESSIONS_STRM_CHUNK_SIZE 1024 # endif #endif | < < | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # ifdef SQLITE_TEST # define SESSIONS_STRM_CHUNK_SIZE 64 # else # define SESSIONS_STRM_CHUNK_SIZE 1024 # endif #endif static int sessions_strm_chunk_size = SESSIONS_STRM_CHUNK_SIZE; typedef struct SessionHook SessionHook; struct SessionHook { void *pCtx; int (*xOld)(void*,int,sqlite3_value**); int (*xNew)(void*,int,sqlite3_value**); |
︙ | ︙ | |||
44 45 46 47 48 49 50 | struct sqlite3_session { sqlite3 *db; /* Database handle session is attached to */ char *zDb; /* Name of database session is attached to */ int bEnableSize; /* True if changeset_size() enabled */ int bEnable; /* True if currently recording */ int bIndirect; /* True if all changes are indirect */ int bAutoAttach; /* True to auto-attach tables */ | < | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | struct sqlite3_session { sqlite3 *db; /* Database handle session is attached to */ char *zDb; /* Name of database session is attached to */ int bEnableSize; /* True if changeset_size() enabled */ int bEnable; /* True if currently recording */ int bIndirect; /* True if all changes are indirect */ int bAutoAttach; /* True to auto-attach tables */ int rc; /* Non-zero if an error has occurred */ void *pFilterCtx; /* First argument to pass to xTableFilter */ int (*xTableFilter)(void *pCtx, const char *zTab); i64 nMalloc; /* Number of bytes of data allocated */ i64 nMaxChangesetSize; sqlite3_value *pZeroBlob; /* Value containing X'' */ sqlite3_session *pNext; /* Next session object on same db. */ |
︙ | ︙ | |||
121 122 123 124 125 126 127 | ** start of the session. Or no initial values if the row was inserted. */ struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ int nCol; /* Number of columns in table zName */ int bStat1; /* True if this is sqlite_stat1 */ | < | 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | ** start of the session. Or no initial values if the row was inserted. */ struct SessionTable { SessionTable *pNext; char *zName; /* Local name of table */ int nCol; /* Number of columns in table zName */ int bStat1; /* True if this is sqlite_stat1 */ const char **azCol; /* Column names */ u8 *abPK; /* Array of primary key flags */ int nEntry; /* Total number of entries in hash table */ int nChange; /* Size of apChange[] array */ SessionChange **apChange; /* Hash table buckets */ }; |
︙ | ︙ | |||
514 515 516 517 518 519 520 | ** ** If an error occurs, an SQLite error code is returned and the final values ** of *piHash asn *pbNullPK are undefined. Otherwise, SQLITE_OK is returned ** and the output variables are set as described above. */ static int sessionPreupdateHash( sqlite3_session *pSession, /* Session object that owns pTab */ | < < < < < | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | ** ** If an error occurs, an SQLite error code is returned and the final values ** of *piHash asn *pbNullPK are undefined. Otherwise, SQLITE_OK is returned ** and the output variables are set as described above. */ static int sessionPreupdateHash( sqlite3_session *pSession, /* Session object that owns pTab */ SessionTable *pTab, /* Session table handle */ int bNew, /* True to hash the new.* PK */ int *piHash, /* OUT: Hash value */ int *pbNullPK /* OUT: True if there are NULL values in PK */ ){ unsigned int h = 0; /* Hash value to return */ int i; /* Used to iterate through columns */ assert( *pbNullPK==0 ); assert( pTab->nCol==pSession->hook.xCount(pSession->hook.pCtx) ); for(i=0; i<pTab->nCol; i++){ if( pTab->abPK[i] ){ int rc; int eType; sqlite3_value *pVal; if( bNew ){ rc = pSession->hook.xNew(pSession->hook.pCtx, i, &pVal); }else{ rc = pSession->hook.xOld(pSession->hook.pCtx, i, &pVal); } if( rc!=SQLITE_OK ) return rc; eType = sqlite3_value_type(pVal); h = sessionHashAppendType(h, eType); if( eType==SQLITE_INTEGER || eType==SQLITE_FLOAT ){ i64 iVal; if( eType==SQLITE_INTEGER ){ iVal = sqlite3_value_int64(pVal); }else{ double rVal = sqlite3_value_double(pVal); assert( sizeof(iVal)==8 && sizeof(rVal)==8 ); memcpy(&iVal, &rVal, 8); } h = sessionHashAppendI64(h, iVal); }else if( eType==SQLITE_TEXT || eType==SQLITE_BLOB ){ const u8 *z; int n; if( eType==SQLITE_TEXT ){ z = (const u8 *)sqlite3_value_text(pVal); }else{ z = (const u8 *)sqlite3_value_blob(pVal); } n = sqlite3_value_bytes(pVal); if( !z && (eType!=SQLITE_BLOB || n>0) ) return SQLITE_NOMEM; h = sessionHashAppendBlob(h, n, z); }else{ assert( eType==SQLITE_NULL ); assert( pTab->bStat1==0 || i!=1 ); *pbNullPK = 1; } } } *piHash = (h % pTab->nChange); return SQLITE_OK; } |
︙ | ︙ | |||
852 853 854 855 856 857 858 | ** It determines if the current pre-update-hook change affects the same row ** as the change stored in argument pChange. If so, it returns true. Otherwise ** if the pre-update-hook does not affect the same row as pChange, it returns ** false. */ static int sessionPreupdateEqual( sqlite3_session *pSession, /* Session object that owns SessionTable */ | < < < < < < | 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 | ** It determines if the current pre-update-hook change affects the same row ** as the change stored in argument pChange. If so, it returns true. Otherwise ** if the pre-update-hook does not affect the same row as pChange, it returns ** false. */ static int sessionPreupdateEqual( sqlite3_session *pSession, /* Session object that owns SessionTable */ SessionTable *pTab, /* Table associated with change */ SessionChange *pChange, /* Change to compare to */ int op /* Current pre-update operation */ ){ int iCol; /* Used to iterate through columns */ u8 *a = pChange->aRecord; /* Cursor used to scan change record */ assert( op==SQLITE_INSERT || op==SQLITE_UPDATE || op==SQLITE_DELETE ); for(iCol=0; iCol<pTab->nCol; iCol++){ if( !pTab->abPK[iCol] ){ a += sessionSerialLen(a); }else{ sqlite3_value *pVal; /* Value returned by preupdate_new/old */ int rc; /* Error code from preupdate_new/old */ |
︙ | ︙ | |||
1009 1010 1011 1012 1013 1014 1015 | sqlite3_session *pSession, /* For memory accounting. May be NULL */ sqlite3 *db, /* Database connection */ const char *zDb, /* Name of attached database (e.g. "main") */ const char *zThis, /* Table name */ int *pnCol, /* OUT: number of columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ | | < < | 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 | sqlite3_session *pSession, /* For memory accounting. May be NULL */ sqlite3 *db, /* Database connection */ const char *zDb, /* Name of attached database (e.g. "main") */ const char *zThis, /* Table name */ int *pnCol, /* OUT: number of columns */ const char **pzTab, /* OUT: Copy of zThis */ const char ***pazCol, /* OUT: Array of column names for table */ u8 **pabPK /* OUT: Array of booleans - true for PK col */ ){ char *zPragma; sqlite3_stmt *pStmt; int rc; sqlite3_int64 nByte; int nDbCol = 0; int nThis; int i; u8 *pAlloc = 0; char **azCol = 0; u8 *abPK = 0; assert( pazCol && pabPK ); nThis = sqlite3Strlen30(zThis); if( nThis==12 && 0==sqlite3_stricmp("sqlite_stat1", zThis) ){ rc = sqlite3_table_column_metadata(db, zDb, zThis, 0, 0, 0, 0, 0, 0); if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
1067 1068 1069 1070 1071 1072 1073 | *pabPK = 0; *pnCol = 0; if( pzTab ) *pzTab = 0; return rc; } nByte = nThis + 1; | < < < < < | 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 | *pabPK = 0; *pnCol = 0; if( pzTab ) *pzTab = 0; return rc; } nByte = nThis + 1; while( SQLITE_ROW==sqlite3_step(pStmt) ){ nByte += sqlite3_column_bytes(pStmt, 1); nDbCol++; } rc = sqlite3_reset(pStmt); if( rc==SQLITE_OK ){ nByte += nDbCol * (sizeof(const char *) + sizeof(u8) + 1); pAlloc = sessionMalloc64(pSession, nByte); if( pAlloc==0 ){ rc = SQLITE_NOMEM; |
︙ | ︙ | |||
1097 1098 1099 1100 1101 1102 1103 | if( pzTab ){ memcpy(pAlloc, zThis, nThis+1); *pzTab = (char *)pAlloc; pAlloc += nThis+1; } i = 0; | < < < < < < < < > < | 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 | if( pzTab ){ memcpy(pAlloc, zThis, nThis+1); *pzTab = (char *)pAlloc; pAlloc += nThis+1; } i = 0; while( SQLITE_ROW==sqlite3_step(pStmt) ){ int nName = sqlite3_column_bytes(pStmt, 1); const unsigned char *zName = sqlite3_column_text(pStmt, 1); if( zName==0 ) break; memcpy(pAlloc, zName, nName+1); azCol[i] = (char *)pAlloc; pAlloc += nName+1; abPK[i] = sqlite3_column_int(pStmt, 5); i++; } rc = sqlite3_reset(pStmt); } /* If successful, populate the output variables. Otherwise, zero them and ** free any allocation made. An error code will be returned in this case. */ if( rc==SQLITE_OK ){ *pazCol = (const char **)azCol; *pabPK = abPK; *pnCol = nDbCol; }else{ *pazCol = 0; *pabPK = 0; *pnCol = 0; if( pzTab ) *pzTab = 0; sessionFree(pSession, azCol); } sqlite3_finalize(pStmt); return rc; } /* ** This function is only called from within a pre-update handler for a ** write to table pTab, part of session pSession. If this is the first |
︙ | ︙ | |||
1154 1155 1156 1157 1158 1159 1160 | ** is set to NULL in this case. */ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, | | < | 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 | ** is set to NULL in this case. */ static int sessionInitTable(sqlite3_session *pSession, SessionTable *pTab){ if( pTab->nCol==0 ){ u8 *abPK; assert( pTab->azCol==0 || pTab->abPK==0 ); pSession->rc = sessionTableInfo(pSession, pSession->db, pSession->zDb, pTab->zName, &pTab->nCol, 0, &pTab->azCol, &abPK ); if( pSession->rc==SQLITE_OK ){ int i; for(i=0; i<pTab->nCol; i++){ if( abPK[i] ){ pTab->abPK = abPK; break; |
︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 | int op, sqlite3_session *pSession, /* Session object pTab is attached to */ SessionTable *pTab, /* Table that change applies to */ SessionChange *pC /* Update pC->nMaxSize */ ){ i64 nNew = 2; if( pC->op==SQLITE_INSERT ){ | < < < < < | | | 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 | int op, sqlite3_session *pSession, /* Session object pTab is attached to */ SessionTable *pTab, /* Table that change applies to */ SessionChange *pC /* Update pC->nMaxSize */ ){ i64 nNew = 2; if( pC->op==SQLITE_INSERT ){ if( op!=SQLITE_DELETE ){ int ii; for(ii=0; ii<pTab->nCol; ii++){ sqlite3_value *p = 0; pSession->hook.xNew(pSession->hook.pCtx, ii, &p); sessionSerializeValue(0, p, &nNew); } } }else if( op==SQLITE_DELETE ){ nNew += pC->nRecord; if( sqlite3_preupdate_blobwrite(pSession->db)>=0 ){ nNew += pC->nRecord; } }else{ int ii; u8 *pCsr = pC->aRecord; for(ii=0; ii<pTab->nCol; ii++){ int bChanged = 1; int nOld = 0; int eType; sqlite3_value *p = 0; pSession->hook.xNew(pSession->hook.pCtx, ii, &p); if( p==0 ){ return SQLITE_NOMEM; } eType = *pCsr++; switch( eType ){ case SQLITE_NULL: |
︙ | ︙ | |||
1332 1333 1334 1335 1336 1337 1338 | ** (UPDATE, INSERT, DELETE) is specified by the first argument. ** ** Unless one is already present or an error occurs, an entry is added ** to the changed-rows hash table associated with table pTab. */ static void sessionPreupdateOneChange( int op, /* One of SQLITE_UPDATE, INSERT, DELETE */ | < | | 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 | ** (UPDATE, INSERT, DELETE) is specified by the first argument. ** ** Unless one is already present or an error occurs, an entry is added ** to the changed-rows hash table associated with table pTab. */ static void sessionPreupdateOneChange( int op, /* One of SQLITE_UPDATE, INSERT, DELETE */ sqlite3_session *pSession, /* Session object pTab is attached to */ SessionTable *pTab /* Table that change applies to */ ){ int iHash; int bNull = 0; int rc = SQLITE_OK; SessionStat1Ctx stat1 = {{0,0,0,0,0},0}; if( pSession->rc ) return; /* Load table details if required */ if( sessionInitTable(pSession, pTab) ) return; /* Check the number of columns in this xPreUpdate call matches the ** number of columns in the table. */ if( pTab->nCol!=pSession->hook.xCount(pSession->hook.pCtx) ){ pSession->rc = SQLITE_SCHEMA; return; } /* Grow the hash table if required */ if( sessionGrowHash(pSession, 0, pTab) ){ pSession->rc = SQLITE_NOMEM; |
︙ | ︙ | |||
1381 1382 1383 1384 1385 1386 1387 | pSession->pZeroBlob = p; } } /* Calculate the hash-key for this change. If the primary key of the row ** includes a NULL value, exit early. Such changes are ignored by the ** session module. */ | | < < | | < < < < < < < < | | 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 | pSession->pZeroBlob = p; } } /* Calculate the hash-key for this change. If the primary key of the row ** includes a NULL value, exit early. Such changes are ignored by the ** session module. */ rc = sessionPreupdateHash(pSession, pTab, op==SQLITE_INSERT, &iHash, &bNull); if( rc!=SQLITE_OK ) goto error_out; if( bNull==0 ){ /* Search the hash table for an existing record for this row. */ SessionChange *pC; for(pC=pTab->apChange[iHash]; pC; pC=pC->pNext){ if( sessionPreupdateEqual(pSession, pTab, pC, op) ) break; } if( pC==0 ){ /* Create a new change object containing all the old values (if ** this is an SQLITE_UPDATE or SQLITE_DELETE), or just the PK ** values (if this is an INSERT). */ sqlite3_int64 nByte; /* Number of bytes to allocate */ int i; /* Used to iterate through columns */ assert( rc==SQLITE_OK ); pTab->nEntry++; /* Figure out how large an allocation is required */ nByte = sizeof(SessionChange); for(i=0; i<pTab->nCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); assert( trc==SQLITE_OK ); }else if( pTab->abPK[i] ){ TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); assert( trc==SQLITE_OK ); } /* This may fail if SQLite value p contains a utf-16 string that must ** be converted to utf-8 and an OOM error occurs while doing so. */ rc = sessionSerializeValue(0, p, &nByte); if( rc!=SQLITE_OK ) goto error_out; } /* Allocate the change object */ pC = (SessionChange *)sessionMalloc64(pSession, nByte); if( !pC ){ rc = SQLITE_NOMEM; goto error_out; }else{ memset(pC, 0, sizeof(SessionChange)); pC->aRecord = (u8 *)&pC[1]; } /* Populate the change object. None of the preupdate_old(), ** preupdate_new() or SerializeValue() calls below may fail as all ** required values and encodings have already been cached in memory. ** It is not possible for an OOM to occur in this block. */ nByte = 0; for(i=0; i<pTab->nCol; i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ pSession->hook.xOld(pSession->hook.pCtx, i, &p); }else if( pTab->abPK[i] ){ pSession->hook.xNew(pSession->hook.pCtx, i, &p); } sessionSerializeValue(&pC->aRecord[nByte], p, &nByte); |
︙ | ︙ | |||
1559 1560 1561 1562 1563 1564 1565 | if( pSession->bEnable==0 ) continue; if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; pSession->rc = sessionFindTable(pSession, zName, &pTab); if( pTab ){ assert( pSession->rc==SQLITE_OK ); | < | | | 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 | if( pSession->bEnable==0 ) continue; if( pSession->rc ) continue; if( sqlite3_strnicmp(zDb, pSession->zDb, nDb+1) ) continue; pSession->rc = sessionFindTable(pSession, zName, &pTab); if( pTab ){ assert( pSession->rc==SQLITE_OK ); sessionPreupdateOneChange(op, pSession, pTab); if( op==SQLITE_UPDATE ){ sessionPreupdateOneChange(SQLITE_INSERT, pSession, pTab); } } } } /* ** The pre-update hook implementations. |
︙ | ︙ | |||
1601 1602 1603 1604 1605 1606 1607 | pSession->hook.xCount = sessionPreupdateCount; pSession->hook.xDepth = sessionPreupdateDepth; } typedef struct SessionDiffCtx SessionDiffCtx; struct SessionDiffCtx { sqlite3_stmt *pStmt; | < | | | | 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 | pSession->hook.xCount = sessionPreupdateCount; pSession->hook.xDepth = sessionPreupdateDepth; } typedef struct SessionDiffCtx SessionDiffCtx; struct SessionDiffCtx { sqlite3_stmt *pStmt; int nOldOff; }; /* ** The diff hook implementations. */ static int sessionDiffOld(void *pCtx, int iVal, sqlite3_value **ppVal){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; *ppVal = sqlite3_column_value(p->pStmt, iVal+p->nOldOff); return SQLITE_OK; } static int sessionDiffNew(void *pCtx, int iVal, sqlite3_value **ppVal){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; *ppVal = sqlite3_column_value(p->pStmt, iVal); return SQLITE_OK; } static int sessionDiffCount(void *pCtx){ SessionDiffCtx *p = (SessionDiffCtx*)pCtx; return p->nOldOff ? p->nOldOff : sqlite3_column_count(p->pStmt); } static int sessionDiffDepth(void *pCtx){ (void)pCtx; return 0; } /* |
︙ | ︙ | |||
1699 1700 1701 1702 1703 1704 1705 | return zRet; } static char *sessionSelectFindNew( const char *zDb1, /* Pick rows in this db only */ const char *zDb2, /* But not in this one */ | < < | | | < < < < | < < < < < < < < < < < < < < < < < < < < < < < | | | < | < | < < > | 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 | return zRet; } static char *sessionSelectFindNew( const char *zDb1, /* Pick rows in this db only */ const char *zDb2, /* But not in this one */ const char *zTbl, /* Table name */ const char *zExpr ){ char *zRet = sqlite3_mprintf( "SELECT * FROM \"%w\".\"%w\" WHERE NOT EXISTS (" " SELECT 1 FROM \"%w\".\"%w\" WHERE %s" ")", zDb1, zTbl, zDb2, zTbl, zExpr ); return zRet; } static int sessionDiffFindNew( int op, sqlite3_session *pSession, SessionTable *pTab, const char *zDb1, const char *zDb2, char *zExpr ){ int rc = SQLITE_OK; char *zStmt = sessionSelectFindNew(zDb1, zDb2, pTab->zName,zExpr); if( zStmt==0 ){ rc = SQLITE_NOMEM; }else{ sqlite3_stmt *pStmt; rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); if( rc==SQLITE_OK ){ SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; pDiffCtx->pStmt = pStmt; pDiffCtx->nOldOff = 0; while( SQLITE_ROW==sqlite3_step(pStmt) ){ sessionPreupdateOneChange(op, pSession, pTab); } rc = sqlite3_finalize(pStmt); } sqlite3_free(zStmt); } return rc; } static int sessionDiffFindModified( sqlite3_session *pSession, SessionTable *pTab, const char *zFrom, const char *zExpr ){ int rc = SQLITE_OK; char *zExpr2 = sessionExprCompareOther(pTab->nCol, pSession->zDb, zFrom, pTab->zName, pTab->azCol, pTab->abPK ); if( zExpr2==0 ){ rc = SQLITE_NOMEM; }else{ char *zStmt = sqlite3_mprintf( "SELECT * FROM \"%w\".\"%w\", \"%w\".\"%w\" WHERE %s AND (%z)", pSession->zDb, pTab->zName, zFrom, pTab->zName, zExpr, zExpr2 ); if( zStmt==0 ){ rc = SQLITE_NOMEM; }else{ sqlite3_stmt *pStmt; rc = sqlite3_prepare(pSession->db, zStmt, -1, &pStmt, 0); if( rc==SQLITE_OK ){ SessionDiffCtx *pDiffCtx = (SessionDiffCtx*)pSession->hook.pCtx; pDiffCtx->pStmt = pStmt; pDiffCtx->nOldOff = pTab->nCol; while( SQLITE_ROW==sqlite3_step(pStmt) ){ sessionPreupdateOneChange(SQLITE_UPDATE, pSession, pTab); } rc = sqlite3_finalize(pStmt); } sqlite3_free(zStmt); } } return rc; } int sqlite3session_diff( sqlite3_session *pSession, |
︙ | ︙ | |||
1847 1848 1849 1850 1851 1852 1853 | } /* Check the table schemas match */ if( rc==SQLITE_OK ){ int bHasPk = 0; int bMismatch = 0; int nCol; /* Columns in zFrom.zTbl */ | < | < < | 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 | } /* Check the table schemas match */ if( rc==SQLITE_OK ){ int bHasPk = 0; int bMismatch = 0; int nCol; /* Columns in zFrom.zTbl */ u8 *abPK; const char **azCol = 0; rc = sessionTableInfo(0, db, zFrom, zTbl, &nCol, 0, &azCol, &abPK); if( rc==SQLITE_OK ){ if( pTo->nCol!=nCol ){ bMismatch = 1; }else{ int i; for(i=0; i<nCol; i++){ if( pTo->abPK[i]!=abPK[i] ) bMismatch = 1; |
︙ | ︙ | |||
2194 2195 2196 2197 2198 2199 2200 | */ static void sessionAppendStr( SessionBuffer *p, const char *zStr, int *pRc ){ int nStr = sqlite3Strlen30(zStr); | | < | 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 | */ static void sessionAppendStr( SessionBuffer *p, const char *zStr, int *pRc ){ int nStr = sqlite3Strlen30(zStr); if( 0==sessionBufferGrow(p, nStr, pRc) ){ memcpy(&p->aBuf[p->nBuf], zStr, nStr); p->nBuf += nStr; } } /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append the string representation of integer iVal ** to the buffer. No nul-terminator is written. |
︙ | ︙ | |||
2219 2220 2221 2222 2223 2224 2225 | int *pRc /* IN/OUT: Error code */ ){ char aBuf[24]; sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); sessionAppendStr(p, aBuf, pRc); } | < < < < < < < < < < < < < < < < < < < < < | < | 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 | int *pRc /* IN/OUT: Error code */ ){ char aBuf[24]; sqlite3_snprintf(sizeof(aBuf)-1, aBuf, "%d", iVal); sessionAppendStr(p, aBuf, pRc); } /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwise, append the string zStr enclosed in quotes (") and ** with any embedded quote characters escaped to the buffer. No ** nul-terminator byte is written. ** ** If an OOM condition is encountered, set *pRc to SQLITE_NOMEM before ** returning. */ static void sessionAppendIdent( SessionBuffer *p, /* Buffer to a append to */ const char *zStr, /* String to quote, escape and append */ int *pRc /* IN/OUT: Error code */ ){ int nStr = sqlite3Strlen30(zStr)*2 + 2 + 1; if( 0==sessionBufferGrow(p, nStr, pRc) ){ char *zOut = (char *)&p->aBuf[p->nBuf]; const char *zIn = zStr; *zOut++ = '"'; while( *zIn ){ if( *zIn=='"' ) *zOut++ = '"'; *zOut++ = *(zIn++); } *zOut++ = '"'; p->nBuf = (int)((u8 *)zOut - p->aBuf); } } /* ** This function is a no-op if *pRc is other than SQLITE_OK when it is ** called. Otherwse, it appends the serialized version of the value stored ** in column iCol of the row that SQL statement pStmt currently points |
︙ | ︙ | |||
2401 2402 2403 2404 2405 2406 2407 | bChanged = 1; } } /* If at least one field has been modified, this is not a no-op. */ if( bChanged ) bNoop = 0; | | | 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 | bChanged = 1; } } /* If at least one field has been modified, this is not a no-op. */ if( bChanged ) bNoop = 0; /* Add a field to the old.* record. This is omitted if this modules is ** currently generating a patchset. */ if( bPatchset==0 ){ if( bChanged || abPK[i] ){ sessionAppendBlob(pBuf, pCsr, nAdvance, &rc); }else{ sessionAppendByte(pBuf, 0, &rc); } |
︙ | ︙ | |||
2490 2491 2492 2493 2494 2495 2496 | return rc; } /* ** Formulate and prepare a SELECT statement to retrieve a row from table ** zTab in database zDb based on its primary key. i.e. ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > < < < < | 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 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 2439 2440 2441 2442 2443 | return rc; } /* ** Formulate and prepare a SELECT statement to retrieve a row from table ** zTab in database zDb based on its primary key. i.e. ** ** SELECT * FROM zDb.zTab WHERE pk1 = ? AND pk2 = ? AND ... */ static int sessionSelectStmt( sqlite3 *db, /* Database handle */ const char *zDb, /* Database name */ const char *zTab, /* Table name */ int nCol, /* Number of columns in table */ const char **azCol, /* Names of table columns */ u8 *abPK, /* PRIMARY KEY array */ sqlite3_stmt **ppStmt /* OUT: Prepared SELECT statement */ ){ int rc = SQLITE_OK; char *zSql = 0; int nSql = -1; if( 0==sqlite3_stricmp("sqlite_stat1", zTab) ){ zSql = sqlite3_mprintf( "SELECT tbl, ?2, stat FROM %Q.sqlite_stat1 WHERE tbl IS ?1 AND " "idx IS (CASE WHEN ?2=X'' THEN NULL ELSE ?2 END)", zDb ); if( zSql==0 ) rc = SQLITE_NOMEM; }else{ int i; const char *zSep = ""; SessionBuffer buf = {0, 0, 0}; sessionAppendStr(&buf, "SELECT * FROM ", &rc); sessionAppendIdent(&buf, zDb, &rc); sessionAppendStr(&buf, ".", &rc); sessionAppendIdent(&buf, zTab, &rc); sessionAppendStr(&buf, " WHERE ", &rc); for(i=0; i<nCol; i++){ if( abPK[i] ){ sessionAppendStr(&buf, zSep, &rc); sessionAppendIdent(&buf, azCol[i], &rc); sessionAppendStr(&buf, " IS ?", &rc); sessionAppendInteger(&buf, i+1, &rc); zSep = " AND "; } } zSql = (char*)buf.aBuf; nSql = buf.nBuf; } if( rc==SQLITE_OK ){ rc = sqlite3_prepare_v2(db, zSql, nSql, ppStmt, 0); } sqlite3_free(zSql); return rc; } /* ** Bind the PRIMARY KEY values from the change passed in argument pChange ** to the SELECT statement passed as the first argument. The SELECT statement ** is as prepared by function sessionSelectStmt(). |
︙ | ︙ | |||
2737 2738 2739 2740 2741 2742 2743 | int nCol = 0; /* Number of columns in table */ u8 *abPK = 0; /* Primary key array */ const char **azCol = 0; /* Table columns */ int i; /* Used to iterate through hash buckets */ sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ int nRewind = buf.nBuf; /* Initial size of write buffer */ int nNoop; /* Size of buffer after writing tbl header */ | < | < < < < < < | < | < | 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 | int nCol = 0; /* Number of columns in table */ u8 *abPK = 0; /* Primary key array */ const char **azCol = 0; /* Table columns */ int i; /* Used to iterate through hash buckets */ sqlite3_stmt *pSel = 0; /* SELECT statement to query table pTab */ int nRewind = buf.nBuf; /* Initial size of write buffer */ int nNoop; /* Size of buffer after writing tbl header */ /* Check the table schema is still Ok. */ rc = sessionTableInfo(0, db, pSession->zDb, zName, &nCol, 0,&azCol,&abPK); if( !rc && (pTab->nCol!=nCol || memcmp(abPK, pTab->abPK, nCol)) ){ rc = SQLITE_SCHEMA; } /* Write a table header */ sessionAppendTableHdr(&buf, bPatchset, pTab, &rc); /* Build and compile a statement to execute: */ if( rc==SQLITE_OK ){ rc = sessionSelectStmt( db, pSession->zDb, zName, nCol, azCol, abPK, &pSel); } nNoop = buf.nBuf; for(i=0; i<pTab->nChange && rc==SQLITE_OK; i++){ SessionChange *p; /* Used to iterate through changes */ for(p=pTab->apChange[i]; rc==SQLITE_OK && p; p=p->pNext){ |
︙ | ︙ | |||
2842 2843 2844 2845 2846 2847 2848 | sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ){ int rc; if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE; | | | 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 | sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ){ int rc; if( pnChangeset==0 || ppChangeset==0 ) return SQLITE_MISUSE; rc = sessionGenerateChangeset(pSession, 0, 0, 0, pnChangeset,ppChangeset); assert( rc || pnChangeset==0 || pSession->bEnableSize==0 || *pnChangeset<=pSession->nMaxChangesetSize ); return rc; } /* |
︙ | ︙ | |||
2960 2961 2962 2963 2964 2965 2966 | pSession->bEnableSize = (iArg!=0); } } *(int*)pArg = pSession->bEnableSize; break; } | < < < < < < < < < < < < < | 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 | pSession->bEnableSize = (iArg!=0); } } *(int*)pArg = pSession->bEnableSize; break; } default: rc = SQLITE_MISUSE; } return rc; } |
︙ | ︙ | |||
3961 3962 3963 3964 3965 3966 3967 | int bStat1; /* True if table is sqlite_stat1 */ int bDeferConstraints; /* True to defer constraints */ int bInvertConstraints; /* Invert when iterating constraints buffer */ SessionBuffer constraints; /* Deferred constraints are stored here */ SessionBuffer rebase; /* Rebase information (if any) here */ u8 bRebaseStarted; /* If table header is already in rebase */ u8 bRebase; /* True to collect rebase information */ | < < | 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 | int bStat1; /* True if table is sqlite_stat1 */ int bDeferConstraints; /* True to defer constraints */ int bInvertConstraints; /* Invert when iterating constraints buffer */ SessionBuffer constraints; /* Deferred constraints are stored here */ SessionBuffer rebase; /* Rebase information (if any) here */ u8 bRebaseStarted; /* If table header is already in rebase */ u8 bRebase; /* True to collect rebase information */ }; /* Number of prepared UPDATE statements to cache. */ #define SESSION_UPDATE_CACHE_SZ 12 /* ** Find a prepared UPDATE statement suitable for the UPDATE step currently |
︙ | ︙ | |||
4213 4214 4215 4216 4217 4218 4219 | ** pointing to the prepared version of the SQL statement. */ static int sessionSelectRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ SessionApplyCtx *p /* Session changeset-apply context */ ){ | < | | < | 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 | ** pointing to the prepared version of the SQL statement. */ static int sessionSelectRow( sqlite3 *db, /* Database handle */ const char *zTab, /* Table name */ SessionApplyCtx *p /* Session changeset-apply context */ ){ return sessionSelectStmt( db, "main", zTab, p->nCol, p->azCol, p->abPK, &p->pSelect); } /* ** Formulate and prepare an INSERT statement to add a record to table zTab. ** For example: ** ** INSERT INTO main."zTab" VALUES(?1, ?2, ?3 ...); |
︙ | ︙ | |||
4375 4376 4377 4378 4379 4380 4381 | ** ** If the iterator currently points to an INSERT record, bind values from the ** new.* record to the SELECT statement. Or, if it points to a DELETE or ** UPDATE, bind values from the old.* record. */ static int sessionSeekToRow( sqlite3_changeset_iter *pIter, /* Changeset iterator */ | | > < < | < < < < < < < < < < < < | 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 | ** ** If the iterator currently points to an INSERT record, bind values from the ** new.* record to the SELECT statement. Or, if it points to a DELETE or ** UPDATE, bind values from the old.* record. */ static int sessionSeekToRow( sqlite3_changeset_iter *pIter, /* Changeset iterator */ u8 *abPK, /* Primary key flags array */ sqlite3_stmt *pSelect /* SELECT statement from sessionSelectRow() */ ){ int rc; /* Return code */ int nCol; /* Number of columns in table */ int op; /* Changset operation (SQLITE_UPDATE etc.) */ const char *zDummy; /* Unused */ sqlite3changeset_op(pIter, &zDummy, &nCol, &op, 0); rc = sessionBindRow(pIter, op==SQLITE_INSERT ? sqlite3changeset_new : sqlite3changeset_old, nCol, abPK, pSelect ); if( rc==SQLITE_OK ){ rc = sqlite3_step(pSelect); if( rc!=SQLITE_ROW ) rc = sqlite3_reset(pSelect); } return rc; } |
︙ | ︙ | |||
4516 4517 4518 4519 4520 4521 4522 | assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA ); assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT ); assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND ); /* Bind the new.* PRIMARY KEY values to the SELECT statement. */ if( pbReplace ){ | | < < < < < | | | < | 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 | assert( eType==SQLITE_CHANGESET_CONFLICT || eType==SQLITE_CHANGESET_DATA ); assert( SQLITE_CHANGESET_CONFLICT+1==SQLITE_CHANGESET_CONSTRAINT ); assert( SQLITE_CHANGESET_DATA+1==SQLITE_CHANGESET_NOTFOUND ); /* Bind the new.* PRIMARY KEY values to the SELECT statement. */ if( pbReplace ){ rc = sessionSeekToRow(pIter, p->abPK, p->pSelect); }else{ rc = SQLITE_OK; } if( rc==SQLITE_ROW ){ /* There exists another row with the new.* primary key. */ pIter->pConflict = p->pSelect; res = xConflict(pCtx, eType, pIter); pIter->pConflict = 0; rc = sqlite3_reset(p->pSelect); }else if( rc==SQLITE_OK ){ if( p->bDeferConstraints && eType==SQLITE_CHANGESET_CONFLICT ){ /* Instead of invoking the conflict handler, append the change blob ** to the SessionApplyCtx.constraints buffer. */ u8 *aBlob = &pIter->in.aData[pIter->in.iCurrent]; int nBlob = pIter->in.iNext - pIter->in.iCurrent; |
︙ | ︙ | |||
4639 4640 4641 4642 4643 4644 4645 | if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK)); } if( rc!=SQLITE_OK ) return rc; sqlite3_step(p->pDelete); rc = sqlite3_reset(p->pDelete); | | | 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 | if( rc==SQLITE_OK && sqlite3_bind_parameter_count(p->pDelete)>nCol ){ rc = sqlite3_bind_int(p->pDelete, nCol+1, (pbRetry==0 || abPK)); } if( rc!=SQLITE_OK ) return rc; sqlite3_step(p->pDelete); rc = sqlite3_reset(p->pDelete); if( rc==SQLITE_OK && sqlite3_changes(p->db)==0 ){ rc = sessionConflictHandler( SQLITE_CHANGESET_DATA, p, pIter, xConflict, pCtx, pbRetry ); }else if( (rc&0xff)==SQLITE_CONSTRAINT ){ rc = sessionConflictHandler( SQLITE_CHANGESET_CONFLICT, p, pIter, xConflict, pCtx, 0 ); |
︙ | ︙ | |||
4696 4697 4698 4699 4700 4701 4702 | }else{ assert( op==SQLITE_INSERT ); if( p->bStat1 ){ /* Check if there is a conflicting row. For sqlite_stat1, this needs ** to be done using a SELECT, as there is no PRIMARY KEY in the ** database schema to throw an exception if a duplicate is inserted. */ | | | 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 | }else{ assert( op==SQLITE_INSERT ); if( p->bStat1 ){ /* Check if there is a conflicting row. For sqlite_stat1, this needs ** to be done using a SELECT, as there is no PRIMARY KEY in the ** database schema to throw an exception if a duplicate is inserted. */ rc = sessionSeekToRow(pIter, p->abPK, p->pSelect); if( rc==SQLITE_ROW ){ rc = SQLITE_CONSTRAINT; sqlite3_reset(p->pSelect); } } if( rc==SQLITE_OK ){ |
︙ | ︙ | |||
4873 4874 4875 4876 4877 4878 4879 | assert( xConflict!=0 ); pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); sApply.bRebase = (ppRebase && pnRebase); sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); | < | 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 | assert( xConflict!=0 ); pIter->in.bNoDiscard = 1; memset(&sApply, 0, sizeof(sApply)); sApply.bRebase = (ppRebase && pnRebase); sApply.bInvertConstraints = !!(flags & SQLITE_CHANGESETAPPLY_INVERT); sqlite3_mutex_enter(sqlite3_db_mutex(db)); if( (flags & SQLITE_CHANGESETAPPLY_NOSAVEPOINT)==0 ){ rc = sqlite3_exec(db, "SAVEPOINT changeset_apply", 0, 0, 0); } if( rc==SQLITE_OK ){ rc = sqlite3_exec(db, "PRAGMA defer_foreign_keys = 1", 0, 0, 0); } |
︙ | ︙ | |||
4911 4912 4913 4914 4915 4916 4917 | sApply.pSelect = 0; sApply.nCol = 0; sApply.azCol = 0; sApply.abPK = 0; sApply.bStat1 = 0; sApply.bDeferConstraints = 1; sApply.bRebaseStarted = 0; | < | | | 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 | sApply.pSelect = 0; sApply.nCol = 0; sApply.azCol = 0; sApply.abPK = 0; sApply.bStat1 = 0; sApply.bDeferConstraints = 1; sApply.bRebaseStarted = 0; memset(&sApply.constraints, 0, sizeof(SessionBuffer)); /* If an xFilter() callback was specified, invoke it now. If the ** xFilter callback returns zero, skip this table. If it returns ** non-zero, proceed. */ schemaMismatch = (xFilter && (0==xFilter(pCtx, zNew))); if( schemaMismatch ){ zTab = sqlite3_mprintf("%s", zNew); if( zTab==0 ){ rc = SQLITE_NOMEM; break; } nTab = (int)strlen(zTab); sApply.azCol = (const char **)zTab; }else{ int nMinCol = 0; int i; sqlite3changeset_pk(pIter, &abPK, 0); rc = sessionTableInfo(0, db, "main", zNew, &sApply.nCol, &zTab, &sApply.azCol, &sApply.abPK ); if( rc!=SQLITE_OK ) break; for(i=0; i<sApply.nCol; i++){ if( sApply.abPK[i] ) nMinCol = i+1; } if( sApply.nCol==0 ){ |
︙ | ︙ |
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
76 77 78 79 80 81 82 | ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ void sqlite3session_delete(sqlite3_session *pSession); /* | | | | < < < < | | | | | < < < < < < < < < > | < | 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 | ** Session objects must be deleted before the database handle to which they ** are attached is closed. Refer to the documentation for ** [sqlite3session_create()] for details. */ void sqlite3session_delete(sqlite3_session *pSession); /* ** CAPIREF: Conigure a Session Object ** METHOD: sqlite3_session ** ** This method is used to configure a session object after it has been ** created. At present the only valid value for the second parameter is ** [SQLITE_SESSION_OBJCONFIG_SIZE]. ** ** Arguments for sqlite3session_object_config() ** ** The following values may passed as the the 4th parameter to ** sqlite3session_object_config(). ** ** <dt>SQLITE_SESSION_OBJCONFIG_SIZE <dd> ** This option is used to set, clear or query the flag that enables ** the [sqlite3session_changeset_size()] API. Because it imposes some ** computational overhead, this API is disabled by default. Argument ** pArg must point to a value of type (int). If the value is initially ** 0, then the sqlite3session_changeset_size() API is disabled. If it ** is greater than 0, then the same API is enabled. Or, if the initial ** value is less than zero, no change is made. In all cases the (int) ** variable is set to 1 if the sqlite3session_changeset_size() API is ** enabled following the current call, or 0 otherwise. ** ** It is an error (SQLITE_MISUSE) to attempt to modify this setting after ** the first table has been attached to the session object. */ int sqlite3session_object_config(sqlite3_session*, int op, void *pArg); /* */ #define SQLITE_SESSION_OBJCONFIG_SIZE 1 /* ** CAPI3REF: Enable Or Disable A Session Object ** METHOD: sqlite3_session ** ** Enable or disable the recording of changes by a session object. When ** enabled, a session object records changes made to the database. When |
︙ | ︙ | |||
1252 1253 1254 1255 1256 1257 1258 | ** caller has an open transaction or savepoint when apply_v2() is called, ** it may revert the partially applied changeset by rolling it back. ** ** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> ** Invert the changeset before applying it. This is equivalent to inverting ** a changeset using sqlite3changeset_invert() before applying it. It is ** an error to specify this flag with a patchset. | < < < < < < < < < < < < < < | 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 | ** caller has an open transaction or savepoint when apply_v2() is called, ** it may revert the partially applied changeset by rolling it back. ** ** <dt>SQLITE_CHANGESETAPPLY_INVERT <dd> ** Invert the changeset before applying it. This is equivalent to inverting ** a changeset using sqlite3changeset_invert() before applying it. It is ** an error to specify this flag with a patchset. */ #define SQLITE_CHANGESETAPPLY_NOSAVEPOINT 0x0001 #define SQLITE_CHANGESETAPPLY_INVERT 0x0002 /* ** CAPI3REF: Constants Passed To The Conflict Handler ** ** Values that may be passed as the second argument to a conflict-handler. ** ** <dl> |
︙ | ︙ |
Changes to ext/session/test_session.c.
︙ | ︙ | |||
72 73 74 75 76 77 78 | sqlite3 *db, /* Database handle */ const char *zSql, /* SQL script to execute */ int *pnChangeset, /* OUT: Size of changeset blob in bytes */ void **ppChangeset /* OUT: Pointer to changeset blob */ ){ sqlite3_session *pSession = 0; int rc; | < < | 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | sqlite3 *db, /* Database handle */ const char *zSql, /* SQL script to execute */ int *pnChangeset, /* OUT: Size of changeset blob in bytes */ void **ppChangeset /* OUT: Pointer to changeset blob */ ){ sqlite3_session *pSession = 0; int rc; /* Create a new session object */ rc = sqlite3session_create(db, "main", &pSession); /* Configure the session object to record changes to all tables */ if( rc==SQLITE_OK ) rc = sqlite3session_attach(pSession, NULL); /* Execute the SQL script */ if( rc==SQLITE_OK ) rc = sqlite3_exec(db, zSql, 0, 0, 0); |
︙ | ︙ | |||
258 259 260 261 262 263 264 | { "indirect", 1, "BOOL", }, /* 4 */ { "isempty", 0, "", }, /* 5 */ { "table_filter", 1, "SCRIPT", }, /* 6 */ { "patchset", 0, "", }, /* 7 */ { "diff", 2, "FROMDB TBL", }, /* 8 */ { "memory_used", 0, "", }, /* 9 */ { "changeset_size", 0, "", }, /* 10 */ | | | 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 | { "indirect", 1, "BOOL", }, /* 4 */ { "isempty", 0, "", }, /* 5 */ { "table_filter", 1, "SCRIPT", }, /* 6 */ { "patchset", 0, "", }, /* 7 */ { "diff", 2, "FROMDB TBL", }, /* 8 */ { "memory_used", 0, "", }, /* 9 */ { "changeset_size", 0, "", }, /* 10 */ { "object_config_size", 1, "INTEGER", }, /* 11 */ { 0 } }; int iSub; int rc; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); |
︙ | ︙ | |||
377 378 379 380 381 382 383 | } case 10: { sqlite3_int64 nSize = sqlite3session_changeset_size(pSession); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize)); break; } | | < < < < < < < < < < < < < < | | > > | 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 | } case 10: { sqlite3_int64 nSize = sqlite3session_changeset_size(pSession); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(nSize)); break; } case 11: { int rc; int iArg; if( Tcl_GetIntFromObj(interp, objv[2], &iArg) ){ return TCL_ERROR; } rc = sqlite3session_object_config( pSession, SQLITE_SESSION_OBJCONFIG_SIZE, &iArg ); if( rc!=SQLITE_OK ){ extern const char *sqlite3ErrName(int); Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1)); }else{ Tcl_SetObjResult(interp, Tcl_NewIntObj(iArg)); } break; |
︙ | ︙ | |||
803 804 805 806 807 808 809 | void *pRebase = 0; int nRebase = 0; int flags = 0; /* Flags for apply_v2() */ memset(&sStr, 0, sizeof(sStr)); sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); | | | > > < < | > > > | | < < < | | > | | 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | void *pRebase = 0; int nRebase = 0; int flags = 0; /* Flags for apply_v2() */ memset(&sStr, 0, sizeof(sStr)); sStr.nStream = test_tcl_integer(interp, SESSION_STREAM_TCL_VAR); /* Check for the -nosavepoint flag */ if( bV2 ){ if( objc>1 ){ const char *z1 = Tcl_GetString(objv[1]); int n = strlen(z1); if( n>1 && n<=12 && 0==sqlite3_strnicmp("-nosavepoint", z1, n) ){ flags |= SQLITE_CHANGESETAPPLY_NOSAVEPOINT; objc--; objv++; } } if( objc>1 ){ const char *z1 = Tcl_GetString(objv[1]); int n = strlen(z1); if( n>1 && n<=7 && 0==sqlite3_strnicmp("-invert", z1, n) ){ flags |= SQLITE_CHANGESETAPPLY_INVERT; objc--; objv++; } } } if( objc!=4 && objc!=5 ){ const char *zMsg; if( bV2 ){ zMsg = "?-nosavepoint? ?-inverse? " "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; }else{ zMsg = "DB CHANGESET CONFLICT-SCRIPT ?FILTER-SCRIPT?"; } Tcl_WrongNumArgs(interp, 1, objv, zMsg); return TCL_ERROR; } |
︙ | ︙ |
Changes to ext/wasm/GNUmakefile.
︙ | ︙ | |||
40 41 42 43 44 45 46 | # # Significant TODOs for this build include, but are not necessarily # limited to: # # 1) Consolidate the code generation for sqlite3*.*js into a script # which generates the makefile code, rather than using $(call) and # $(eval), or at least centralize the setup of the numerous vars | | | < < | 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 | # # Significant TODOs for this build include, but are not necessarily # limited to: # # 1) Consolidate the code generation for sqlite3*.*js into a script # which generates the makefile code, rather than using $(call) and # $(eval), or at least centralize the setup of the numerous vars # related to each build variant (vanilla, esm, bundler-friendly). # SHELL := $(shell which bash 2>/dev/null) MAKEFILE := $(lastword $(MAKEFILE_LIST)) CLEAN_FILES := DISTCLEAN_FILES := ./--dummy-- default: all release: oz # Emscripten SDK home dir and related binaries... EMSDK_HOME ?= $(word 1,$(wildcard $(HOME)/emsdk $(HOME)/src/emsdk)) emcc.bin ?= $(word 1,$(wildcard $(EMSDK_HOME)/upstream/emscripten/emcc) $(shell which emcc)) ifeq (,$(emcc.bin)) $(error Cannot find emcc.) endif emcc.version := $(shell "$(emcc.bin)" --version | sed -n 1p \ |
︙ | ︙ | |||
143 144 145 146 147 148 149 | ifeq (,$(wildcard $(dir.dout))) dir._tmp := $(shell mkdir -p $(dir.dout)) endif ifeq (,$(wildcard $(dir.tmp))) dir._tmp := $(shell mkdir -p $(dir.tmp)) endif | < < < < < < < < < < < < | < < < < < < < | 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | ifeq (,$(wildcard $(dir.dout))) dir._tmp := $(shell mkdir -p $(dir.dout)) endif ifeq (,$(wildcard $(dir.tmp))) dir._tmp := $(shell mkdir -p $(dir.tmp)) endif sqlite3.c := $(dir.top)/sqlite3.c sqlite3.h := $(dir.top)/sqlite3.h # Most SQLITE_OPT flags are set in sqlite3-wasm.c but we need them # made explicit here for building speedtest1.c. SQLITE_OPT = \ -DSQLITE_ENABLE_FTS5 \ -DSQLITE_ENABLE_RTREE \ -DSQLITE_ENABLE_EXPLAIN_COMMENTS \ -DSQLITE_ENABLE_UNKNOWN_SQL_FUNCTION \ |
︙ | ︙ | |||
186 187 188 189 190 191 192 | -DSQLITE_OMIT_SHARED_CACHE \ -DSQLITE_OMIT_WAL \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=3 \ -DSQLITE_OS_KV_OPTIONAL=1 \ '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \ -DSQLITE_USE_URI=1 \ | | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 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 | -DSQLITE_OMIT_SHARED_CACHE \ -DSQLITE_OMIT_WAL \ -DSQLITE_THREADSAFE=0 \ -DSQLITE_TEMP_STORE=3 \ -DSQLITE_OS_KV_OPTIONAL=1 \ '-DSQLITE_DEFAULT_UNIX_VFS="unix-none"' \ -DSQLITE_USE_URI=1 \ -DSQLITE_WASM_ENABLE_C_TESTS $(sqlite3.c) $(sqlite3.h): $(MAKE) -C $(dir.top) sqlite3.c .PHONY: clean distclean clean: -rm -f $(CLEAN_FILES) distclean: clean -rm -f $(DISTCLEAN_FILES) ifeq (release,$(filter release,$(MAKECMDGOALS))) ifeq (,$(wasm-strip)) $(error Cannot make release-quality binary because wasm-strip is not available. \ See notes in the warning above) endif else $(info Development build. Use '$(MAKE) release' for a smaller release build.) endif # bin.version-info = binary to output various sqlite3 version info for # embedding in the JS files and in building the distribution zip file. # It must NOT be in $(dir.tmp) because we need it to survive the # cleanup process for the dist build to work properly. bin.version-info := $(dir.wasm)/version-info $(bin.version-info): $(dir.wasm)/version-info.c $(sqlite3.h) $(MAKEFILE) $(CC) -O0 -I$(dir.top) -o $@ $< DISTCLEAN_FILES += $(bin.version-info) # bin.stripcomments is used for stripping C/C++-style comments from JS # files. The JS files contain large chunks of documentation which we # don't need for all builds. That app's -k flag is of particular # importance here, as it allows us to retain the opening comment # blocks, which contain the license header and version info. |
︙ | ︙ | |||
302 303 304 305 306 307 308 | $$(bin.c-pp) -f $(1) -o $$@ $(3) CLEAN_FILES += $(2) endef # /end C-PP.FILTER ######################################################################## # cflags.common = C compiler flags for all builds | | | 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 | $$(bin.c-pp) -f $(1) -o $$@ $(3) CLEAN_FILES += $(2) endef # /end C-PP.FILTER ######################################################################## # cflags.common = C compiler flags for all builds cflags.common := -I. -I.. -I$(dir.top) # emcc.WASM_BIGINT = 1 for BigInt (C int64) support, else 0. The API # disables certain features if BigInt is not enabled and such builds # _are not tested_ on any regular basis. emcc.WASM_BIGINT ?= 1 # emcc_opt = optimization-related flags. These are primarily used by # the various oX targets. build times for -O levels higher than 0 are |
︙ | ︙ | |||
345 346 347 348 349 350 351 | # Much practice has demonstrated that -O2 consistently gives the best # runtime speeds, but not by a large enough factor to rule out use of # -Oz when small deliverable size is a priority. ######################################################################## # EXPORTED_FUNCTIONS.* = files for use with Emscripten's # -sEXPORTED_FUNCTION flag. | | < < < < | | | 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 | # Much practice has demonstrated that -O2 consistently gives the best # runtime speeds, but not by a large enough factor to rule out use of # -Oz when small deliverable size is a priority. ######################################################################## # EXPORTED_FUNCTIONS.* = files for use with Emscripten's # -sEXPORTED_FUNCTION flag. EXPORTED_FUNCTIONS.api.in := $(abspath $(dir.api)/EXPORTED_FUNCTIONS.sqlite3-api) EXPORTED_FUNCTIONS.api := $(dir.tmp)/EXPORTED_FUNCTIONS.api $(EXPORTED_FUNCTIONS.api): $(EXPORTED_FUNCTIONS.api.in) $(MAKEFILE) cp $(EXPORTED_FUNCTIONS.api.in) $@ # sqlite3-license-version.js = generated JS file with the license # header and version info. sqlite3-license-version.js := $(dir.tmp)/sqlite3-license-version.js # sqlite3-license-version-header.js = JS file containing only the # license header. sqlite3-license-version-header.js := $(dir.api)/sqlite3-license-version-header.js |
︙ | ︙ | |||
455 456 457 458 459 460 461 | emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api) emcc.exportedRuntimeMethods := \ -sEXPORTED_RUNTIME_METHODS=wasmMemory # wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY emcc.jsflags += $(emcc.exportedRuntimeMethods) emcc.jsflags += -sUSE_CLOSURE_COMPILER=0 emcc.jsflags += -sIMPORTED_MEMORY | > | | | < | | | < < | < < < < | | < < | 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | emcc.jsflags += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.api) emcc.exportedRuntimeMethods := \ -sEXPORTED_RUNTIME_METHODS=wasmMemory # wasmMemory ==> required by our code for use with -sIMPORTED_MEMORY emcc.jsflags += $(emcc.exportedRuntimeMethods) emcc.jsflags += -sUSE_CLOSURE_COMPILER=0 emcc.jsflags += -sIMPORTED_MEMORY ifeq (3.1.31,$(emcc.version)) emcc.jsflags += -sSTRICT_JS=0 $(warning Disabling -sSTRICT_JS for emcc $(emcc.version): \ https://github.com/emscripten-core/emscripten/issues/18610) else emcc.jsflags += -sSTRICT_JS=1 endif emcc.environment := -sENVIRONMENT=web,worker ######################################################################## # -sINITIAL_MEMORY: How much memory we need to start with is governed # at least in part by whether -sALLOW_MEMORY_GROWTH is enabled. If so, # we can start with less. If not, we need as much as we'll ever # possibly use (which, of course, we can't know for sure). Note, # however, that speedtest1 shows that performance for even moderate # workloads MAY suffer considerably if we start small and have to grow # at runtime. e.g. OPFS-backed (speedtest1 --size 75) take MAY take X # time with 16mb+ memory and 3X time when starting with 8MB. However, # such test results are inconsistent due to browser internals which # are opaque to us. emcc.jsflags += -sALLOW_MEMORY_GROWTH emcc.INITIAL_MEMORY.128 := 13107200 emcc.INITIAL_MEMORY.96 := 100663296 emcc.INITIAL_MEMORY.64 := 64225280 emcc.INITIAL_MEMORY.32 := 33554432 emcc.INITIAL_MEMORY.16 := 16777216 emcc.INITIAL_MEMORY.8 := 8388608 emcc.INITIAL_MEMORY ?= 16 ifeq (,$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY))) $(error emcc.INITIAL_MEMORY must be one of: 8, 16, 32, 64, 96, 128 (megabytes)) endif emcc.jsflags += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)) # /INITIAL_MEMORY ######################################################################## emcc.jsflags += $(emcc.environment) emcc.jsflags += -sSTACK_SIZE=512KB # ^^^ ACHTUNG: emsdk 3.1.27 reduced the default stack size from 5MB to # a mere 64KB, which leads to silent memory corruption via the kvvfs # VFS, which requires twice that for its xRead() and xWrite() methods. ######################################################################## # $(sqlite3.js.init-func) is the name Emscripten assigns our exported # module init/load function. This symbol name is hard-coded in # $(extern-post-js.js) as well as in numerous docs. # # "sqlite3InitModule" is the symbol we document for client use, so # that's the symbol name which must be exported, whether it comes from |
︙ | ︙ | |||
570 571 572 573 574 575 576 | # file. The result is that the generated JS file is, because of the # -g3 debugging info, _huge_. ######################################################################## $(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE) @echo "Making $@..." @{ \ | | | 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 | # file. The result is that the generated JS file is, because of the # -g3 debugging info, _huge_. ######################################################################## $(sqlite3-api-build-version.js): $(bin.version-info) $(MAKEFILE) @echo "Making $@..." @{ \ echo 'self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){'; \ echo -n ' sqlite3.version = '; \ $(bin.version-info) --json; \ echo ';'; \ echo '});'; \ } > $@ $(sqlite3-license-version.js): $(sqlite3.h) $(sqlite3-license-version-header.js) \ $(MAKEFILE) |
︙ | ︙ | |||
612 613 614 615 616 617 618 | echo "/* END FILE: $$i */"; \ done > $@ ######################################################################## # call-make-pre-post is a $(call)able which creates rules for # pre-js-$(1).js. $1 = the base name of the JS file on whose behalf | | | | < | | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 | echo "/* END FILE: $$i */"; \ done > $@ ######################################################################## # call-make-pre-post is a $(call)able which creates rules for # pre-js-$(1).js. $1 = the base name of the JS file on whose behalf # this pre-js is for (one of: sqlite3, sqlite3-wasmfs). $2 is the build # mode: one of (vanilla, esm, bundler-friendly). This sets up # --[extern-][pre/post]-js flags in $(pre-post-$(1).flags.$(2)) and # dependencies in $(pre-post-$(1).deps.$(2)). define call-make-pre-post pre-post-$(1).flags.$(2) ?= $$(dir.tmp)/pre-js-$(1)-$(2).js: $$(pre-js.js.$(2)) $$(MAKEFILE) cp $$(pre-js.js.$(2)) $$@ @if [ sqlite3-wasmfs = $(1) ]; then \ echo "delete Module[xNameOfInstantiateWasm] /*for WASMFS build*/;"; \ elif [ sqlite3 != $(1) ]; then \ |
︙ | ︙ | |||
641 642 643 644 645 646 647 | ######################################################################## # Undocumented Emscripten feature: if the target file extension is # "mjs", it defaults to ES6 module builds: # https://github.com/emscripten-core/emscripten/issues/14383 sqlite3.wasm := $(dir.dout)/sqlite3.wasm sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c | < | 575 576 577 578 579 580 581 582 583 584 585 586 587 588 | ######################################################################## # Undocumented Emscripten feature: if the target file extension is # "mjs", it defaults to ES6 module builds: # https://github.com/emscripten-core/emscripten/issues/14383 sqlite3.wasm := $(dir.dout)/sqlite3.wasm sqlite3-wasm.c := $(dir.api)/sqlite3-wasm.c # sqlite3-wasm.o vs sqlite3-wasm.c: building against the latter # (predictably) results in a slightly faster binary. We're close # enough to the target speed requirements that the 500ms makes a # difference, so we build all binaries against sqlite3-wasm.c instead # of building a shared copy of sqlite3-wasm.o to link against. ######################################################################## # SQLITE3.xJS.EXPORT-DEFAULT is part of SQLITE3-WASMFS.xJS.RECIPE and |
︙ | ︙ | |||
689 690 691 692 693 694 695 | pre-post-common.flags := \ --extern-pre-js=$(sqlite3-license-version.js) # pre-post-jses.deps.* = a list of dependencies for the # --[extern-][pre/post]-js files. pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js) ######################################################################## # SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces | | | | < < | > | < | < | | | | < < > < < | < < < < < < < < < < | | | | | < | | 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 | pre-post-common.flags := \ --extern-pre-js=$(sqlite3-license-version.js) # pre-post-jses.deps.* = a list of dependencies for the # --[extern-][pre/post]-js files. pre-post-jses.deps.common := $(extern-pre-js.js) $(sqlite3-license-version.js) ######################################################################## # SETUP_LIB_BUILD_MODE is a $(call)'able which sets up numerous pieces # for one of the build modes (vanilla, esm, bundler-friendly). # # $1 = build mode name # $2 = 1 for ESM build mode, else 0 # $3 = resulting sqlite-api JS/MJS file # $4 = resulting JS/MJS file # $5 = -D... flags for $(bin.c-pp) # $6 = emcc -sXYZ flags define SETUP_LIB_BUILD_MODE $(info Setting up build [$(1)]: $(4)) c-pp.D.$(1) := $(5) pre-js.js.$(1) := $$(dir.api)/pre-js.$(1).js $$(eval $$(call C-PP.FILTER,$$(pre-js.js.in),$$(pre-js.js.$(1)),$$(c-pp.D.$(1)))) post-js.js.$(1) := $$(dir.tmp)/post-js.$(1).js $$(eval $$(call C-PP.FILTER,$$(post-js.js.in),$$(post-js.js.$(1)),$$(c-pp.D.$(1)))) extern-post-js.js.$(1) := $$(dir.tmp)/extern-post-js.$(1).js $$(eval $$(call C-PP.FILTER,$$(extern-post-js.js.in),$$(extern-post-js.js.$(1)),$$(c-pp.D.$(1)))) pre-post-common.flags.$(1) := \ $$(pre-post-common.flags) \ --post-js=$$(post-js.js.$(1)) \ --extern-post-js=$$(extern-post-js.js.$(1)) pre-post-jses.deps.$(1) := $$(pre-post-jses.deps.common) \ $$(post-js.js.$(1)) $$(extern-post-js.js.$(1)) $$(eval $$(call call-make-pre-post,sqlite3,$(1))) emcc.flags.sqlite3.$(1) := $(6) $$(eval $$(call C-PP.FILTER, $$(sqlite3-api.js.in), $(3), $(5))) $(4): $(3) $(4): $(3) $$(MAKEFILE) $$(sqlite3-wasm.c) $$(EXPORTED_FUNCTIONS.api) $$(pre-post-sqlite3.deps.$(1)) @echo "Building $$@ ..." $$(emcc.bin) -o $$@ $$(emcc_opt_full) $$(emcc.flags) \ $$(emcc.jsflags) \ $$(pre-post-sqlite3.flags.$(1)) $$(emcc.flags.sqlite3.$(1)) \ $$(cflags.common) $$(SQLITE_OPT) $$(sqlite3-wasm.c) @$$(call SQLITE3.xJS.ESM-EXPORT-DEFAULT,$(2)) @if [ bundler-friendly = $(1) ]; then \ echo "Patching $(3) for sqlite3.wasm..."; \ rm -f $$(dir.dout)/sqlite3-bundler-friendly.wasm; \ sed -i -e 's/sqlite3-bundler-friendly.wasm/sqlite3.wasm/g' $$@ || exit $$$$?; \ fi chmod -x $$(sqlite3.wasm) $$(maybe-wasm-strip) $$(sqlite3.wasm) @ls -la $@ $$(sqlite3.wasm) all: $(4) quick: $(4) CLEAN_FILES += $(3) $(4) endef # ^^^ /SETUP_LIB_BUILD_MODE ######################################################################## sqlite3-api.js := $(dir.dout)/sqlite3-api.js sqlite3.js := $(dir.dout)/sqlite3.js sqlite3-api.mjs := $(dir.dout)/sqlite3-api.mjs sqlite3.mjs := $(dir.dout)/sqlite3.mjs sqlite3-api-bundler-friendly.mjs := $(dir.dout)/sqlite3-api-bundler-friendly.mjs sqlite3-bundler-friendly.mjs := $(dir.dout)/sqlite3-bundler-friendly.mjs # Maintenance reminder: careful not to introduce spaces around args $1, $2 #$(info $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js))) $(eval $(call SETUP_LIB_BUILD_MODE,vanilla,0, $(sqlite3-api.js), $(sqlite3.js))) $(eval $(call SETUP_LIB_BUILD_MODE,esm,1, $(sqlite3-api.mjs), $(sqlite3.mjs), \ -Dtarget=es6-module, -sEXPORT_ES6 -sUSE_ES6_IMPORT_META)) $(eval $(call SETUP_LIB_BUILD_MODE,bundler-friendly,1,\ $(sqlite3-api-bundler-friendly.mjs),$(sqlite3-bundler-friendly.mjs),\ $(c-pp.D.esm) -Dtarget=es6-bundler-friendly, $(emcc.flags.sqlite3.esm))) # The various -D... values used by *.c-pp.js include: # # -Dtarget=es6-module: for all ESM module builds # # -Dtarget=es6-module -Dtarget=es6-bundler-friendly: intended for # "bundler-friendly" ESM module build. These have some restrictions # on how URL() objects are constructed in some contexts: URLs which # refer to files which are part of this project must be references # as string literals so that bundlers' static-analysis tools can # find those files and include them in their bundles. # ######################################################################## ######################################################################## # We have to ensure that we do not build both $(sqlite3*.*js) in # parallel because both result in the creation of $(sqlite3.wasm). We # have no way to build just the .mjs file without also building the # .wasm file because the generated .mjs file has to include info about # the imports needed by the wasm file, so they have to be built # together. i.e. we're building $(sqlite3.wasm) multiple times, but # that's unavoidable (and harmless, just a waste of build time). $(sqlite3.wasm): $(sqlite3.js) $(sqlite3.mjs): $(sqlite3.js) $(sqlite3-bundler-friendly.mjs): $(sqlite3.mjs) CLEAN_FILES += $(sqlite3.wasm) ######################################################################## # We need separate copies of certain supplementary JS files for the # bundler-friendly build. Concretely, any supplemental JS files which # themselves use importScripts() or Workers or URL() constructors # which refer to other in-tree (m)JS files quire a bundler-friendly # copy. sqlite3-worker1.js.in := $(dir.api)/sqlite3-worker1.c-pp.js sqlite3-worker1-promiser.js.in := $(dir.api)/sqlite3-worker1-promiser.c-pp.js sqlite3-worker1.js := $(dir.dout)/sqlite3-worker1.js sqlite3-worker1-promiser.js := $(dir.dout)/sqlite3-worker1-promiser.js sqlite3-worker1-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-bundler-friendly.js sqlite3-worker1-promiser-bundler-friendly.js := $(dir.dout)/sqlite3-worker1-promiser-bundler-friendly.js $(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1.js))) $(eval $(call C-PP.FILTER,$(sqlite3-worker1.js.in),$(sqlite3-worker1-bundler-friendly.js),\ $(c-pp.D.bundler-friendly))) $(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),$(sqlite3-worker1-promiser.js))) $(eval $(call C-PP.FILTER,$(sqlite3-worker1-promiser.js.in),\ $(sqlite3-worker1-promiser-bundler-friendly.js),\ |
︙ | ︙ | |||
852 853 854 855 856 857 858 | emcc.speedtest1 := emcc.speedtest1 += -sENVIRONMENT=web emcc.speedtest1 += -sALLOW_MEMORY_GROWTH emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)) emcc.speedtest1.common += -sINVOKE_RUN=0 emcc.speedtest1.common += --no-entry emcc.speedtest1.common += -sABORTING_MALLOC | | | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | emcc.speedtest1 := emcc.speedtest1 += -sENVIRONMENT=web emcc.speedtest1 += -sALLOW_MEMORY_GROWTH emcc.speedtest1 += -sINITIAL_MEMORY=$(emcc.INITIAL_MEMORY.$(emcc.INITIAL_MEMORY)) emcc.speedtest1.common += -sINVOKE_RUN=0 emcc.speedtest1.common += --no-entry emcc.speedtest1.common += -sABORTING_MALLOC emcc.speedtest1.common += -sSTRICT_JS emcc.speedtest1.common += -sMODULARIZE emcc.speedtest1.common += -Wno-limited-postlink-optimizations EXPORTED_FUNCTIONS.speedtest1 := $(abspath $(dir.tmp)/EXPORTED_FUNCTIONS.speedtest1) emcc.speedtest1.common += -sSTACK_SIZE=512KB emcc.speedtest1.common += -sEXPORTED_FUNCTIONS=@$(EXPORTED_FUNCTIONS.speedtest1) emcc.speedtest1.common += $(emcc.exportedRuntimeMethods) emcc.speedtest1.common += -sALLOW_TABLE_GROWTH |
︙ | ︙ | |||
883 884 885 886 887 888 889 | # when you printf etc. # # and pending output is not flushed because it didn't end with a # newline (by design). The lesser of the two evils seems to be # -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app # which runs speedtest1 multiple times. | | | < | < | 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | # when you printf etc. # # and pending output is not flushed because it didn't end with a # newline (by design). The lesser of the two evils seems to be # -sEXIT_RUNTIME=1 but we need EXIT_RUNTIME=0 for the worker-based app # which runs speedtest1 multiple times. $(EXPORTED_FUNCTIONS.speedtest1): $(EXPORTED_FUNCTIONS.api) @echo "Making $@ ..." @{ echo _wasm_main; cat $(EXPORTED_FUNCTIONS.api); } > $@ speedtest1.js := $(dir.dout)/speedtest1.js speedtest1.wasm := $(dir.dout)/speedtest1.wasm cflags.speedtest1 := $(cflags.common) -DSQLITE_SPEEDTEST1_WASM speedtest1.cses := $(speedtest1.c) $(sqlite3-wasm.c) $(eval $(call call-make-pre-post,speedtest1,vanilla)) $(speedtest1.js): $(MAKEFILE) $(speedtest1.cses) \ $(pre-post-speedtest1.deps.vanilla) \ $(EXPORTED_FUNCTIONS.speedtest1) @echo "Building $@ ..." $(emcc.bin) \ $(emcc.speedtest1) $(emcc.speedtest1.common) \ $(cflags.speedtest1) $(pre-post-speedtest1.flags.vanilla) \ $(SQLITE_OPT) \ $(speedtest1.exit-runtime0) \ -o $@ $(speedtest1.cses) -lm $(maybe-wasm-strip) $(speedtest1.wasm) ls -la $@ $(speedtest1.wasm) speedtest1: $(speedtest1.js) all: speedtest1 |
︙ | ︙ |
Deleted ext/wasm/api/EXPORTED_FUNCTIONS.sqlite3-see.
|
| < < < < < |
Changes to ext/wasm/api/extern-post-js.c-pp.js.
︙ | ︙ | |||
24 25 26 27 28 29 30 | this. */ const originalInit = /* Maintenance reminder: DO NOT use `self.` here. It's correct for non-ES6 Module cases but wrong for ES6 modules because those resolve this symbol differently. */ sqlite3InitModule; if(!originalInit){ | | | | | < | < | | | | | | | | | | 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 | this. */ const originalInit = /* Maintenance reminder: DO NOT use `self.` here. It's correct for non-ES6 Module cases but wrong for ES6 modules because those resolve this symbol differently. */ sqlite3InitModule; if(!originalInit){ throw new Error("Expecting self.sqlite3InitModule to be defined by the Emscripten build."); } /** We need to add some state which our custom Module.locateFile() can see, but an Emscripten limitation currently prevents us from attaching it to the sqlite3InitModule function object: https://github.com/emscripten-core/emscripten/issues/18071 The only(?) current workaround is to temporarily stash this state into the global scope and delete it when sqlite3InitModule() is called. */ const initModuleState = self.sqlite3InitModuleState = Object.assign(Object.create(null),{ moduleScript: self?.document?.currentScript, isWorker: ('undefined' !== typeof WorkerGlobalScope), location: self.location, urlParams: new URL(self.location.href).searchParams }); initModuleState.debugModule = initModuleState.urlParams.has('sqlite3.debugModule') ? (...args)=>console.warn('sqlite3.debugModule:',...args) : ()=>{}; if(initModuleState.urlParams.has('sqlite3.dir')){ initModuleState.sqlite3Dir = initModuleState.urlParams.get('sqlite3.dir') +'/'; }else if(initModuleState.moduleScript){ const li = initModuleState.moduleScript.src.split('/'); li.pop(); initModuleState.sqlite3Dir = li.join('/') + '/'; } self.sqlite3InitModule = function ff(...args){ //console.warn("Using replaced sqlite3InitModule()",self.location); return originalInit(...args).then((EmscriptenModule)=>{ if(self.window!==self && (EmscriptenModule['ENVIRONMENT_IS_PTHREAD'] || EmscriptenModule['_pthread_self'] || 'function'===typeof threadAlert || self.location.pathname.endsWith('.worker.js') )){ /** Workaround for wasmfs-generated worker, which calls this routine from each individual thread and requires that its argument be returned. All of the criteria above are fragile, based solely on inspection of the offending code, not public Emscripten details. */ return EmscriptenModule; } const s = EmscriptenModule.sqlite3; s.scriptInfo = initModuleState; //console.warn("sqlite3.scriptInfo =",s.scriptInfo); if(ff.__isUnderTest) s.__isUnderTest = true; const f = s.asyncPostInit; delete s.asyncPostInit; return f(); }).catch((e)=>{ console.error("Exception loading sqlite3 module:",e); throw e; }); }; self.sqlite3InitModule.ready = originalInit.ready; if(self.sqlite3InitModuleState.moduleScript){ const sim = self.sqlite3InitModuleState; let src = sim.moduleScript.src.split('/'); src.pop(); sim.scriptDir = src.join('/') + '/'; } initModuleState.debugModule('sqlite3InitModuleState =',initModuleState); if(0){ console.warn("Replaced sqlite3InitModule()"); console.warn("self.location.href =",self.location.href); if('undefined' !== typeof document){ console.warn("document.currentScript.src =", document?.currentScript?.src); } } //#ifnot target=es6-module // Emscripten does not inject these module-loader bits in ES6 module // builds and including them here breaks JS bundlers, so elide them // from ESM builds. /* Replace the various module exports performed by the Emscripten glue... */ if (typeof exports === 'object' && typeof module === 'object'){ module.exports = sqlite3InitModule; }else if (typeof exports === 'object'){ exports["sqlite3InitModule"] = sqlite3InitModule; } /* AMD modules get injected in a way we cannot override, so we can't handle those here. */ //#endif // !target=es6-module return self.sqlite3InitModule /* required for ESM */; })(); //#if target=es6-module export default toExportForESM; //#endif |
Changes to ext/wasm/api/pre-js.c-pp.js.
1 2 3 4 5 6 7 8 | /** BEGIN FILE: api/pre-js.js This file is intended to be prepended to the sqlite3.js build using Emscripten's --pre-js=THIS_FILE flag (or equivalent). */ // See notes in extern-post-js.js | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /** BEGIN FILE: api/pre-js.js This file is intended to be prepended to the sqlite3.js build using Emscripten's --pre-js=THIS_FILE flag (or equivalent). */ // See notes in extern-post-js.js const sqlite3InitModuleState = self.sqlite3InitModuleState || Object.assign(Object.create(null),{ debugModule: ()=>{} }); delete self.sqlite3InitModuleState; sqlite3InitModuleState.debugModule('self.location =',self.location); //#ifnot target=es6-bundler-friendly /** This custom locateFile() tries to figure out where to load `path` from. The intent is to provide a way for foo/bar/X.js loaded from a Worker constructor or importScripts() to be able to resolve foo/bar/X.wasm (in the latter case, with some help): |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-cleanup.js.
︙ | ︙ | |||
21 22 23 24 25 26 27 | Install a suitable default configuration for sqlite3ApiBootstrap(). */ const SABC = Object.assign( Object.create(null), { exports: Module['asm'], memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */ }, | | | | | | | | | | 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 | Install a suitable default configuration for sqlite3ApiBootstrap(). */ const SABC = Object.assign( Object.create(null), { exports: Module['asm'], memory: Module.wasmMemory /* gets set if built with -sIMPORT_MEMORY */ }, self.sqlite3ApiConfig || {} ); /** For current (2022-08-22) purposes, automatically call sqlite3ApiBootstrap(). That decision will be revisited at some point, as we really want client code to be able to call this to configure certain parts. Clients may modify self.sqlite3ApiBootstrap.defaultConfig to tweak the default configuration used by a no-args call to sqlite3ApiBootstrap(), but must have first loaded their WASM module in order to be able to provide the necessary configuration state. */ //console.warn("self.sqlite3ApiConfig = ",self.sqlite3ApiConfig); self.sqlite3ApiConfig = SABC; let sqlite3; try{ sqlite3 = self.sqlite3ApiBootstrap(); }catch(e){ console.error("sqlite3ApiBootstrap() error:",e); throw e; }finally{ delete self.sqlite3ApiBootstrap; delete self.sqlite3ApiConfig; } Module.sqlite3 = sqlite3 /* Needed for customized sqlite3InitModule() to be able to pass the sqlite3 object off to the client. */; }else{ console.warn("This is not running in an Emscripten module context, so", "self.sqlite3ApiBootstrap() is _not_ being called due to lack", "of config info for the WASM environment.", "It must be called manually."); } |
Changes to ext/wasm/api/sqlite3-api-glue.js.
︙ | ︙ | |||
12 13 14 15 16 17 18 | This file glues together disparate pieces of JS which are loaded in previous steps of the sqlite3-api.js bootstrapping process: sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It initializes the main API pieces so that the downstream components (e.g. sqlite3-api-oo1.js) have all that they need. */ | | | | | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | This file glues together disparate pieces of JS which are loaded in previous steps of the sqlite3-api.js bootstrapping process: sqlite3-api-prologue.js, whwasmutil.js, and jaccwabyt.js. It initializes the main API pieces so that the downstream components (e.g. sqlite3-api-oo1.js) have all that they need. */ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ 'use strict'; const toss = (...args)=>{throw new Error(args.join(' '))}; const toss3 = sqlite3.SQLite3Error.toss; const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util; self.WhWasmUtilInstaller(wasm); delete self.WhWasmUtilInstaller; if(0){ /** Please keep this block around as a maintenance reminder that we cannot rely on this type of check. This block fails on Safari, per a report at |
︙ | ︙ | |||
323 324 325 326 327 328 329 | if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ /* ^^^ "the problem" is that this is an option feature and the build-time function-export list does not currently take optional features into account. */ wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); } | < < < < < < < < < | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 | if(false && wasm.compileOptionUsed('SQLITE_ENABLE_NORMALIZE')){ /* ^^^ "the problem" is that this is an option feature and the build-time function-export list does not currently take optional features into account. */ wasm.bindingSignatures.push(["sqlite3_normalized_sql", "string", "sqlite3_stmt*"]); } /** Functions which require BigInt (int64) support are separated from the others because we need to conditionally bind them or apply dummy impls, depending on the capabilities of the environment. Note that not all of these functions directly require int64 but are only for use with APIs which require int64. For example, |
︙ | ︙ | |||
610 611 612 613 614 615 616 | "sqlite3_vfs*","string","*", "int"], ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"] ]; /** Install JS<->C struct bindings for the non-opaque struct types we need... */ | | | | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | "sqlite3_vfs*","string","*", "int"], ["sqlite3_wasm_vfs_unlink", "int", "sqlite3_vfs*","string"] ]; /** Install JS<->C struct bindings for the non-opaque struct types we need... */ sqlite3.StructBinder = self.Jaccwabyt({ heap: 0 ? wasm.memory : wasm.heap8u, alloc: wasm.alloc, dealloc: wasm.dealloc, bigIntEnabled: wasm.bigIntEnabled, memberPrefix: /* Never change this: this prefix is baked into any amount of code and client-facing docs. */ '$' }); delete self.Jaccwabyt; {// wasm.xWrap() bindings... /* Convert Arrays and certain TypedArrays to strings for 'string:flexible'-type arguments */ const __xString = wasm.xWrap.argAdapter('string'); wasm.xWrap.argAdapter( |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-oo1.js.
︙ | ︙ | |||
8 9 10 11 12 13 14 | * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. *********************************************************************** This file contains the so-called OO #1 API wrapper for the sqlite3 WASM build. It requires that sqlite3-api-glue.js has already run | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | * May you find forgiveness for yourself and forgive others. * May you share freely, never taking more than you give. *********************************************************************** This file contains the so-called OO #1 API wrapper for the sqlite3 WASM build. It requires that sqlite3-api-glue.js has already run and it installs its deliverable as self.sqlite3.oo1. */ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const toss = (...args)=>{throw new Error(args.join(' '))}; const toss3 = (...args)=>{throw new sqlite3.SQLite3Error(...args)}; const capi = sqlite3.capi, wasm = sqlite3.wasm, util = sqlite3.util; /* What follows is colloquially known as "OO API #1". It is a binding of the sqlite3 API which is designed to be run within the same thread (main or worker) as the one in which the |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-api-prologue.js.
︙ | ︙ | |||
25 26 27 28 29 30 31 | */ /** sqlite3ApiBootstrap() is the only global symbol persistently exposed by this API. It is intended to be called one time at the end of the API amalgamation process, passed configuration details for the current environment, and then optionally be removed from | | | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | */ /** sqlite3ApiBootstrap() is the only global symbol persistently exposed by this API. It is intended to be called one time at the end of the API amalgamation process, passed configuration details for the current environment, and then optionally be removed from the global object using `delete self.sqlite3ApiBootstrap`. This function is not intended for client-level use. It is intended for use in creating bundles configured for specific WASM environments. This function expects a configuration object, intended to abstract away details specific to any given WASM environment, primarily so |
︙ | ︙ | |||
54 55 56 57 58 59 60 | - `memory`[^1]: optional WebAssembly.Memory object, defaulting to `exports.memory`. In Emscripten environments this should be set to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be left undefined/falsy to default to `exports.memory` when using WASM-exported memory. - `bigIntEnabled`: true if BigInt support is enabled. Defaults to | | | 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | - `memory`[^1]: optional WebAssembly.Memory object, defaulting to `exports.memory`. In Emscripten environments this should be set to `Module.wasmMemory` if the build uses `-sIMPORT_MEMORY`, or be left undefined/falsy to default to `exports.memory` when using WASM-exported memory. - `bigIntEnabled`: true if BigInt support is enabled. Defaults to true if `self.BigInt64Array` is available, else false. Some APIs will throw exceptions if called without BigInt support, as BigInt is required for marshalling C-side int64 into and out of JS. (Sidebar: it is technically possible to add int64 support via marshalling of int32 pairs, but doing so is unduly invasive.) - `allocExportName`: the name of the function, in `exports`, of the `malloc(3)`-compatible routine for the WASM environment. Defaults |
︙ | ︙ | |||
96 97 98 99 100 101 102 | function re-assigns calls that function to fetch the value, enabling delayed evaluation. The returned object is the top-level sqlite3 namespace object. */ 'use strict'; | | | | | 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 | function re-assigns calls that function to fetch the value, enabling delayed evaluation. The returned object is the top-level sqlite3 namespace object. */ 'use strict'; self.sqlite3ApiBootstrap = function sqlite3ApiBootstrap( apiConfig = (self.sqlite3ApiConfig || sqlite3ApiBootstrap.defaultConfig) ){ if(sqlite3ApiBootstrap.sqlite3){ /* already initalized */ console.warn("sqlite3ApiBootstrap() called multiple times.", "Config and external initializers are ignored on calls after the first."); return sqlite3ApiBootstrap.sqlite3; } const config = Object.assign(Object.create(null),{ exports: undefined, memory: undefined, bigIntEnabled: (()=>{ if('undefined'!==typeof Module){ /* Emscripten module will contain HEAPU64 when built with -sWASM_BIGINT=1, else it will not. */ return !!Module.HEAPU64; } return !!self.BigInt64Array; })(), debug: console.debug.bind(console), warn: console.warn.bind(console), error: console.error.bind(console), log: console.log.bind(console), wasmfsOpfsDir: '/opfs', /** |
︙ | ︙ | |||
768 769 770 771 772 773 774 | */ const util = { affirmBindableTypedArray, flexibleString, bigIntFits32, bigIntFits64, bigIntFitsDouble, isBindableTypedArray, isInt32, isSQLableTypedArray, isTypedArray, typedArrayToString, | | | 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 | */ const util = { affirmBindableTypedArray, flexibleString, bigIntFits32, bigIntFits64, bigIntFitsDouble, isBindableTypedArray, isInt32, isSQLableTypedArray, isTypedArray, typedArrayToString, isUIThread: ()=>(self.window===self && !!self.document), // is this true for ESM?: 'undefined'===typeof WorkerGlobalScope isSharedTypedArray, toss: function(...args){throw new Error(args.join(' '))}, toss3, typedArrayPart }; |
︙ | ︙ | |||
1199 1200 1201 1202 1203 1204 1205 | capi.sqlite3_wasmfs_opfs_dir = function(){ if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir; // If we have no OPFS, there is no persistent dir const pdir = config.wasmfsOpfsDir; console.error("sqlite3_wasmfs_opfs_dir() can no longer work due "+ "to incompatible WASMFS changes. It will be removed."); if(!pdir | | | | | 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 | capi.sqlite3_wasmfs_opfs_dir = function(){ if(undefined !== __wasmfsOpfsDir) return __wasmfsOpfsDir; // If we have no OPFS, there is no persistent dir const pdir = config.wasmfsOpfsDir; console.error("sqlite3_wasmfs_opfs_dir() can no longer work due "+ "to incompatible WASMFS changes. It will be removed."); if(!pdir || !self.FileSystemHandle || !self.FileSystemDirectoryHandle || !self.FileSystemFileHandle){ return __wasmfsOpfsDir = ""; } try{ if(pdir && 0===wasm.xCallWrapped( 'sqlite3_wasm_init_wasmfs', 'i32', ['string'], pdir )){ return __wasmfsOpfsDir = pdir; |
︙ | ︙ | |||
1457 1458 1459 1460 1461 1462 1463 | Internal helper for sqlite3_js_kvvfs_clear() and friends. Its argument should be one of ('local','session',""). */ const __kvvfsInfo = function(which){ const rc = Object.create(null); rc.prefix = 'kvvfs-'+which; rc.stores = []; | | | | 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 | Internal helper for sqlite3_js_kvvfs_clear() and friends. Its argument should be one of ('local','session',""). */ const __kvvfsInfo = function(which){ const rc = Object.create(null); rc.prefix = 'kvvfs-'+which; rc.stores = []; if('session'===which || ""===which) rc.stores.push(self.sessionStorage); if('local'===which || ""===which) rc.stores.push(self.localStorage); return rc; }; /** Clears all storage used by the kvvfs DB backend, deleting any DB(s) stored there. Its argument must be either 'session', 'local', or "". In the first two cases, only sessionStorage |
︙ | ︙ | |||
1533 1534 1535 1536 1537 1538 1539 | /** Wraps all known variants of the C-side variadic sqlite3_db_config(). Full docs: https://sqlite.org/c3ref/db_config.html Returns capi.SQLITE_MISUSE if op is not a valid operation ID. | < < < | > | | | | | | | | | | | | | | | | < < | | | | 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 | /** Wraps all known variants of the C-side variadic sqlite3_db_config(). Full docs: https://sqlite.org/c3ref/db_config.html Returns capi.SQLITE_MISUSE if op is not a valid operation ID. */ capi.sqlite3_db_config = function f(pDb, op, ...args){ if(!this.s){ this.s = wasm.xWrap('sqlite3_wasm_db_config_s','int', ['sqlite3*', 'int', 'string:static'] /* MAINDBNAME requires a static string */); this.pii = wasm.xWrap('sqlite3_wasm_db_config_pii', 'int', ['sqlite3*', 'int', '*','int', 'int']); this.ip = wasm.xWrap('sqlite3_wasm_db_config_ip','int', ['sqlite3*', 'int', 'int','*']); } const c = capi; switch(op){ case c.SQLITE_DBCONFIG_ENABLE_FKEY: case c.SQLITE_DBCONFIG_ENABLE_TRIGGER: case c.SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: case c.SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: case c.SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: case c.SQLITE_DBCONFIG_ENABLE_QPSG: case c.SQLITE_DBCONFIG_TRIGGER_EQP: case c.SQLITE_DBCONFIG_RESET_DATABASE: case c.SQLITE_DBCONFIG_DEFENSIVE: case c.SQLITE_DBCONFIG_WRITABLE_SCHEMA: case c.SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: case c.SQLITE_DBCONFIG_DQS_DML: case c.SQLITE_DBCONFIG_DQS_DDL: case c.SQLITE_DBCONFIG_ENABLE_VIEW: case c.SQLITE_DBCONFIG_LEGACY_FILE_FORMAT: case c.SQLITE_DBCONFIG_TRUSTED_SCHEMA: return this.ip(pDb, op, args[0], args[1] || 0); case c.SQLITE_DBCONFIG_LOOKASIDE: return this.pii(pDb, op, args[0], args[1], args[2]); case c.SQLITE_DBCONFIG_MAINDBNAME: return this.s(pDb, op, args[0]); default: return c.SQLITE_MISUSE; } }.bind(Object.create(null)); /** Given a (sqlite3_value*), this function attempts to convert it to an equivalent JS value with as much fidelity as feasible and return it. |
︙ | ︙ | |||
1962 1963 1964 1965 1966 1967 1968 | throw e; } delete sqlite3ApiBootstrap.initializers; sqlite3ApiBootstrap.sqlite3 = sqlite3; return sqlite3; }/*sqlite3ApiBootstrap()*/; /** | | | | | | | | | | | > | 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 | throw e; } delete sqlite3ApiBootstrap.initializers; sqlite3ApiBootstrap.sqlite3 = sqlite3; return sqlite3; }/*sqlite3ApiBootstrap()*/; /** self.sqlite3ApiBootstrap.initializers is an internal detail used by the various pieces of the sqlite3 API's amalgamation process. It must not be modified by client code except when plugging such code into the amalgamation process. Each component of the amalgamation is expected to append a function to this array. When sqlite3ApiBootstrap() is called for the first time, each such function will be called (in their appended order) and passed the sqlite3 namespace object, into which they can install their features (noting that most will also require that certain features alread have been installed). At the end of that process, this array is deleted. Note that the order of insertion into this array is significant for some pieces. e.g. sqlite3.capi and sqlite3.wasm cannot be fully utilized until the whwasmutil.js part is plugged in via sqlite3-api-glue.js. */ self.sqlite3ApiBootstrap.initializers = []; /** self.sqlite3ApiBootstrap.initializersAsync is an internal detail used by the sqlite3 API's amalgamation process. It must not be modified by client code except when plugging such code into the amalgamation process. The counterpart of self.sqlite3ApiBootstrap.initializers, specifically for initializers which are asynchronous. All entries in this list must be either async functions, non-async functions which return a Promise, or a Promise. Each function in the list is called with the sqlite3 ojbect as its only argument. The resolved value of any Promise is ignored and rejection will kill the asyncPostInit() process (at an indeterminate point because all of them are run asynchronously in parallel). This list is not processed until the client calls sqlite3.asyncPostInit(). This means, for example, that intializers added to self.sqlite3ApiBootstrap.initializers may push entries to this list. */ self.sqlite3ApiBootstrap.initializersAsync = []; /** Client code may assign sqlite3ApiBootstrap.defaultConfig an object-type value before calling sqlite3ApiBootstrap() (without arguments) in order to tell that call to use this object as its default config value. The intention of this is to provide downstream clients with a reasonably flexible approach for plugging in an environment-suitable configuration without having to define a new global-scope symbol. */ self.sqlite3ApiBootstrap.defaultConfig = Object.create(null); /** Placeholder: gets installed by the first call to self.sqlite3ApiBootstrap(). However, it is recommended that the caller of sqlite3ApiBootstrap() capture its return value and delete self.sqlite3ApiBootstrap after calling it. It returns the same value which will be stored here. */ self.sqlite3ApiBootstrap.sqlite3 = undefined; |
Changes to ext/wasm/api/sqlite3-api-worker1.js.
︙ | ︙ | |||
309 310 311 312 313 314 315 | to wait until the first exec() is completed. The response is the input options object (or a synthesized one if passed only a string), noting that options.resultRows and options.columnNames may be populated by the call to db.exec(). */ | | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 | to wait until the first exec() is completed. The response is the input options object (or a synthesized one if passed only a string), noting that options.resultRows and options.columnNames may be populated by the call to db.exec(). */ self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ sqlite3.initWorker1API = function(){ 'use strict'; const toss = (...args)=>{throw new Error(args.join(' '))}; if('function' !== typeof importScripts){ toss("initWorker1API() must be run from a Worker thread."); } const self = this.self; const sqlite3 = this.sqlite3 || toss("Missing this.sqlite3 object."); const DB = sqlite3.oo1.DB; /** |
︙ | ︙ | |||
378 379 380 381 382 383 384 | Posts the given worker message value. If xferList is provided, it must be an array, in which case a copy of it passed as postMessage()'s second argument and xferList.length is set to 0. */ post: function(msg,xferList){ if(xferList && xferList.length){ | | | | 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 | Posts the given worker message value. If xferList is provided, it must be an array, in which case a copy of it passed as postMessage()'s second argument and xferList.length is set to 0. */ post: function(msg,xferList){ if(xferList && xferList.length){ self.postMessage( msg, Array.from(xferList) ); xferList.length = 0; }else{ self.postMessage(msg); } }, /** Map of DB IDs to DBs. */ dbs: Object.create(null), /** Fetch the DB for the given id. Throw if require=true and the id is not valid, else return the db or undefined. */ getDb: function(id,require=true){ |
︙ | ︙ | |||
585 586 587 588 589 590 591 | 'opfs-tree': async function(ev){ if(!sqlite3.opfs) toss("OPFS support is unavailable."); const response = await sqlite3.opfs.treeList(); return response; } }/*wMsgHandler*/; | | | 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 | 'opfs-tree': async function(ev){ if(!sqlite3.opfs) toss("OPFS support is unavailable."); const response = await sqlite3.opfs.treeList(); return response; } }/*wMsgHandler*/; self.onmessage = async function(ev){ ev = ev.data; let result, dbId = ev.dbId, evType = ev.type; const arrivalTime = performance.now(); try { if(wMsgHandler.hasOwnProperty(evType) && wMsgHandler[evType] instanceof Function){ result = await wMsgHandler[evType](ev); |
︙ | ︙ | |||
633 634 635 636 637 638 639 | // departure: ev.departureTime, // workerReceived: arrivalTime, // workerResponse: performance.now(); //}, result: result }, wState.xfer); }; | | | 633 634 635 636 637 638 639 640 641 642 | // departure: ev.departureTime, // workerReceived: arrivalTime, // workerResponse: performance.now(); //}, result: result }, wState.xfer); }; self.postMessage({type:'sqlite3-api',result:'worker1-ready'}); }.bind({self, sqlite3}); }); |
Changes to ext/wasm/api/sqlite3-license-version-header.js.
1 2 3 | /* ** LICENSE for the sqlite3 WebAssembly/JavaScript APIs. ** | | | 1 2 3 4 5 6 7 8 9 10 11 | /* ** LICENSE for the sqlite3 WebAssembly/JavaScript APIs. ** ** This bundle (typically released as sqlite3.js or sqlite3-wasmfs.js) ** is an amalgamation of JavaScript source code from two projects: ** ** 1) https://emscripten.org: the Emscripten "glue code" is covered by ** the terms of the MIT license and University of Illinois/NCSA ** Open Source License, as described at: ** ** https://emscripten.org/docs/introducing_emscripten/emscripten_license.html |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-opfs-async-proxy.js.
︙ | ︙ | |||
46 47 48 49 50 51 52 | versions (approximately) 104-107 are extinct) should change our usage of those methods to remove the "await". */ "use strict"; const wPost = (type,...args)=>postMessage({type, payload:args}); const installAsyncProxy = function(self){ const toss = function(...args){throw new Error(args.join(' '))}; | | | | | | | 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 | versions (approximately) 104-107 are extinct) should change our usage of those methods to remove the "await". */ "use strict"; const wPost = (type,...args)=>postMessage({type, payload:args}); const installAsyncProxy = function(self){ const toss = function(...args){throw new Error(args.join(' '))}; if(self.window === self){ toss("This code cannot run from the main thread.", "Load it as a Worker from a separate Worker."); }else if(!navigator.storage.getDirectory){ toss("This API requires navigator.storage.getDirectory."); } /** Will hold state copied to this object from the syncronous side of this API. */ const state = Object.create(null); /** verbose: 0 = no logging output 1 = only errors 2 = warnings and errors 3 = debug, warnings, and errors */ state.verbose = 1; const loggers = { 0:sqlite3.config.error.bind(console), 1:sqlite3.config.warn.bind(console), 2:sqlite3.config.log.bind(console) }; const logImpl = (level,...args)=>{ if(state.verbose>level) loggers[level]("OPFS asyncer:",...args); }; const log = (...args)=>logImpl(2, ...args); const warn = (...args)=>logImpl(1, ...args); const error = (...args)=>logImpl(0, ...args); |
︙ | ︙ | |||
102 103 104 105 106 107 108 | for(k in state.opIds){ const m = metrics[k]; n += m.count; t += m.time; w += m.wait; m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0; } | | | | | 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | for(k in state.opIds){ const m = metrics[k]; n += m.count; t += m.time; w += m.wait; m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0; } sqlite3.config.log(self.location.href, "metrics for",self.location.href,":\n", metrics, "\nTotal of",n,"op(s) for",t,"ms", "approx",w,"ms spent waiting on OPFS APIs."); sqlite3.config.log("Serialization metrics:",metrics.s11n); }; /** __openFiles is a map of sqlite3_file pointers (integers) to metadata related to a given OPFS file handles. The pointers are, in this side of the interface, opaque file handle IDs provided by the synchronous part of this constellation. Each value is an object |
︙ | ︙ | |||
268 269 270 271 272 273 274 | e instanceof GetSyncHandleError && ((e.cause.name==='NoModificationAllowedError') /* Inconsistent exception.name from Chrome/ium with the same exception.message text: */ || (e.cause.name==='DOMException' && 0===e.cause.message.indexOf('Access Handles cannot'))) ) ? ( | | | 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | e instanceof GetSyncHandleError && ((e.cause.name==='NoModificationAllowedError') /* Inconsistent exception.name from Chrome/ium with the same exception.message text: */ || (e.cause.name==='DOMException' && 0===e.cause.message.indexOf('Access Handles cannot'))) ) ? ( /*sqlite3.config.warn("SQLITE_BUSY",e),*/ state.sq3Codes.SQLITE_BUSY ) : rc; }else{ return rc; } } /** |
︙ | ︙ | |||
839 840 841 842 843 844 845 | error('in waitLoop():',e); } } }; navigator.storage.getDirectory().then(function(d){ state.rootDir = d; | | | 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | error('in waitLoop():',e); } } }; navigator.storage.getDirectory().then(function(d){ state.rootDir = d; self.onmessage = function({data}){ switch(data.type){ case 'opfs-async-init':{ /* Receive shared state from synchronous partner */ const opt = data.args; for(const k in opt) state[k] = opt[k]; state.verbose = opt.verbose ?? 1; state.sabOPView = new Int32Array(state.sabOP); |
︙ | ︙ | |||
876 877 878 879 880 881 882 | metrics.dump(); break; } }; wPost('opfs-async-loaded'); }).catch((e)=>error("error initializing OPFS asyncer:",e)); }/*installAsyncProxy()*/; | | | | | | | | | 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 | metrics.dump(); break; } }; wPost('opfs-async-loaded'); }).catch((e)=>error("error initializing OPFS asyncer:",e)); }/*installAsyncProxy()*/; if(!self.SharedArrayBuffer){ wPost('opfs-unavailable', "Missing SharedArrayBuffer API.", "The server must emit the COOP/COEP response headers to enable that."); }else if(!self.Atomics){ wPost('opfs-unavailable', "Missing Atomics API.", "The server must emit the COOP/COEP response headers to enable that."); }else if(!self.FileSystemHandle || !self.FileSystemDirectoryHandle || !self.FileSystemFileHandle || !self.FileSystemFileHandle.prototype.createSyncAccessHandle || !navigator.storage.getDirectory){ wPost('opfs-unavailable',"Missing required OPFS APIs."); }else{ installAsyncProxy(self); } |
Changes to ext/wasm/api/sqlite3-v-helper.js.
︙ | ︙ | |||
11 12 13 14 15 16 17 | /** This file installs sqlite3.vfs, and object which exists to assist in the creation of JavaScript implementations of sqlite3_vfs, along with its virtual table counterpart, sqlite3.vtab. */ 'use strict'; | | < < < | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | /** This file installs sqlite3.vfs, and object which exists to assist in the creation of JavaScript implementations of sqlite3_vfs, along with its virtual table counterpart, sqlite3.vtab. */ 'use strict'; self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ const wasm = sqlite3.wasm, capi = sqlite3.capi, toss = sqlite3.util.toss3; const vfs = Object.create(null), vtab = Object.create(null); sqlite3.vfs = vfs; sqlite3.vtab = vtab; const sii = capi.sqlite3_index_info; /** If n is >=0 and less than this.$nConstraint, this function returns either a WASM pointer to the 0-based nth entry of |
︙ | ︙ | |||
111 112 113 114 115 116 117 | argument count does not match expectations. That is only intended for dev-time usage for sanity checking, and will leave the C environment in an undefined state. */ const installMethod = function callee( tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck ){ | | | | 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 | argument count does not match expectations. That is only intended for dev-time usage for sanity checking, and will leave the C environment in an undefined state. */ const installMethod = function callee( tgt, name, func, applyArgcCheck = callee.installMethodArgcCheck ){ if(!(tgt instanceof sqlite3.StructBinder.StructType)){ toss("Usage error: target object is-not-a StructType."); }else if(!(func instanceof Function) && !wasm.isPtr(func)){ toss("Usage errror: expecting a Function or WASM pointer to one."); } if(1===arguments.length){ return (n,f)=>callee(tgt, n, f, applyArgcCheck); } if(!callee.argcProxy){ callee.argcProxy = function(tgt, funcName, func,sig){ return function(...args){ if(func.length!==arguments.length){ toss("Argument mismatch for", tgt.structInfo.name+"::"+funcName +": Native signature is:",sig); } return func.apply(this, args); } }; /* An ondispose() callback for use with sqlite3.StructBinder-created types. */ callee.removeFuncList = function(){ if(this.ondispose.__removeFuncList){ this.ondispose.__removeFuncList.forEach( (v,ndx)=>{ if('number'===typeof v){ try{wasm.uninstallFunction(v)} catch(e){/*ignore*/} |
︙ | ︙ | |||
220 221 222 223 224 225 226 | /** Equivalent to calling installMethod(this,...arguments) with a first argument of this object. If called with 1 or 2 arguments and the first is an object, it's instead equivalent to calling installMethods(this,...arguments). */ | | | | 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 | /** Equivalent to calling installMethod(this,...arguments) with a first argument of this object. If called with 1 or 2 arguments and the first is an object, it's instead equivalent to calling installMethods(this,...arguments). */ sqlite3.StructBinder.StructType.prototype.installMethod = function callee( name, func, applyArgcCheck = installMethod.installMethodArgcCheck ){ return (arguments.length < 3 && name && 'object'===typeof name) ? installMethods(this, ...arguments) : installMethod(this, ...arguments); }; /** Equivalent to calling installMethods() with a first argument of this object. */ sqlite3.StructBinder.StructType.prototype.installMethods = function( methods, applyArgcCheck = installMethod.installMethodArgcCheck ){ return installMethods(this, methods, applyArgcCheck); }; /** Uses sqlite3_vfs_register() to register this |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-vfs-opfs.c-pp.js.
︙ | ︙ | |||
14 15 16 17 18 19 20 | implementation which proxies, in a synchronous fashion, the asynchronous Origin-Private FileSystem (OPFS) APIs using a second Worker, implemented in sqlite3-opfs-async-proxy.js. This file is intended to be appended to the main sqlite3 JS deliverable somewhere after sqlite3-api-oo1.js and before sqlite3-api-cleanup.js. */ 'use strict'; | | | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | implementation which proxies, in a synchronous fashion, the asynchronous Origin-Private FileSystem (OPFS) APIs using a second Worker, implemented in sqlite3-opfs-async-proxy.js. This file is intended to be appended to the main sqlite3 JS deliverable somewhere after sqlite3-api-oo1.js and before sqlite3-api-cleanup.js. */ 'use strict'; self.sqlite3ApiBootstrap.initializers.push(function(sqlite3){ /** installOpfsVfs() returns a Promise which, on success, installs an sqlite3_vfs named "opfs", suitable for use with all sqlite3 APIs which accept a VFS. It is intended to be called via sqlite3ApiBootstrap.initializersAsync or an equivalent mechanism. The installed VFS uses the Origin-Private FileSystem API for |
︙ | ︙ | |||
72 73 74 75 76 77 78 | returned Promise resolves. On success, the Promise resolves to the top-most sqlite3 namespace object and that object gets a new object installed in its `opfs` property, containing several OPFS-specific utilities. */ const installOpfsVfs = function callee(options){ | | | | | | | | | | | | | | | | 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 | returned Promise resolves. On success, the Promise resolves to the top-most sqlite3 namespace object and that object gets a new object installed in its `opfs` property, containing several OPFS-specific utilities. */ const installOpfsVfs = function callee(options){ if(!self.SharedArrayBuffer || !self.Atomics){ return Promise.reject( new Error("Cannot install OPFS: Missing SharedArrayBuffer and/or Atomics. "+ "The server must emit the COOP/COEP response headers to enable those. "+ "See https://sqlite.org/wasm/doc/trunk/persistence.md#coop-coep") ); }else if(self.window===self && self.document){ return Promise.reject( new Error("The OPFS sqlite3_vfs cannot run in the main thread "+ "because it requires Atomics.wait().") ); }else if(!self.FileSystemHandle || !self.FileSystemDirectoryHandle || !self.FileSystemFileHandle || !self.FileSystemFileHandle.prototype.createSyncAccessHandle || !navigator.storage.getDirectory){ return Promise.reject( new Error("Missing required OPFS APIs.") ); } if(!options || 'object'!==typeof options){ options = Object.create(null); } const urlParams = new URL(self.location.href).searchParams; if(undefined===options.verbose){ options.verbose = urlParams.has('opfs-verbose') ? (+urlParams.get('opfs-verbose') || 2) : 1; } if(undefined===options.sanityChecks){ options.sanityChecks = urlParams.has('opfs-sanity-check'); } if(undefined===options.proxyUri){ options.proxyUri = callee.defaultProxyUri; } //sqlite3.config.warn("OPFS options =",options,self.location); if('function' === typeof options.proxyUri){ options.proxyUri = options.proxyUri(); } const thePromise = new Promise(function(promiseResolve, promiseReject_){ const loggers = { 0:sqlite3.config.error.bind(console), 1:sqlite3.config.warn.bind(console), 2:sqlite3.config.log.bind(console) }; const logImpl = (level,...args)=>{ if(options.verbose>level) loggers[level]("OPFS syncer:",...args); }; const log = (...args)=>logImpl(2, ...args); const warn = (...args)=>logImpl(1, ...args); const error = (...args)=>logImpl(0, ...args); |
︙ | ︙ | |||
145 146 147 148 149 150 151 | */ const opfsUtil = Object.create(null); /** Returns true if _this_ thread has access to the OPFS APIs. */ const thisThreadHasOPFS = ()=>{ | | | | | | | | < | < < < < < < < < < < < < < < < < < | 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 | */ const opfsUtil = Object.create(null); /** Returns true if _this_ thread has access to the OPFS APIs. */ const thisThreadHasOPFS = ()=>{ return self.FileSystemHandle && self.FileSystemDirectoryHandle && self.FileSystemFileHandle && self.FileSystemFileHandle.prototype.createSyncAccessHandle && navigator.storage.getDirectory; }; /** Not part of the public API. Solely for internal/development use. */ opfsUtil.metrics = { dump: function(){ let k, n = 0, t = 0, w = 0; for(k in state.opIds){ const m = metrics[k]; n += m.count; t += m.time; w += m.wait; m.avgTime = (m.count && m.time) ? (m.time / m.count) : 0; m.avgWait = (m.count && m.wait) ? (m.wait / m.count) : 0; } sqlite3.config.log(self.location.href, "metrics for",self.location.href,":",metrics, "\nTotal of",n,"op(s) for",t, "ms (incl. "+w+" ms of waiting on the async side)"); sqlite3.config.log("Serialization metrics:",metrics.s11n); W.postMessage({type:'opfs-async-metrics'}); }, reset: function(){ let k; const r = (m)=>(m.count = m.time = m.wait = 0); for(k in state.opIds){ r(metrics[k] = Object.create(null)); } let s = metrics.s11n = Object.create(null); s = s.serialize = Object.create(null); s.count = s.time = 0; s = metrics.s11n.deserialize = Object.create(null); s.count = s.time = 0; } }/*metrics*/; const opfsVfs = new sqlite3_vfs(); const opfsIoMethods = new sqlite3_io_methods(); const promiseReject = function(err){ opfsVfs.dispose(); return promiseReject_(err); }; const W = //#if target=es6-bundler-friendly new Worker(new URL("sqlite3-opfs-async-proxy.js", import.meta.url)); //#elif target=es6-module new Worker(new URL(options.proxyUri, import.meta.url)); //#else new Worker(options.proxyUri); //#endif W._originalOnError = W.onerror /* will be restored later */; W.onerror = function(err){ // The error object doesn't contain any useful info when the // failure is, e.g., that the remote script is 404. error("Error initializing OPFS asyncer:",err); promiseReject(new Error("Loading OPFS async Worker failed for unknown reasons.")); }; |
︙ | ︙ | |||
349 350 351 352 353 354 355 356 357 358 359 360 361 362 | the whichOp slot. The async-api worker uses Atomic.wait() on the whichOp slot to figure out which operation to run next. */ state.opIds.xAccess = i++; state.opIds.xClose = i++; state.opIds.xDelete = i++; state.opIds.xDeleteNoWait = i++; state.opIds.xFileSize = i++; state.opIds.xLock = i++; state.opIds.xOpen = i++; state.opIds.xRead = i++; state.opIds.xSleep = i++; state.opIds.xSync = i++; state.opIds.xTruncate = i++; | > | 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 | the whichOp slot. The async-api worker uses Atomic.wait() on the whichOp slot to figure out which operation to run next. */ state.opIds.xAccess = i++; state.opIds.xClose = i++; state.opIds.xDelete = i++; state.opIds.xDeleteNoWait = i++; state.opIds.xFileControl = i++; state.opIds.xFileSize = i++; state.opIds.xLock = i++; state.opIds.xOpen = i++; state.opIds.xRead = i++; state.opIds.xSleep = i++; state.opIds.xSync = i++; state.opIds.xTruncate = i++; |
︙ | ︙ | |||
713 714 715 716 717 718 719 | return rc; }, xDeviceCharacteristics: function(pFile){ //debug("xDeviceCharacteristics(",pFile,")"); return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; }, xFileControl: function(pFile, opId, pArg){ | | > > > | | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 | return rc; }, xDeviceCharacteristics: function(pFile){ //debug("xDeviceCharacteristics(",pFile,")"); return capi.SQLITE_IOCAP_UNDELETABLE_WHEN_OPEN; }, xFileControl: function(pFile, opId, pArg){ mTimeStart('xFileControl'); const rc = (capi.SQLITE_FCNTL_SYNC===opId) ? opRun('xSync', pFile, 0) : capi.SQLITE_NOTFOUND; mTimeEnd(); return rc; }, xFileSize: function(pFile,pSz64){ mTimeStart('xFileSize'); let rc = opRun('xFileSize', pFile); if(0==rc){ try { const sz = state.s11n.deserialize()[0]; |
︙ | ︙ | |||
771 772 773 774 775 776 777 | error("xRead(",arguments,") failed:",e,f); rc = capi.SQLITE_IOERR_READ; } mTimeEnd(); return rc; }, xSync: function(pFile,flags){ | < < < | | 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 | error("xRead(",arguments,") failed:",e,f); rc = capi.SQLITE_IOERR_READ; } mTimeEnd(); return rc; }, xSync: function(pFile,flags){ ++metrics.xSync.count; return 0; // impl'd in xFileControl() }, xTruncate: function(pFile,sz64){ mTimeStart('xTruncate'); const rc = opRun('xTruncate', pFile, Number(sz64)); mTimeEnd(); return rc; }, |
︙ | ︙ | |||
1184 1185 1186 1187 1188 1189 1190 | help OPFS dbs deal with multi-tab/multi-worker contention. */ sqlite3.capi.sqlite3_busy_timeout(oo1Db, 10000); sqlite3.capi.sqlite3_exec(oo1Db, [ /* Truncate journal mode is faster than delete for this vfs, per speedtest1. That gap seems to have closed with Chrome version 108 or 109, but "persist" is very roughly 5-6% | | < < < < < < < < | 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 | help OPFS dbs deal with multi-tab/multi-worker contention. */ sqlite3.capi.sqlite3_busy_timeout(oo1Db, 10000); sqlite3.capi.sqlite3_exec(oo1Db, [ /* Truncate journal mode is faster than delete for this vfs, per speedtest1. That gap seems to have closed with Chrome version 108 or 109, but "persist" is very roughly 5-6% faster than truncate in initial tests. */ "pragma journal_mode=persist;", /* This vfs benefits hugely from cache on moderate/large speedtest1 --size 50 and --size 100 workloads. We currently rely on setting a non-default cache size when building sqlite3.wasm. If that policy changes, the cache can be set here. |
︙ | ︙ | |||
1282 1283 1284 1285 1286 1287 1288 | switch(data.type){ case 'opfs-unavailable': /* Async proxy has determined that OPFS is unavailable. There's nothing more for us to do here. */ promiseReject(new Error(data.payload.join(' '))); break; case 'opfs-async-loaded': | | | < | | | | < < < | 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 | switch(data.type){ case 'opfs-unavailable': /* Async proxy has determined that OPFS is unavailable. There's nothing more for us to do here. */ promiseReject(new Error(data.payload.join(' '))); break; case 'opfs-async-loaded': /*Arrives as soon as the asyc proxy finishes loading. Pass our config and shared state on to the async worker.*/ W.postMessage({type: 'opfs-async-init',args: state}); break; case 'opfs-async-inited':{ /*Indicates that the async partner has received the 'init' and has finished initializing, so the real work can begin...*/ try { sqlite3.vfs.installVfs({ io: {struct: opfsIoMethods, methods: ioSyncWrappers}, vfs: {struct: opfsVfs, methods: vfsSyncWrappers} }); state.sabOPView = new Int32Array(state.sabOP); state.sabFileBufView = new Uint8Array(state.sabIO, 0, state.fileBufferSize); |
︙ | ︙ | |||
1325 1326 1327 1328 1329 1330 1331 | } }catch(e){ error(e); promiseReject(e); } break; } | | < < < < < | > < | | 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 | } }catch(e){ error(e); promiseReject(e); } break; } default: promiseReject(e); error("Unexpected message from the async worker:",data); break; }/*switch(data.type)*/ }/*W.onmessage()*/; })/*thePromise*/; return thePromise; }/*installOpfsVfs()*/; installOpfsVfs.defaultProxyUri = "sqlite3-opfs-async-proxy.js"; self.sqlite3ApiBootstrap.initializersAsync.push(async (sqlite3)=>{ try{ let proxyJs = installOpfsVfs.defaultProxyUri; if(sqlite3.scriptInfo.sqlite3Dir){ installOpfsVfs.defaultProxyUri = sqlite3.scriptInfo.sqlite3Dir + proxyJs; //sqlite3.config.warn("installOpfsVfs.defaultProxyUri =",installOpfsVfs.defaultProxyUri); } |
︙ | ︙ |
Changes to ext/wasm/api/sqlite3-wasm.c.
︙ | ︙ | |||
159 160 161 162 163 164 165 | /**********************************************************************/ /* SQLITE_USE_... */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 1 #endif | | | < > | > | | 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | /**********************************************************************/ /* SQLITE_USE_... */ #ifndef SQLITE_USE_URI # define SQLITE_USE_URI 1 #endif #include <assert.h> #include "sqlite3.c" /* yes, .c instead of .h. */ #if defined(__EMSCRIPTEN__) # include <emscripten/console.h> #endif /* ** SQLITE_WASM_KEEP is functionally identical to EMSCRIPTEN_KEEPALIVE ** but is not Emscripten-specific. It explicitly marks functions for ** export into the target wasm file without requiring explicit listing ** of those functions in Emscripten's -sEXPORTED_FUNCTIONS=... list ** (or equivalent in other build platforms). Any function with neither ** this attribute nor which is listed as an explicit export will not ** be exported from the wasm file (but may still be used internally ** within the wasm file). |
︙ | ︙ | |||
188 189 190 191 192 193 194 | ** ** 2022-09-11: it's not yet _proven_ that this approach works in ** non-Emscripten builds. If not, such builds will need to export ** those using the --export=... wasm-ld flag (or equivalent). As of ** this writing we are tied to Emscripten for various reasons ** and cannot test the library with other build environments. */ | | < < < < < < < < < < < < < < < < < < < < < < < < | | | | | | 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 | ** ** 2022-09-11: it's not yet _proven_ that this approach works in ** non-Emscripten builds. If not, such builds will need to export ** those using the --export=... wasm-ld flag (or equivalent). As of ** this writing we are tied to Emscripten for various reasons ** and cannot test the library with other build environments. */ #define SQLITE_WASM_KEEP __attribute__((used,visibility("default"))) // See also: //__attribute__((export_name("theExportedName"), used, visibility("default"))) #if 0 /* ** An EXPERIMENT in implementing a stack-based allocator analog to ** Emscripten's stackSave(), stackAlloc(), stackRestore(). ** Unfortunately, this cannot work together with Emscripten because ** Emscripten defines its own native one and we'd stomp on each ** other's memory. Other than that complication, basic tests show it ** to work just fine. ** ** Another option is to malloc() a chunk of our own and call that our ** "stack". */ SQLITE_WASM_KEEP void * sqlite3_wasm_stack_end(void){ extern void __heap_base /* see https://stackoverflow.com/questions/10038964 */; return &__heap_base; } SQLITE_WASM_KEEP void * sqlite3_wasm_stack_begin(void){ extern void __data_end; return &__data_end; } static void * pWasmStackPtr = 0; SQLITE_WASM_KEEP void * sqlite3_wasm_stack_ptr(void){ if(!pWasmStackPtr) pWasmStackPtr = sqlite3_wasm_stack_end(); return pWasmStackPtr; } SQLITE_WASM_KEEP void sqlite3_wasm_stack_restore(void * p){ pWasmStackPtr = p; } SQLITE_WASM_KEEP void * sqlite3_wasm_stack_alloc(int n){ if(n<=0) return 0; n = (n + 7) & ~7 /* align to 8-byte boundary */; unsigned char * const p = (unsigned char *)sqlite3_wasm_stack_ptr(); unsigned const char * const b = (unsigned const char *)sqlite3_wasm_stack_begin(); if(b + n >= p || b + n < b/*overflow*/) return 0; return pWasmStackPtr = p - n; } |
︙ | ︙ | |||
282 283 284 285 286 287 288 | &PStack_mem[0], &PStack_mem[0] + sizeof(PStack_mem), &PStack_mem[0] + sizeof(PStack_mem) }; /* ** Returns the current pstack position. */ | | | | | | | | 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 | &PStack_mem[0], &PStack_mem[0] + sizeof(PStack_mem), &PStack_mem[0] + sizeof(PStack_mem) }; /* ** Returns the current pstack position. */ SQLITE_WASM_KEEP void * sqlite3_wasm_pstack_ptr(void){ return PStack.pPos; } /* ** Sets the pstack position poitner to p. Results are undefined if the ** given value did not come from sqlite3_wasm_pstack_ptr(). */ SQLITE_WASM_KEEP void sqlite3_wasm_pstack_restore(unsigned char * p){ assert(p>=PStack.pBegin && p<=PStack.pEnd && p>=PStack.pPos); assert(0==(p & 0x7)); if(p>=PStack.pBegin && p<=PStack.pEnd /*&& p>=PStack.pPos*/){ PStack.pPos = p; } } /* ** Allocate and zero out n bytes from the pstack. Returns a pointer to ** the memory on success, 0 on error (including a negative n value). n ** is always adjusted to be a multiple of 8 and returned memory is ** always zeroed out before returning (because this keeps the client ** JS code from having to do so, and most uses of the pstack will ** call for doing so). */ SQLITE_WASM_KEEP void * sqlite3_wasm_pstack_alloc(int n){ if( n<=0 ) return 0; //if( n & 0x7 ) n += 8 - (n & 0x7) /* align to 8-byte boundary */; n = (n + 7) & ~7 /* align to 8-byte boundary */; if( PStack.pBegin + n > PStack.pPos /*not enough space left*/ || PStack.pBegin + n <= PStack.pBegin /*overflow*/ ) return 0; memset((PStack.pPos = PStack.pPos - n), 0, (unsigned int)n); return PStack.pPos; } /* ** Return the number of bytes left which can be ** sqlite3_wasm_pstack_alloc()'d. */ SQLITE_WASM_KEEP int sqlite3_wasm_pstack_remaining(void){ assert(PStack.pPos >= PStack.pBegin); assert(PStack.pPos <= PStack.pEnd); return (int)(PStack.pPos - PStack.pBegin); } /* ** Return the total number of bytes available in the pstack, including ** any space which is currently allocated. This value is a ** compile-time constant. */ SQLITE_WASM_KEEP int sqlite3_wasm_pstack_quota(void){ return (int)(PStack.pEnd - PStack.pBegin); } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** For purposes of certain hand-crafted C/Wasm function bindings, we ** need a way of reporting errors which is consistent with the rest of ** the C API, as opposed to throwing JS exceptions. To that end, this ** internal-use-only function is a thin proxy around ** sqlite3ErrorWithMessage(). The intent is that it only be used from ** Wasm bindings such as sqlite3_prepare_v2/v3(), and definitely not ** from client code. ** ** Returns err_code. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_error(sqlite3*db, int err_code, const char *zMsg){ if( db!=0 ){ if( 0!=zMsg ){ const int nMsg = sqlite3Strlen30(zMsg); sqlite3ErrorWithMsg(db, err_code, "%.*s", nMsg, zMsg); }else{ sqlite3ErrorWithMsg(db, err_code, NULL); |
︙ | ︙ | |||
368 369 370 371 372 373 374 | int v4; void * ppV; const char * cstr; int64_t v8; void (*xFunc)(void*); }; typedef struct WasmTestStruct WasmTestStruct; | | | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 | int v4; void * ppV; const char * cstr; int64_t v8; void (*xFunc)(void*); }; typedef struct WasmTestStruct WasmTestStruct; SQLITE_WASM_KEEP void sqlite3_wasm_test_struct(WasmTestStruct * s){ if(s){ s->v4 *= 2; s->v8 = s->v4 * 2; s->ppV = s; s->cstr = __FILE__; if(s->xFunc) s->xFunc(s); |
︙ | ︙ | |||
396 397 398 399 400 401 402 | ** the JS environment. The JSON is initialized the first time this ** function is called and that result is reused for all future calls. ** ** If this function returns NULL then it means that the internal ** buffer is not large enough for the generated JSON and needs to be ** increased. In debug builds that will trigger an assert(). */ | | | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 | ** the JS environment. The JSON is initialized the first time this ** function is called and that result is reused for all future calls. ** ** If this function returns NULL then it means that the internal ** buffer is not large enough for the generated JSON and needs to be ** increased. In debug builds that will trigger an assert(). */ SQLITE_WASM_KEEP const char * sqlite3_wasm_enum_json(void){ static char aBuffer[1024 * 20] = {0} /* where the JSON goes */; int n = 0, nChildren = 0, nStruct = 0 /* output counters for figuring out where commas go */; char * zPos = &aBuffer[1] /* skip first byte for now to help protect ** against a small race condition */; char const * const zEnd = &aBuffer[0] + sizeof(aBuffer) /* one-past-the-end */; |
︙ | ︙ | |||
491 492 493 494 495 496 497 | (sqlite3_int64)(sqlite3_free)); } _DefGroup; DefGroup(changeset){ DefInt(SQLITE_CHANGESETSTART_INVERT); DefInt(SQLITE_CHANGESETAPPLY_NOSAVEPOINT); DefInt(SQLITE_CHANGESETAPPLY_INVERT); | < | 468 469 470 471 472 473 474 475 476 477 478 479 480 481 | (sqlite3_int64)(sqlite3_free)); } _DefGroup; DefGroup(changeset){ DefInt(SQLITE_CHANGESETSTART_INVERT); DefInt(SQLITE_CHANGESETAPPLY_NOSAVEPOINT); DefInt(SQLITE_CHANGESETAPPLY_INVERT); DefInt(SQLITE_CHANGESET_DATA); DefInt(SQLITE_CHANGESET_NOTFOUND); DefInt(SQLITE_CHANGESET_CONFLICT); DefInt(SQLITE_CHANGESET_CONSTRAINT); DefInt(SQLITE_CHANGESET_FOREIGN_KEY); |
︙ | ︙ | |||
563 564 565 566 567 568 569 | DefInt(SQLITE_DBCONFIG_WRITABLE_SCHEMA); DefInt(SQLITE_DBCONFIG_LEGACY_ALTER_TABLE); DefInt(SQLITE_DBCONFIG_DQS_DML); DefInt(SQLITE_DBCONFIG_DQS_DDL); DefInt(SQLITE_DBCONFIG_ENABLE_VIEW); DefInt(SQLITE_DBCONFIG_LEGACY_FILE_FORMAT); DefInt(SQLITE_DBCONFIG_TRUSTED_SCHEMA); | < < | 539 540 541 542 543 544 545 546 547 548 549 550 551 552 | DefInt(SQLITE_DBCONFIG_WRITABLE_SCHEMA); DefInt(SQLITE_DBCONFIG_LEGACY_ALTER_TABLE); DefInt(SQLITE_DBCONFIG_DQS_DML); DefInt(SQLITE_DBCONFIG_DQS_DDL); DefInt(SQLITE_DBCONFIG_ENABLE_VIEW); DefInt(SQLITE_DBCONFIG_LEGACY_FILE_FORMAT); DefInt(SQLITE_DBCONFIG_TRUSTED_SCHEMA); DefInt(SQLITE_DBCONFIG_MAX); } _DefGroup; DefGroup(dbStatus){ DefInt(SQLITE_DBSTATUS_LOOKASIDE_USED); DefInt(SQLITE_DBSTATUS_CACHE_USED); DefInt(SQLITE_DBSTATUS_SCHEMA_USED); |
︙ | ︙ | |||
636 637 638 639 640 641 642 | DefInt(SQLITE_FCNTL_DATA_VERSION); DefInt(SQLITE_FCNTL_SIZE_LIMIT); DefInt(SQLITE_FCNTL_CKPT_DONE); DefInt(SQLITE_FCNTL_RESERVE_BYTES); DefInt(SQLITE_FCNTL_CKPT_START); DefInt(SQLITE_FCNTL_EXTERNAL_READER); DefInt(SQLITE_FCNTL_CKSM_FILE); | < | 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | DefInt(SQLITE_FCNTL_DATA_VERSION); DefInt(SQLITE_FCNTL_SIZE_LIMIT); DefInt(SQLITE_FCNTL_CKPT_DONE); DefInt(SQLITE_FCNTL_RESERVE_BYTES); DefInt(SQLITE_FCNTL_CKPT_START); DefInt(SQLITE_FCNTL_EXTERNAL_READER); DefInt(SQLITE_FCNTL_CKSM_FILE); } _DefGroup; DefGroup(flock) { DefInt(SQLITE_LOCK_NONE); DefInt(SQLITE_LOCK_SHARED); DefInt(SQLITE_LOCK_RESERVED); DefInt(SQLITE_LOCK_PENDING); |
︙ | ︙ | |||
926 927 928 929 930 931 932 | DefInt(SQLITE_INDEX_CONSTRAINT_IS); DefInt(SQLITE_INDEX_CONSTRAINT_LIMIT); DefInt(SQLITE_INDEX_CONSTRAINT_OFFSET); DefInt(SQLITE_INDEX_CONSTRAINT_FUNCTION); DefInt(SQLITE_VTAB_CONSTRAINT_SUPPORT); DefInt(SQLITE_VTAB_INNOCUOUS); DefInt(SQLITE_VTAB_DIRECTONLY); | < | 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | DefInt(SQLITE_INDEX_CONSTRAINT_IS); DefInt(SQLITE_INDEX_CONSTRAINT_LIMIT); DefInt(SQLITE_INDEX_CONSTRAINT_OFFSET); DefInt(SQLITE_INDEX_CONSTRAINT_FUNCTION); DefInt(SQLITE_VTAB_CONSTRAINT_SUPPORT); DefInt(SQLITE_VTAB_INNOCUOUS); DefInt(SQLITE_VTAB_DIRECTONLY); DefInt(SQLITE_ROLLBACK); //DefInt(SQLITE_IGNORE); // Also used by sqlite3_authorizer() callback DefInt(SQLITE_FAIL); //DefInt(SQLITE_ABORT); // Also an error code DefInt(SQLITE_REPLACE); } _DefGroup; |
︙ | ︙ | |||
1206 1207 1208 1209 1210 1211 1212 | ** ** This function invokes the xDelete method of the given VFS (or the ** default VFS if pVfs is NULL), passing on the given filename. If ** zName is NULL, no default VFS is found, or it has no xDelete ** method, SQLITE_MISUSE is returned, else the result of the xDelete() ** call is returned. */ | | | | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 | ** ** This function invokes the xDelete method of the given VFS (or the ** default VFS if pVfs is NULL), passing on the given filename. If ** zName is NULL, no default VFS is found, or it has no xDelete ** method, SQLITE_MISUSE is returned, else the result of the xDelete() ** call is returned. */ SQLITE_WASM_KEEP int sqlite3_wasm_vfs_unlink(sqlite3_vfs *pVfs, const char *zName){ int rc = SQLITE_MISUSE /* ??? */; if( 0==pVfs && 0!=zName ) pVfs = sqlite3_vfs_find(0); if( zName && pVfs && pVfs->xDelete ){ rc = pVfs->xDelete(pVfs, zName, 1); } return rc; } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Returns a pointer to the given DB's VFS for the given DB name, ** defaulting to "main" if zDbName is 0. Returns 0 if no db with the ** given name is open. */ SQLITE_WASM_KEEP sqlite3_vfs * sqlite3_wasm_db_vfs(sqlite3 *pDb, const char *zDbName){ sqlite3_vfs * pVfs = 0; sqlite3_file_control(pDb, zDbName ? zDbName : "main", SQLITE_FCNTL_VFS_POINTER, &pVfs); return pVfs; } |
︙ | ︙ | |||
1247 1248 1249 1250 1251 1252 1253 | ** But beware: virtual tables destroyed that way do not have their ** xDestroy() called, so will leak if they require that function for ** proper cleanup. ** ** Returns 0 on success, an SQLITE_xxx code on error. Returns ** SQLITE_MISUSE if pDb is NULL. */ | | | 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 | ** But beware: virtual tables destroyed that way do not have their ** xDestroy() called, so will leak if they require that function for ** proper cleanup. ** ** Returns 0 on success, an SQLITE_xxx code on error. Returns ** SQLITE_MISUSE if pDb is NULL. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_reset(sqlite3 *pDb){ int rc = SQLITE_MISUSE; if( pDb ){ sqlite3_table_column_metadata(pDb, "main", 0, 0, 0, 0, 0, 0, 0); rc = sqlite3_db_config(pDb, SQLITE_DBCONFIG_RESET_DATABASE, 1, 0); if( 0==rc ){ rc = sqlite3_exec(pDb, "VACUUM", 0, 0, 0); |
︙ | ︙ | |||
1278 1279 1280 1281 1282 1283 1284 | ** expects that it will be the only thread reading the db file and ** takes no measures to ensure that is the case. ** ** This implementation appears to work fine, but ** sqlite3_wasm_db_serialize() is arguably the better way to achieve ** this. */ | | | 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 | ** expects that it will be the only thread reading the db file and ** takes no measures to ensure that is the case. ** ** This implementation appears to work fine, but ** sqlite3_wasm_db_serialize() is arguably the better way to achieve ** this. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_export_chunked( sqlite3* pDb, int (*xCallback)(unsigned const char *zOut, int n) ){ sqlite3_int64 nSize = 0; sqlite3_int64 nPos = 0; sqlite3_file * pFile = 0; unsigned char buf[1024 * 8]; int nBuf = (int)sizeof(buf); |
︙ | ︙ | |||
1329 1330 1331 1332 1333 1334 1335 | ** mFlags includes SQLITE_SERIALIZE_NOCOPY and the database has no ** contiguous memory representation, in which case `*pOut` will be ** NULL but 0 will be returned. ** ** If `*pOut` is not NULL, the caller is responsible for passing it to ** sqlite3_free() to free it. */ | | | 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 | ** mFlags includes SQLITE_SERIALIZE_NOCOPY and the database has no ** contiguous memory representation, in which case `*pOut` will be ** NULL but 0 will be returned. ** ** If `*pOut` is not NULL, the caller is responsible for passing it to ** sqlite3_free() to free it. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_serialize( sqlite3 *pDb, const char *zSchema, unsigned char **pOut, sqlite3_int64 *nOut, unsigned int mFlags ){ unsigned char * z; if( !pDb || !pOut ) return SQLITE_MISUSE; if( nOut ) *nOut = 0; z = sqlite3_serialize(pDb, zSchema ? zSchema : "main", nOut, mFlags); |
︙ | ︙ | |||
1386 1387 1388 1389 1390 1391 1392 | ** Returns 0 on success. On error, it returns a code described above ** or propagates a code from one of the I/O methods. ** ** Design note: nData is an integer, instead of int64, for WASM ** portability, so that the API can still work in builds where BigInt ** support is disabled or unavailable. */ | | | 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 | ** Returns 0 on success. On error, it returns a code described above ** or propagates a code from one of the I/O methods. ** ** Design note: nData is an integer, instead of int64, for WASM ** portability, so that the API can still work in builds where BigInt ** support is disabled or unavailable. */ SQLITE_WASM_KEEP int sqlite3_wasm_vfs_create_file( sqlite3_vfs *pVfs, const char *zFilename, const unsigned char * pData, int nData ){ int rc; sqlite3_file *pFile = 0; sqlite3_io_methods const *pIo; |
︙ | ︙ | |||
1470 1471 1472 1473 1474 1475 1476 | ** ** Allocates sqlite3KvvfsMethods.nKeySize bytes from ** sqlite3_wasm_pstack_alloc() and returns 0 if that allocation fails, ** else it passes that string to kvstorageMakeKey() and returns a ** NUL-terminated pointer to that string. It is up to the caller to ** use sqlite3_wasm_pstack_restore() to free the returned pointer. */ | | | | | < < | | | | | | 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 | ** ** Allocates sqlite3KvvfsMethods.nKeySize bytes from ** sqlite3_wasm_pstack_alloc() and returns 0 if that allocation fails, ** else it passes that string to kvstorageMakeKey() and returns a ** NUL-terminated pointer to that string. It is up to the caller to ** use sqlite3_wasm_pstack_restore() to free the returned pointer. */ SQLITE_WASM_KEEP char * sqlite3_wasm_kvvfsMakeKeyOnPstack(const char *zClass, const char *zKeyIn){ assert(sqlite3KvvfsMethods.nKeySize>24); char *zKeyOut = (char *)sqlite3_wasm_pstack_alloc(sqlite3KvvfsMethods.nKeySize); if(zKeyOut){ kvstorageMakeKey(zClass, zKeyIn, zKeyOut); } return zKeyOut; } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Returns the pointer to the singleton object which holds the kvvfs ** I/O methods and associated state. */ SQLITE_WASM_KEEP sqlite3_kvvfs_methods * sqlite3_wasm_kvvfs_methods(void){ return &sqlite3KvvfsMethods; } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** This is a proxy for the variadic sqlite3_vtab_config() which passes ** its argument on, or not, to sqlite3_vtab_config(), depending on the ** value of its 2nd argument. Returns the result of ** sqlite3_vtab_config(), or SQLITE_MISUSE if the 2nd arg is not a ** valid value. */ SQLITE_WASM_KEEP int sqlite3_wasm_vtab_config(sqlite3 *pDb, int op, int arg){ switch(op){ case SQLITE_VTAB_DIRECTONLY: case SQLITE_VTAB_INNOCUOUS: return sqlite3_vtab_config(pDb, op); case SQLITE_VTAB_CONSTRAINT_SUPPORT: return sqlite3_vtab_config(pDb, op, arg); default: return SQLITE_MISUSE; } } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Wrapper for the variants of sqlite3_db_config() which take ** (int,int*) variadic args. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_config_ip(sqlite3 *pDb, int op, int arg1, int* pArg2){ switch(op){ case SQLITE_DBCONFIG_ENABLE_FKEY: case SQLITE_DBCONFIG_ENABLE_TRIGGER: case SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER: case SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION: case SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE: case SQLITE_DBCONFIG_ENABLE_QPSG: case SQLITE_DBCONFIG_TRIGGER_EQP: case SQLITE_DBCONFIG_RESET_DATABASE: case SQLITE_DBCONFIG_DEFENSIVE: case SQLITE_DBCONFIG_WRITABLE_SCHEMA: case SQLITE_DBCONFIG_LEGACY_ALTER_TABLE: case SQLITE_DBCONFIG_DQS_DML: case SQLITE_DBCONFIG_DQS_DDL: case SQLITE_DBCONFIG_ENABLE_VIEW: case SQLITE_DBCONFIG_LEGACY_FILE_FORMAT: case SQLITE_DBCONFIG_TRUSTED_SCHEMA: return sqlite3_db_config(pDb, op, arg1, pArg2); default: return SQLITE_MISUSE; } } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Wrapper for the variants of sqlite3_db_config() which take ** (void*,int,int) variadic args. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_config_pii(sqlite3 *pDb, int op, void * pArg1, int arg2, int arg3){ switch(op){ case SQLITE_DBCONFIG_LOOKASIDE: return sqlite3_db_config(pDb, op, pArg1, arg2, arg3); default: return SQLITE_MISUSE; } } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Wrapper for the variants of sqlite3_db_config() which take ** (const char *) variadic args. */ SQLITE_WASM_KEEP int sqlite3_wasm_db_config_s(sqlite3 *pDb, int op, const char *zArg){ switch(op){ case SQLITE_DBCONFIG_MAINDBNAME: return sqlite3_db_config(pDb, op, zArg); default: return SQLITE_MISUSE; } } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Binding for combinations of sqlite3_config() arguments which take ** a single integer argument. */ SQLITE_WASM_KEEP int sqlite3_wasm_config_i(int op, int arg){ return sqlite3_config(op, arg); } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Binding for combinations of sqlite3_config() arguments which take ** two int arguments. */ SQLITE_WASM_KEEP int sqlite3_wasm_config_ii(int op, int arg1, int arg2){ return sqlite3_config(op, arg1, arg2); } /* ** This function is NOT part of the sqlite3 public API. It is strictly ** for use by the sqlite project's own JS/WASM bindings. ** ** Binding for combinations of sqlite3_config() arguments which take ** a single i64 argument. */ SQLITE_WASM_KEEP int sqlite3_wasm_config_j(int op, sqlite3_int64 arg){ return sqlite3_config(op, arg); } #if 0 // Pending removal after verification of a workaround discussed in the // forum post linked to below. |
︙ | ︙ | |||
1643 1644 1645 1646 1647 1648 1649 | ** ``` ** ** Using a function to return this pointer, as opposed to exporting it ** via sqlite3_wasm_enum_json(), is an attempt to work around a ** Safari-specific quirk covered at ** https://sqlite.org/forum/info/e5b20e1feb37a19a. **/ | | | 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 | ** ``` ** ** Using a function to return this pointer, as opposed to exporting it ** via sqlite3_wasm_enum_json(), is an attempt to work around a ** Safari-specific quirk covered at ** https://sqlite.org/forum/info/e5b20e1feb37a19a. **/ SQLITE_WASM_KEEP void * sqlite3_wasm_ptr_to_sqlite3_free(void){ return (void*)sqlite3_free; } #endif #if defined(__EMSCRIPTEN__) && defined(SQLITE_ENABLE_WASMFS) #include <emscripten/wasmfs.h> |
︙ | ︙ | |||
1673 1674 1675 1676 1677 1678 1679 | ** NULL or empty, it defaults to "/opfs". ** ** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend ** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in ** the virtual FS fails. In builds compiled without SQLITE_ENABLE_WASMFS ** defined, SQLITE_NOTFOUND is returned without side effects. */ | | | | | | | | | | | | | | 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 | ** NULL or empty, it defaults to "/opfs". ** ** Returns 0 on success, SQLITE_NOMEM if instantiation of the backend ** object fails, SQLITE_IOERR if mkdir() of the zMountPoint dir in ** the virtual FS fails. In builds compiled without SQLITE_ENABLE_WASMFS ** defined, SQLITE_NOTFOUND is returned without side effects. */ SQLITE_WASM_KEEP int sqlite3_wasm_init_wasmfs(const char *zMountPoint){ static backend_t pOpfs = 0; if( !zMountPoint || !*zMountPoint ) zMountPoint = "/opfs"; if( !pOpfs ){ pOpfs = wasmfs_create_opfs_backend(); } /** It's not enough to instantiate the backend. We have to create a mountpoint in the VFS and attach the backend to it. */ if( pOpfs && 0!=access(zMountPoint, F_OK) ){ /* Note that this check and is not robust but it will hypothetically suffice for the transient wasm-based virtual filesystem we're currently running in. */ const int rc = wasmfs_create_directory(zMountPoint, 0777, pOpfs); /*emscripten_console_logf("OPFS mkdir(%s) rc=%d", zMountPoint, rc);*/ if(rc) return SQLITE_IOERR; } return pOpfs ? 0 : SQLITE_NOMEM; } #else SQLITE_WASM_KEEP int sqlite3_wasm_init_wasmfs(const char *zUnused){ //emscripten_console_warn("WASMFS OPFS is not compiled in."); if(zUnused){/*unused*/} return SQLITE_NOTFOUND; } #endif /* __EMSCRIPTEN__ && SQLITE_ENABLE_WASMFS */ #if SQLITE_WASM_TESTS SQLITE_WASM_KEEP int sqlite3_wasm_test_intptr(int * p){ return *p = *p * 2; } SQLITE_WASM_KEEP void * sqlite3_wasm_test_voidptr(void * p){ return p; } SQLITE_WASM_KEEP int64_t sqlite3_wasm_test_int64_max(void){ return (int64_t)0x7fffffffffffffff; } SQLITE_WASM_KEEP int64_t sqlite3_wasm_test_int64_min(void){ return ~sqlite3_wasm_test_int64_max(); } SQLITE_WASM_KEEP int64_t sqlite3_wasm_test_int64_times2(int64_t x){ return x * 2; } SQLITE_WASM_KEEP void sqlite3_wasm_test_int64_minmax(int64_t * min, int64_t *max){ *max = sqlite3_wasm_test_int64_max(); *min = sqlite3_wasm_test_int64_min(); /*printf("minmax: min=%lld, max=%lld\n", *min, *max);*/ } SQLITE_WASM_KEEP int64_t sqlite3_wasm_test_int64ptr(int64_t * p){ /*printf("sqlite3_wasm_test_int64ptr( @%lld = 0x%llx )\n", (int64_t)p, *p);*/ return *p = *p * 2; } SQLITE_WASM_KEEP void sqlite3_wasm_test_stack_overflow(int recurse){ if(recurse) sqlite3_wasm_test_stack_overflow(recurse); } /* For testing the 'string:dealloc' whwasmutil.xWrap() conversion. */ SQLITE_WASM_KEEP char * sqlite3_wasm_test_str_hello(int fail){ char * s = fail ? 0 : (char *)sqlite3_malloc(6); if(s){ memcpy(s, "hello", 5); s[5] = 0; } return s; } #endif /* SQLITE_WASM_TESTS */ #undef SQLITE_WASM_KEEP |
Changes to ext/wasm/api/sqlite3-worker1.c-pp.js.
︙ | ︙ | |||
27 28 29 30 31 32 33 34 | above in order to know when the module has completed initialization. This file accepts a URL arguments to adjust how it loads sqlite3.js: - `sqlite3.dir`, if set, treats the given directory name as the directory from which `sqlite3.js` will be loaded. */ //#if target=es6-bundler-friendly | > > | < < < | < < | > > > | 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | above in order to know when the module has completed initialization. This file accepts a URL arguments to adjust how it loads sqlite3.js: - `sqlite3.dir`, if set, treats the given directory name as the directory from which `sqlite3.js` will be loaded. */ "use strict"; (()=>{ //#if target=es6-bundler-friendly importScripts('sqlite3.js'); //#else const urlParams = new URL(self.location.href).searchParams; let theJs = 'sqlite3.js'; if(urlParams.has('sqlite3.dir')){ theJs = urlParams.get('sqlite3.dir') + '/' + theJs; } //console.warn("worker1 theJs =",theJs); importScripts(theJs); //#endif sqlite3InitModule().then((sqlite3)=>{ sqlite3.initWorker1API(); }); })(); |
Changes to ext/wasm/common/whwasmutil.js.
︙ | ︙ | |||
41 42 43 44 45 46 47 | things still requires using Emscripten's glue, but the post-load utility APIs provided by this code are still usable as replacements for their sub-optimally-documented Emscripten counterparts. Intended usage: ``` | | | | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | things still requires using Emscripten's glue, but the post-load utility APIs provided by this code are still usable as replacements for their sub-optimally-documented Emscripten counterparts. Intended usage: ``` self.WhWasmUtilInstaller(appObject); delete self.WhWasmUtilInstaller; ``` Its global-scope symbol is intended only to provide an easy way to make it available to 3rd-party scripts and "should" be deleted after calling it. That symbols is _not_ used within the library. Forewarning: this API explicitly targets only browser |
︙ | ︙ | |||
167 168 169 170 171 172 173 | https://fossil.wanderinghorse.net/r/jaccwabbyt More specifically: https://fossil.wanderinghorse.net/r/jaccwabbyt/file/common/whwasmutil.js */ | | | 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | https://fossil.wanderinghorse.net/r/jaccwabbyt More specifically: https://fossil.wanderinghorse.net/r/jaccwabbyt/file/common/whwasmutil.js */ self.WhWasmUtilInstaller = function(target){ 'use strict'; if(undefined===target.bigIntEnabled){ target.bigIntEnabled = !!self['BigInt64Array']; } /** Throws a new Error, the message of which is the concatenation of all args with a space between each. */ |
︙ | ︙ | |||
2190 2191 2192 2193 2194 2195 2196 | (Note that the initial `then()` attached to the promise gets only that object, and not the `config` one.) Error handling is up to the caller, who may attach a `catch()` call to the promise. */ | | | 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 | (Note that the initial `then()` attached to the promise gets only that object, and not the `config` one.) Error handling is up to the caller, who may attach a `catch()` call to the promise. */ self.WhWasmUtilInstaller.yawl = function(config){ const wfetch = ()=>fetch(config.uri, {credentials: 'same-origin'}); const wui = this; const finalThen = function(arg){ //log("finalThen()",arg); if(config.wasmUtilTarget){ const toss = (...args)=>{throw new Error(args.join(' '))}; const tgt = config.wasmUtilTarget; |
︙ | ︙ | |||
2236 2237 2238 2239 2240 2241 2242 | : function loadWasmOldSchool(){ // Safari < v15 return wfetch() .then(response => response.arrayBuffer()) .then(bytes => WebAssembly.instantiate(bytes, config.imports||{})) .then(finalThen); }; return loadWasm; | | | 2236 2237 2238 2239 2240 2241 2242 2243 | : function loadWasmOldSchool(){ // Safari < v15 return wfetch() .then(response => response.arrayBuffer()) .then(bytes => WebAssembly.instantiate(bytes, config.imports||{})) .then(finalThen); }; return loadWasm; }.bind(self.WhWasmUtilInstaller)/*yawl()*/; |
Changes to ext/wasm/demo-worker1-promiser.js.
1 2 3 4 5 6 7 8 9 10 11 | /* 2022-08-23 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 | /* 2022-08-23 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. *********************************************************************** Demonstration of the sqlite3 Worker API #1 Promiser: a Promise-based proxy for for the sqlite3 Worker #1 API. */ 'use strict'; (function(){ const T = self.SqliteTestUtil; const eOutput = document.querySelector('#test-output'); |
︙ | ︙ | |||
77 78 79 80 81 82 83 | const r = ev.result; log('sqlite3.config subset:', r); T.assert('boolean' === typeof r.bigIntEnabled); sqConfig = r; }); logHtml('', "Sending 'open' message and waiting for its response before continuing..."); | | | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | const r = ev.result; log('sqlite3.config subset:', r); T.assert('boolean' === typeof r.bigIntEnabled); sqConfig = r; }); logHtml('', "Sending 'open' message and waiting for its response before continuing..."); await wtest('open', { filename: dbFilename, simulateError: 0 /* if true, fail the 'open' */, }, function(ev){ const r = ev.result; log("then open result",r); T.assert(ev.dbId === r.dbId) |
︙ | ︙ |
Changes to ext/wasm/demo-worker1.js.
︙ | ︙ | |||
58 59 60 61 62 63 64 | this.queue.push(callback); return type + '-' + (++this.id); }, shift: function(){ return this.queue.shift(); } }; | | | | 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 | this.queue.push(callback); return type + '-' + (++this.id); }, shift: function(){ return this.queue.shift(); } }; const testCount = ()=>{ logHtml("","Total test count:",T.counter+". Total time =",(performance.now() - startTime),"ms"); }; const logEventResult = function(ev){ const evd = ev.result; logHtml(evd.errorClass ? 'error' : '', "runOneTest",ev.messageId,"Worker time =", (ev.workerRespondTime - ev.workerReceivedTime),"ms.", "Round-trip event time =", (performance.now() - ev.departureTime),"ms.", (evd.errorClass ? ev.message : "")//, JSON.stringify(evd) ); }; const runOneTest = function(eventType, eventArgs, callback){ T.assert(eventArgs && 'object'===typeof eventArgs); /* ^^^ that is for the testing and messageId-related code, not a hard requirement of all of the Worker-exposed APIs. */ |
︙ | ︙ |
Changes to ext/wasm/dist.make.
︙ | ︙ | |||
66 67 68 69 70 71 72 | endef # STRIP_K1.js = list of JS files which need to be passed through # $(bin.stripcomments) with a single -k flag. STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \ $(sqlite3-worker1-bundler-friendly.js) $(sqlite3-worker1-promiser-bundler-friendly.js) # STRIP_K2.js = list of JS files which need to be passed through # $(bin.stripcomments) with two -k flags. | | < | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | endef # STRIP_K1.js = list of JS files which need to be passed through # $(bin.stripcomments) with a single -k flag. STRIP_K1.js := $(sqlite3-worker1.js) $(sqlite3-worker1-promiser.js) \ $(sqlite3-worker1-bundler-friendly.js) $(sqlite3-worker1-promiser-bundler-friendly.js) # STRIP_K2.js = list of JS files which need to be passed through # $(bin.stripcomments) with two -k flags. STRIP_K2.js := $(sqlite3.js) $(sqlite3.mjs) $(sqlite3-bundler-friendly.mjs) ######################################################################## # dist: create the end-user deliverable archive. # # Maintenance reminder: because dist depends on $(dist.build), and # $(dist.build) will depend on clean, having any deps on # $(dist-archive) which themselves may be cleaned up by the clean # target will lead to grief in parallel builds (-j #). Thus |
︙ | ︙ |
Deleted ext/wasm/example_extra_init.c.
|
| < < < < < < < < < < < < < < < < < < < < < < < |
Changes to ext/wasm/fiddle.make.
︙ | ︙ | |||
25 26 27 28 29 30 31 | EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle fiddle.emcc-flags = \ $(emcc.cflags) $(emcc_opt_full) \ --minify 0 \ -sALLOW_TABLE_GROWTH \ -sABORTING_MALLOC \ | | > | 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | EXPORTED_FUNCTIONS.fiddle := $(dir.tmp)/EXPORTED_FUNCTIONS.fiddle fiddle.emcc-flags = \ $(emcc.cflags) $(emcc_opt_full) \ --minify 0 \ -sALLOW_TABLE_GROWTH \ -sABORTING_MALLOC \ -sSTRICT_JS \ -sENVIRONMENT=web,worker \ -sMODULARIZE \ -sDYNAMIC_EXECUTION=0 \ -sWASM_BIGINT=$(emcc.WASM_BIGINT) \ -sEXPORT_NAME=$(sqlite3.js.init-func) \ -Wno-limited-postlink-optimizations \ $(sqlite3.js.flags.--post-js) \ $(emcc.exportedRuntimeMethods) \ -sEXPORTED_FUNCTIONS=@$(abspath $(EXPORTED_FUNCTIONS.fiddle)) \ -sEXPORTED_RUNTIME_METHODS=FS,wasmMemory \ $(SQLITE_OPT) $(SHELL_OPT) \ -DSQLITE_SHELL_FIDDLE # -D_POSIX_C_SOURCE is needed for strdup() with emcc |
︙ | ︙ | |||
54 55 56 57 58 59 60 | fiddle-module.wasm := $(subst .js,.wasm,$(fiddle-module.js)) fiddle.cses := $(dir.top)/shell.c $(sqlite3-wasm.c) fiddle.SOAP.js := $(dir.fiddle)/$(notdir $(SOAP.js)) $(fiddle.SOAP.js): $(SOAP.js) cp $< $@ | | | 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | fiddle-module.wasm := $(subst .js,.wasm,$(fiddle-module.js)) fiddle.cses := $(dir.top)/shell.c $(sqlite3-wasm.c) fiddle.SOAP.js := $(dir.fiddle)/$(notdir $(SOAP.js)) $(fiddle.SOAP.js): $(SOAP.js) cp $< $@ $(eval $(call call-make-pre-js,fiddle-module,vanilla)) $(fiddle-module.js): $(MAKEFILE) $(MAKEFILE.fiddle) \ $(EXPORTED_FUNCTIONS.fiddle) \ $(fiddle.cses) $(pre-post-fiddle-module.deps.vanilla) $(fiddle.SOAP.js) $(emcc.bin) -o $@ $(fiddle.emcc-flags) \ $(pre-post-fiddle-module.flags.vanilla) \ $(fiddle.cses) $(maybe-wasm-strip) $(fiddle-module.wasm) |
︙ | ︙ |
Changes to ext/wasm/fiddle/fiddle-worker.js.
︙ | ︙ | |||
42 43 44 45 46 47 48 | {type:'stdout', data: 'Hi, world.'} - module: Status text. This is intended to alert the main thread about module loading status so that, e.g., the main thread can update a progress widget and DTRT when the module is finished loading and available for work. Status messages come in the form | | | 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | {type:'stdout', data: 'Hi, world.'} - module: Status text. This is intended to alert the main thread about module loading status so that, e.g., the main thread can update a progress widget and DTRT when the module is finished loading and available for work. Status messages come in the form {type:'module', data:{ type:'status', data: {text:string|null, step:1-based-integer} } with an incrementing step value for each subsequent message. When the module loading is complete, a message with a text value of |
︙ | ︙ | |||
366 367 368 369 370 371 372 | initFiddleModule() is installed via fiddle-module.js due to building with: emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule */ sqlite3InitModule(fiddleModule).then((_sqlite3)=>{ sqlite3 = _sqlite3; | < < < | 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | initFiddleModule() is installed via fiddle-module.js due to building with: emcc ... -sMODULARIZE=1 -sEXPORT_NAME=initFiddleModule */ sqlite3InitModule(fiddleModule).then((_sqlite3)=>{ sqlite3 = _sqlite3; const dbVfs = sqlite3.wasm.xWrap('fiddle_db_vfs', "*", ['string']); fiddleModule.fsUnlink = (fn)=>{ return sqlite3.wasm.sqlite3_wasm_vfs_unlink(dbVfs(0), fn); }; wMsg('fiddle-ready'); })/*then()*/; })(); |
Changes to ext/wasm/index-dist.html.
︙ | ︙ | |||
37 38 39 40 41 42 43 | <div>Below is the list of demo pages for the sqlite3 WASM builds. The intent is that <em>this</em> page be run using the functional equivalent of:</div> <blockquote><pre><a href='https://sqlite.org/althttpd'>althttpd</a> -enable-sab -page index.html</pre></blockquote> <div>and the individual pages be started in their own tab. Warnings and Caveats: <ul class='warning'> | | < < < < | | | | | | < < < < < < < < | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | <div>Below is the list of demo pages for the sqlite3 WASM builds. The intent is that <em>this</em> page be run using the functional equivalent of:</div> <blockquote><pre><a href='https://sqlite.org/althttpd'>althttpd</a> -enable-sab -page index.html</pre></blockquote> <div>and the individual pages be started in their own tab. Warnings and Caveats: <ul class='warning'> <li>Some of these pages require that the web server emit the so-called <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a> and <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a> headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the <code>-enable-sab</code> flag for that. </li> </ul> </div> <div>The tests and demos... <ul id='test-list'> <li>Core-most tests <ul> |
︙ | ︙ |
Changes to ext/wasm/index.html.
︙ | ︙ | |||
22 23 24 25 26 27 28 | builds. All of them require that this directory have been "make"d first. The intent is that <em>this</em> page be run using:</div> <blockquote><pre>althttpd -enable-sab -page index.html</pre></blockquote> <div>and the individual tests be started in their own tab. Warnings and Caveats: <ul class='warning'> | | < < < < | | | | | | | | | | | | < < | 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 | builds. All of them require that this directory have been "make"d first. The intent is that <em>this</em> page be run using:</div> <blockquote><pre>althttpd -enable-sab -page index.html</pre></blockquote> <div>and the individual tests be started in their own tab. Warnings and Caveats: <ul class='warning'> <li>Some of these pages require that the web server emit the so-called <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Opener-Policy'>COOP</a> and <a href='https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cross-Origin-Embedder-Policy'>COEP</a> headers. <a href='https://sqlite.org/althttpd'>althttpd</a> requires the <code>-enable-sab</code> flag for that. </li> <li>Any OPFS-related pages require very recent version of Chrome or Chromium (v102 at least, possibly newer). OPFS support in the other major browsers is pending. Development and testing is currently done against a dev-channel release of Chrome (v110 as of 2022-12-02). </li> </ul> </div> <div>The tests and demos... <ul id='test-list'> <li>Core-most tests <ul> |
︙ | ︙ |
Changes to ext/wasm/jaccwabyt/jaccwabyt.js.
︙ | ︙ | |||
15 16 17 18 19 20 21 | Project homes: - https://fossil.wanderinghorse.net/r/jaccwabyt - https://sqlite.org/src/dir/ext/wasm/jaccwabyt */ 'use strict'; | | | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | Project homes: - https://fossil.wanderinghorse.net/r/jaccwabyt - https://sqlite.org/src/dir/ext/wasm/jaccwabyt */ 'use strict'; self.Jaccwabyt = function StructBinderFactory(config){ /* ^^^^ it is recommended that clients move that object into wherever they'd like to have it and delete the self-held copy ("self" being the global window or worker object). This API does not require the global reference - it is simply installed as a convenience for connecting these bits to other co-developed code before it gets removed from the global namespace. */ |
︙ | ︙ |
Changes to ext/wasm/speedtest1-worker.html.
︙ | ︙ | |||
19 20 21 22 23 24 25 | On a slow internet connection this may take a moment. If this message displays for "a long time", intialization may have failed and the JavaScript console may contain clues as to why. </div> </figure> <div class="emscripten" id="module-status">Downloading...</div> <div class="emscripten"> | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | On a slow internet connection this may take a moment. If this message displays for "a long time", intialization may have failed and the JavaScript console may contain clues as to why. </div> </figure> <div class="emscripten" id="module-status">Downloading...</div> <div class="emscripten"> <progress value="0" max="100" id="module-progress" hidden='1'></progress> </div><!-- /emscripten bits --> <fieldset id='ui-controls' class='hidden'> <legend>Options</legend> <div id='toolbar'> <div id='toolbar-select'> <select id='select-flags' size='10' multiple></select> <div>The following flags can be passed as URL parameters: |
︙ | ︙ | |||
64 65 66 67 68 69 70 | <div id='test-output'> </div> <div id='tips'> <strong>Tips:</strong> <ul> <li>Control-click the flags to (de)select multiple flags.</li> <li>The <tt>--big-transactions</tt> flag is important for two | | | | > | 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | <div id='test-output'> </div> <div id='tips'> <strong>Tips:</strong> <ul> <li>Control-click the flags to (de)select multiple flags.</li> <li>The <tt>--big-transactions</tt> flag is important for two of the bigger tests. Without it, those tests create a combined total of 140k implicit transactions, reducing their speed to an absolute crawl, especially when WASMFS is activated. </li> <li>The easiest way to try different optimization levels is, from this directory: <pre>$ rm -f jswasm/speedtest1.js; make -e emcc_opt='-O2' speedtest1</pre> Then reload this page. -O2 seems to consistently produce the fastest results. </li> </ul> |
︙ | ︙ |
Changes to ext/wasm/tester1.c-pp.js.
︙ | ︙ | |||
1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 | rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_MAX+1, 0); T.assert(capi.SQLITE_MISUSE === rc); rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_MAINDBNAME, "main"); T.assert(0 === rc); const stack = wasm.pstack.pointer; try { const [pCur, pHi] = wasm.pstack.allocChunks(2,'i64'); wasm.poke32([pCur, pHi], 0); let [vCur, vHi] = wasm.peek32(pCur, pHi); T.assert(0===vCur).assert(0===vHi); rc = capi.sqlite3_status(capi.SQLITE_STATUS_MEMORY_USED, pCur, pHi, 0); [vCur, vHi] = wasm.peek32(pCur, pHi); //console.warn("i32 vCur,vHi",vCur,vHi); | > > > > > > > > > > > | 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 | rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_MAX+1, 0); T.assert(capi.SQLITE_MISUSE === rc); rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_MAINDBNAME, "main"); T.assert(0 === rc); const stack = wasm.pstack.pointer; try { const [pCur, pHi] = wasm.pstack.allocChunks(2,'i64'); rc = capi.sqlite3_db_status(this.db, capi.SQLITE_DBSTATUS_LOOKASIDE_USED, pCur, pHi, 0); T.assert(0===rc); if(!wasm.peek32(pCur)){ rc = capi.sqlite3_db_config(this.db, capi.SQLITE_DBCONFIG_LOOKASIDE, 0, 4096, 12); T.assert(0 === rc); }else{ console.debug("Cannot test db_config(SQLITE_DBCONFIG_LOOKASIDE)", "while lookaside memory is in use."); } wasm.poke32([pCur, pHi], 0); let [vCur, vHi] = wasm.peek32(pCur, pHi); T.assert(0===vCur).assert(0===vHi); rc = capi.sqlite3_status(capi.SQLITE_STATUS_MEMORY_USED, pCur, pHi, 0); [vCur, vHi] = wasm.peek32(pCur, pHi); //console.warn("i32 vCur,vHi",vCur,vHi); |
︙ | ︙ | |||
1448 1449 1450 1451 1452 1453 1454 | try { db.prepare("/*empty SQL*/"); toss("Must not be reached."); }catch(e){ T.assert(e instanceof sqlite3.SQLite3Error) .assert(0==e.message.indexOf('Cannot prepare empty')); } | < < < < < < < < < < < < | 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 | try { db.prepare("/*empty SQL*/"); toss("Must not be reached."); }catch(e){ T.assert(e instanceof sqlite3.SQLite3Error) .assert(0==e.message.indexOf('Cannot prepare empty')); } })/*setup table T*/ //////////////////////////////////////////////////////////////////// .t({ name: "sqlite3_set_authorizer()", test:function(sqlite3){ T.assert(capi.SQLITE_IGNORE>0) |
︙ | ︙ |
Changes to src/alter.c.
︙ | ︙ | |||
1275 1276 1277 1278 1279 1280 1281 | rc = SQLITE_NOMEM; } sqlite3_free(zQuot); return rc; } | < < < < < < < < < < < < < | 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 | rc = SQLITE_NOMEM; } sqlite3_free(zQuot); return rc; } /* ** Resolve all symbols in the trigger at pParse->pNewTrigger, assuming ** it was read from the schema of database zDb. Return SQLITE_OK if ** successful. Otherwise, return an SQLite error code and leave an error ** message in the Parse object. */ static int renameResolveTrigger(Parse *pParse){ |
︙ | ︙ | |||
1335 1336 1337 1338 1339 1340 1341 | pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 ); if( pSel==0 ){ pStep->pExprList = 0; pSrc = 0; rc = SQLITE_NOMEM; }else{ | < < < < < < < < < < | 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 | pParse, pStep->pExprList, pSrc, 0, 0, 0, 0, 0, 0 ); if( pSel==0 ){ pStep->pExprList = 0; pSrc = 0; rc = SQLITE_NOMEM; }else{ sqlite3SelectPrep(pParse, pSel, 0); rc = pParse->nErr ? SQLITE_ERROR : SQLITE_OK; assert( pStep->pExprList==0 || pStep->pExprList==pSel->pEList ); assert( pSrc==pSel->pSrc ); if( pStep->pExprList ) pSel->pEList = 0; pSel->pSrc = 0; sqlite3SelectDelete(db, pSel); } |
︙ | ︙ |
Changes to src/analyze.c.
︙ | ︙ | |||
990 991 992 993 994 995 996 | int regRowid = iMem++; /* Rowid argument passed to stat_push() */ int regTemp = iMem++; /* Temporary use register */ int regTemp2 = iMem++; /* Second temporary use register */ int regTabname = iMem++; /* Register containing table name */ int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */ int regPrev = iMem; /* MUST BE LAST (see below) */ | < < < | | < | 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | int regRowid = iMem++; /* Rowid argument passed to stat_push() */ int regTemp = iMem++; /* Temporary use register */ int regTemp2 = iMem++; /* Second temporary use register */ int regTabname = iMem++; /* Register containing table name */ int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* Value for the stat column of sqlite_stat1 */ int regPrev = iMem; /* MUST BE LAST (see below) */ #ifdef SQLITE_ENABLE_PREUPDATE_HOOK Table *pStat1 = 0; #endif pParse->nMem = MAX(pParse->nMem, iMem); v = sqlite3GetVdbe(pParse); if( v==0 || NEVER(pTab==0) ){ return; } if( !IsOrdinaryTable(pTab) ){ /* Do not gather statistics on views or virtual tables */ return; |
︙ | ︙ | |||
1104 1105 1106 1107 1108 1109 1110 | ** end_of_scan: */ /* Make sure there are enough memory cells allocated to accommodate ** the regPrev array and a trailing rowid (the rowid slot is required ** when building a record to insert into the sample column of ** the sqlite_stat4 table. */ | | | 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 | ** end_of_scan: */ /* Make sure there are enough memory cells allocated to accommodate ** the regPrev array and a trailing rowid (the rowid slot is required ** when building a record to insert into the sample column of ** the sqlite_stat4 table. */ pParse->nMem = MAX(pParse->nMem, regPrev+nColTest); /* Open a read-only cursor on the index being analyzed. */ assert( iDb==sqlite3SchemaToIndex(db, pIdx->pSchema) ); sqlite3VdbeAddOp3(v, OP_OpenRead, iIdxCur, pIdx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "%s", pIdx->zName)); |
︙ | ︙ | |||
1276 1277 1278 1279 1280 1281 1282 | int regSample = regStat1+3; int regCol = regStat1+4; int regSampleRowid = regCol + nCol; int addrNext; int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; | < < < | < < < < < < < < < < < < < < < < < < < < < < < < < | 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 | int regSample = regStat1+3; int regCol = regStat1+4; int regSampleRowid = regCol + nCol; int addrNext; int addrIsNull; u8 seekOp = HasRowid(pTab) ? OP_NotExists : OP_NotFound; pParse->nMem = MAX(pParse->nMem, regCol+nCol); addrNext = sqlite3VdbeCurrentAddr(v); callStatGet(pParse, regStat, STAT_GET_ROWID, regSampleRowid); addrIsNull = sqlite3VdbeAddOp1(v, OP_IsNull, regSampleRowid); VdbeCoverage(v); callStatGet(pParse, regStat, STAT_GET_NEQ, regEq); callStatGet(pParse, regStat, STAT_GET_NLT, regLt); |
︙ | ︙ | |||
1385 1386 1387 1388 1389 1390 1391 | openStatTable(pParse, iDb, iStatCur, 0, 0); iMem = pParse->nMem+1; iTab = pParse->nTab; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); | < < < < < | 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 | openStatTable(pParse, iDb, iStatCur, 0, 0); iMem = pParse->nMem+1; iTab = pParse->nTab; assert( sqlite3SchemaMutexHeld(db, iDb, 0) ); for(k=sqliteHashFirst(&pSchema->tblHash); k; k=sqliteHashNext(k)){ Table *pTab = (Table*)sqliteHashData(k); analyzeOneTable(pParse, pTab, 0, iStatCur, iMem, iTab); } loadAnalysis(pParse, iDb); } /* ** Generate code that will do an analysis of a single table in ** a database. If pOnlyIdx is not NULL then it is a single index |
︙ | ︙ | |||
1777 1778 1779 1780 1781 1782 1783 | zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; nSample = sqlite3_column_int(pStmt, 1); pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); assert( pIdx==0 || pIdx->nSample==0 ); if( pIdx==0 ) continue; | < < < < < | 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 | zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; nSample = sqlite3_column_int(pStmt, 1); pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); assert( pIdx==0 || pIdx->nSample==0 ); if( pIdx==0 ) continue; assert( !HasRowid(pIdx->pTable) || pIdx->nColumn==pIdx->nKeyCol+1 ); if( !HasRowid(pIdx->pTable) && IsPrimaryKeyIndex(pIdx) ){ nIdxCol = pIdx->nKeyCol; }else{ nIdxCol = pIdx->nColumn; } pIdx->nSampleCol = nIdxCol; nByte = sizeof(IndexSample) * nSample; nByte += sizeof(tRowcnt) * nIdxCol * 3 * nSample; nByte += nIdxCol * sizeof(tRowcnt); /* Space for Index.aAvgEq[] */ pIdx->aSample = sqlite3DbMallocZero(db, nByte); if( pIdx->aSample==0 ){ sqlite3_finalize(pStmt); |
︙ | ︙ | |||
1828 1829 1830 1831 1832 1833 1834 | Index *pIdx; /* Pointer to the index object */ int nCol = 1; /* Number of columns in index */ zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); if( pIdx==0 ) continue; | < < < < < | 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 | Index *pIdx; /* Pointer to the index object */ int nCol = 1; /* Number of columns in index */ zIndex = (char *)sqlite3_column_text(pStmt, 0); if( zIndex==0 ) continue; pIdx = findIndexOrPrimaryKey(db, zIndex, zDb); if( pIdx==0 ) continue; /* This next condition is true if data has already been loaded from ** the sqlite_stat4 table. */ nCol = pIdx->nSampleCol; if( pIdx!=pPrevIdx ){ initAvgEq(pPrevIdx); pPrevIdx = pIdx; } |
︙ | ︙ | |||
1876 1877 1878 1879 1880 1881 1882 | ** the Index.aSample[] arrays of all indices. */ static int loadStat4(sqlite3 *db, const char *zDb){ int rc = SQLITE_OK; /* Result codes from subroutines */ const Table *pStat4; assert( db->lookaside.bDisable ); | < | | | 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 | ** the Index.aSample[] arrays of all indices. */ static int loadStat4(sqlite3 *db, const char *zDb){ int rc = SQLITE_OK; /* Result codes from subroutines */ const Table *pStat4; assert( db->lookaside.bDisable ); if( (pStat4 = sqlite3FindTable(db, "sqlite_stat4", zDb))!=0 && IsOrdinaryTable(pStat4) ){ rc = loadStatTbl(db, "SELECT idx,count(*) FROM %Q.sqlite_stat4 GROUP BY idx", "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat4", zDb ); } return rc; } #endif /* SQLITE_ENABLE_STAT4 */ |
︙ | ︙ |
Changes to src/backup.c.
︙ | ︙ | |||
238 239 240 241 242 243 244 | i64 iOff; assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); assert( p->bDestLocked ); assert( !isFatalError(p->rc) ); assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); assert( zSrcData ); | > > > > | > > | 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 | i64 iOff; assert( sqlite3BtreeGetReserveNoMutex(p->pSrc)>=0 ); assert( p->bDestLocked ); assert( !isFatalError(p->rc) ); assert( iSrcPg!=PENDING_BYTE_PAGE(p->pSrc->pBt) ); assert( zSrcData ); /* Catch the case where the destination is an in-memory database and the ** page sizes of the source and destination differ. */ if( nSrcPgsz!=nDestPgsz && sqlite3PagerIsMemdb(pDestPager) ){ rc = SQLITE_READONLY; } /* This loop runs once for each destination page spanned by the source ** page. For each iteration, variable iOff is set to the byte offset ** of the destination page. */ for(iOff=iEnd-(i64)nSrcPgsz; rc==SQLITE_OK && iOff<iEnd; iOff+=nDestPgsz){ DbPage *pDestPg = 0; |
︙ | ︙ | |||
371 372 373 374 375 376 377 | } /* Do not allow backup if the destination database is in WAL mode ** and the page sizes are different between source and destination */ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); pgszDest = sqlite3BtreeGetPageSize(p->pDest); destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); | | < < < | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | } /* Do not allow backup if the destination database is in WAL mode ** and the page sizes are different between source and destination */ pgszSrc = sqlite3BtreeGetPageSize(p->pSrc); pgszDest = sqlite3BtreeGetPageSize(p->pDest); destMode = sqlite3PagerGetJournalMode(sqlite3BtreePager(p->pDest)); if( SQLITE_OK==rc && destMode==PAGER_JOURNALMODE_WAL && pgszSrc!=pgszDest ){ rc = SQLITE_READONLY; } /* Now that there is a read-lock on the source database, query the ** source pager for the number of pages in the database. */ nSrcPage = (int)sqlite3BtreeLastPage(p->pSrc); |
︙ | ︙ |
Changes to src/btree.c.
︙ | ︙ | |||
132 133 134 135 136 137 138 | ** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented ** with the page number and filename associated with the (MemPage*). */ #ifdef SQLITE_DEBUG int corruptPageError(int lineno, MemPage *p){ char *zMsg; sqlite3BeginBenignMalloc(); | | | | 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 | ** normally produced as a side-effect of SQLITE_CORRUPT_BKPT is augmented ** with the page number and filename associated with the (MemPage*). */ #ifdef SQLITE_DEBUG int corruptPageError(int lineno, MemPage *p){ char *zMsg; sqlite3BeginBenignMalloc(); zMsg = sqlite3_mprintf("database corruption page %d of %s", (int)p->pgno, sqlite3PagerFilename(p->pBt->pPager, 0) ); sqlite3EndBenignMalloc(); if( zMsg ){ sqlite3ReportError(SQLITE_CORRUPT, lineno, zMsg); } sqlite3_free(zMsg); return SQLITE_CORRUPT_BKPT; |
︙ | ︙ | |||
942 943 944 945 946 947 948 | /* ** 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 */ | < < < < < < < < < < < < < < | | < < < | 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 | /* ** 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; |
︙ | ︙ | |||
1045 1046 1047 1048 1049 1050 1051 | *pRC = SQLITE_CORRUPT_BKPT; goto ptrmap_exit; } assert( offset <= (int)pBt->usableSize-5 ); pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ | | | 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 | *pRC = SQLITE_CORRUPT_BKPT; goto ptrmap_exit; } assert( offset <= (int)pBt->usableSize-5 ); pPtrmap = (u8 *)sqlite3PagerGetData(pDbPage); if( eType!=pPtrmap[offset] || get4byte(&pPtrmap[offset+1])!=parent ){ TRACE(("PTRMAP_UPDATE: %d->(%d,%d)\n", key, eType, parent)); *pRC= rc = sqlite3PagerWrite(pDbPage); if( rc==SQLITE_OK ){ pPtrmap[offset] = eType; put4byte(&pPtrmap[offset+1], parent); } } |
︙ | ︙ | |||
1244 1245 1246 1247 1248 1249 1250 | ** ** The code is inlined and the loop is unrolled for performance. ** This routine is a high-runner. */ iKey = *pIter; if( iKey>=0x80 ){ u8 x; | | | | | | | | | < < < < | 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 | ** ** The code is inlined and the loop is unrolled for performance. ** This routine is a high-runner. */ iKey = *pIter; if( iKey>=0x80 ){ u8 x; iKey = ((iKey&0x7f)<<7) | ((x = *++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<7) | ((x =*++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<7) | ((x = *++pIter) & 0x7f); if( x>=0x80 ){ iKey = (iKey<<8) | (*++pIter); } } } } } } } } pIter++; pInfo->nKey = *(i64*)&iKey; pInfo->nPayload = nPayload; pInfo->pPayload = pIter; |
︙ | ︙ | |||
1345 1346 1347 1348 1349 1350 1351 | ** Compute the total number of bytes that a Cell needs in the cell ** data area of the btree-page. The return number includes the cell ** data header and the local payload, but not any overflow page or ** the space used by the cell pointer. ** ** cellSizePtrNoPayload() => table internal nodes ** cellSizePtrTableLeaf() => table leaf nodes | | < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 | ** Compute the total number of bytes that a Cell needs in the cell ** data area of the btree-page. The return number includes the cell ** data header and the local payload, but not any overflow page or ** the space used by the cell pointer. ** ** cellSizePtrNoPayload() => table internal nodes ** cellSizePtrTableLeaf() => table leaf nodes ** cellSizePtr() => all index nodes & table leaf nodes */ static u16 cellSizePtr(MemPage *pPage, u8 *pCell){ u8 *pIter = pCell + pPage->childPtrSize; /* For looping over bytes of pCell */ u8 *pEnd; /* End mark for a varint */ u32 nSize; /* Size value to return */ #ifdef SQLITE_DEBUG /* The value returned by this function should always be the same as ** the (CellInfo.nSize) value found by doing a full parse of the ** cell. If SQLITE_DEBUG is defined, an assert() at the bottom of ** this function verifies that this invariant is not violated. */ CellInfo debuginfo; pPage->xParseCell(pPage, pCell, &debuginfo); #endif nSize = *pIter; if( nSize>=0x80 ){ pEnd = &pIter[8]; nSize &= 0x7f; do{ nSize = (nSize<<7) | (*++pIter & 0x7f); }while( *(pIter)>=0x80 && pIter<pEnd ); |
︙ | ︙ | |||
1641 1642 1643 1644 1645 1646 1647 | pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); testcase( pc==iCellFirst ); testcase( pc==iCellLast ); /* These conditions have already been verified in btreeInitPage() ** if PRAGMA cell_size_check=ON. */ | | | | 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 | pAddr = &data[cellOffset + i*2]; pc = get2byte(pAddr); testcase( pc==iCellFirst ); testcase( pc==iCellLast ); /* These conditions have already been verified in btreeInitPage() ** if PRAGMA cell_size_check=ON. */ if( pc<iCellStart || pc>iCellLast ){ return SQLITE_CORRUPT_PAGE(pPage); } assert( pc>=iCellStart && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrk<iCellStart || pc+size>usableSize ){ return SQLITE_CORRUPT_PAGE(pPage); } assert( cbrk+size<=usableSize && cbrk>=iCellStart ); testcase( cbrk+size==usableSize ); |
︙ | ︙ | |||
1759 1760 1761 1762 1763 1764 1765 | ** The caller guarantees that there is sufficient space to make the ** allocation. This routine might need to defragment in order to bring ** all the space together, however. This routine will avoid using ** the first two bytes past the cell pointer area since presumably this ** allocation is being made in order to insert a new cell, so we will ** also end up needing a new cell pointer. */ | | | 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 | ** The caller guarantees that there is sufficient space to make the ** allocation. This routine might need to defragment in order to bring ** all the space together, however. This routine will avoid using ** the first two bytes past the cell pointer area since presumably this ** allocation is being made in order to insert a new cell, so we will ** also end up needing a new cell pointer. */ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ const int hdr = pPage->hdrOffset; /* Local cache of pPage->hdrOffset */ u8 * const data = pPage->aData; /* Local cache of pPage->aData */ int top; /* First byte of cell content area */ int rc = SQLITE_OK; /* Integer return code */ u8 *pTmp; /* Temp ptr into data[] */ int gap; /* First byte of gap between cell pointers and cell content */ |
︙ | ︙ | |||
1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 | /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size ** and the reserved space is zero (the usual value for reserved space) ** then the cell content offset of an empty page wants to be 65536. ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ pTmp = &data[hdr+5]; top = get2byte(pTmp); if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ return SQLITE_CORRUPT_PAGE(pPage); } | > < < | 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 | /* EVIDENCE-OF: R-29356-02391 If the database uses a 65536-byte page size ** and the reserved space is zero (the usual value for reserved space) ** then the cell content offset of an empty page wants to be 65536. ** However, that integer is too large to be stored in a 2-byte unsigned ** integer, so a value of 0 is used in its place. */ pTmp = &data[hdr+5]; top = get2byte(pTmp); assert( top<=(int)pPage->pBt->usableSize ); /* by btreeComputeFreeSpace() */ if( gap>top ){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ return SQLITE_CORRUPT_PAGE(pPage); } } /* If there is enough space between gap and top for one more cell pointer, ** and if the freelist is not empty, then search the ** freelist looking for a slot big enough to satisfy the request. */ testcase( gap+2==top ); |
︙ | ︙ | |||
1875 1876 1877 1878 1879 1880 1881 | assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iSize>=4 ); /* Minimum cell size is 4 */ | | | 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 | assert( pPage->pBt!=0 ); assert( sqlite3PagerIswriteable(pPage->pDbPage) ); assert( CORRUPT_DB || iStart>=pPage->hdrOffset+6+pPage->childPtrSize ); assert( CORRUPT_DB || iEnd <= pPage->pBt->usableSize ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( iSize>=4 ); /* Minimum cell size is 4 */ assert( iStart<=pPage->pBt->usableSize-4 ); /* The list of freeblocks must be in ascending order. Find the ** spot on the list where iStart should be inserted. */ hdr = pPage->hdrOffset; iPtr = hdr + 1; if( data[iPtr+1]==0 && data[iPtr]==0 ){ |
︙ | ︙ | |||
1932 1933 1934 1935 1936 1937 1938 | } } if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); data[hdr+7] -= nFrag; } pTmp = &data[hdr+5]; x = get2byte(pTmp); | < < < < < > > > > > > | | < | 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 | } } if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PAGE(pPage); data[hdr+7] -= nFrag; } pTmp = &data[hdr+5]; x = get2byte(pTmp); if( iStart<=x ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ if( iStart<x ) return SQLITE_CORRUPT_PAGE(pPage); if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PAGE(pPage); put2byte(&data[hdr+1], iFreeBlk); put2byte(&data[hdr+5], iEnd); }else{ /* Insert the new freeblock into the freelist */ put2byte(&data[iPtr], iStart); } if( pPage->pBt->btsFlags & BTS_FAST_SECURE ){ /* Overwrite deleted information with zeros when the secure_delete ** option is enabled */ memset(&data[iStart], 0, iSize); } put2byte(&data[iStart], iFreeBlk); put2byte(&data[iStart+2], iSize); pPage->nFree += iOrigSize; return SQLITE_OK; } /* ** Decode the flags byte (the first byte of the header) for a page ** and initialize fields of the MemPage structure accordingly. |
︙ | ︙ | |||
1987 1988 1989 1990 1991 1992 1993 | pPage->xParseCell = btreeParseCellPtr; pPage->intKey = 1; pPage->maxLocal = pBt->maxLeaf; pPage->minLocal = pBt->minLeaf; }else if( flagByte==(PTF_ZERODATA | PTF_LEAF) ){ pPage->intKey = 0; pPage->intKeyLeaf = 0; | | | | 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 | pPage->xParseCell = btreeParseCellPtr; pPage->intKey = 1; pPage->maxLocal = pBt->maxLeaf; pPage->minLocal = pBt->minLeaf; }else if( flagByte==(PTF_ZERODATA | PTF_LEAF) ){ pPage->intKey = 0; pPage->intKeyLeaf = 0; pPage->xCellSize = cellSizePtr; pPage->xParseCell = btreeParseCellPtrIndex; pPage->maxLocal = pBt->maxLocal; pPage->minLocal = pBt->minLocal; }else{ pPage->intKey = 0; pPage->intKeyLeaf = 0; pPage->xCellSize = cellSizePtr; pPage->xParseCell = btreeParseCellPtrIndex; return SQLITE_CORRUPT_PAGE(pPage); } }else{ pPage->childPtrSize = 4; pPage->leaf = 0; if( flagByte==(PTF_ZERODATA) ){ |
︙ | ︙ | |||
3860 3861 3862 3863 3864 3865 3866 | assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3_mutex_held(pBt->mutex) ); assert( pDbPage->pBt==pBt ); if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; /* Move page iDbPage from its current location to page number iFreePage */ | | | 3794 3795 3796 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 | assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ); assert( sqlite3_mutex_held(pBt->mutex) ); assert( pDbPage->pBt==pBt ); if( iDbPage<3 ) return SQLITE_CORRUPT_BKPT; /* Move page iDbPage from its current location to page number iFreePage */ TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n", iDbPage, iFreePage, iPtrPage, eType)); rc = sqlite3PagerMovepage(pPager, pDbPage->pDbPage, iFreePage, isCommit); if( rc!=SQLITE_OK ){ return rc; } pDbPage->pgno = iFreePage; |
︙ | ︙ | |||
6146 6147 6148 6149 6150 6151 6152 | pCur->eState = CURSOR_VALID; if( pCur->skipNext>0 ) return SQLITE_OK; } } pPage = pCur->pPage; idx = ++pCur->ix; | | < | 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 | pCur->eState = CURSOR_VALID; if( pCur->skipNext>0 ) return SQLITE_OK; } } pPage = pCur->pPage; idx = ++pCur->ix; if( NEVER(!pPage->isInit) || sqlite3FaultSim(412) ){ return SQLITE_CORRUPT_BKPT; } if( idx>=pPage->nCell ){ if( !pPage->leaf ){ rc = moveToChild(pCur, get4byte(&pPage->aData[pPage->hdrOffset+8])); if( rc ) return rc; |
︙ | ︙ | |||
6410 6411 6412 6413 6414 6415 6416 | if( rc ){ goto end_allocate_page; } *pPgno = iTrunk; memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; | | | 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 | if( rc ){ goto end_allocate_page; } *pPgno = iTrunk; memcpy(&pPage1->aData[32], &pTrunk->aData[0], 4); *ppPage = pTrunk; pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList && (nearby==iTrunk || (iTrunk<nearby && eMode==BTALLOC_LE)) |
︙ | ︙ | |||
6476 6477 6478 6479 6480 6481 6482 | if( rc ){ goto end_allocate_page; } put4byte(&pPrevTrunk->aData[0], iNewTrunk); } } pTrunk = 0; | | | 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 | if( rc ){ goto end_allocate_page; } put4byte(&pPrevTrunk->aData[0], iNewTrunk); } } pTrunk = 0; TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); #endif }else if( k>0 ){ /* Extract a leaf from the trunk */ u32 closest; Pgno iPage; unsigned char *aData = pTrunk->aData; if( nearby>0 ){ |
︙ | ︙ | |||
6521 6522 6523 6524 6525 6526 6527 | } testcase( iPage==mxPage ); if( !searchList || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) ){ int noContent; *pPgno = iPage; | | | | 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 6465 6466 6467 6468 6469 | } testcase( iPage==mxPage ); if( !searchList || (iPage==nearby || (iPage<nearby && eMode==BTALLOC_LE)) ){ int noContent; *pPgno = iPage; TRACE(("ALLOCATE: %d was leaf %d of %d on trunk %d" ": %d more free pages\n", *pPgno, closest+1, k, pTrunk->pgno, n-1)); rc = sqlite3PagerWrite(pTrunk->pDbPage); if( rc ) goto end_allocate_page; if( closest<k-1 ){ memcpy(&aData[8+closest*4], &aData[4+k*4], 4); } put4byte(&aData[4], k-1); |
︙ | ︙ | |||
6578 6579 6580 6581 6582 6583 6584 | #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ /* If *pPgno refers to a pointer-map page, allocate two new pages ** at the end of the file instead of one. The first allocated page ** becomes a new pointer-map page, the second is used by the caller. */ MemPage *pPg = 0; | | | 6511 6512 6513 6514 6515 6516 6517 6518 6519 6520 6521 6522 6523 6524 6525 | #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum && PTRMAP_ISPAGE(pBt, pBt->nPage) ){ /* If *pPgno refers to a pointer-map page, allocate two new pages ** at the end of the file instead of one. The first allocated page ** becomes a new pointer-map page, the second is used by the caller. */ MemPage *pPg = 0; TRACE(("ALLOCATE: %d from end of file (pointer-map page)\n", pBt->nPage)); assert( pBt->nPage!=PENDING_BYTE_PAGE(pBt) ); rc = btreeGetUnusedPage(pBt, pBt->nPage, &pPg, bNoContent); if( rc==SQLITE_OK ){ rc = sqlite3PagerWrite(pPg->pDbPage); releasePage(pPg); } if( rc ) return rc; |
︙ | ︙ | |||
6601 6602 6603 6604 6605 6606 6607 | rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); *ppPage = 0; } | | | 6534 6535 6536 6537 6538 6539 6540 6541 6542 6543 6544 6545 6546 6547 6548 | rc = btreeGetUnusedPage(pBt, *pPgno, ppPage, bNoContent); if( rc ) return rc; rc = sqlite3PagerWrite((*ppPage)->pDbPage); if( rc!=SQLITE_OK ){ releasePage(*ppPage); *ppPage = 0; } TRACE(("ALLOCATE: %d from end of file\n", *pPgno)); } assert( CORRUPT_DB || *pPgno!=PENDING_BYTE_PAGE(pBt) ); end_allocate_page: releasePage(pTrunk); releasePage(pPrevTrunk); |
︙ | ︙ | |||
6729 6730 6731 6732 6733 6734 6735 | put4byte(&pTrunk->aData[4], nLeaf+1); put4byte(&pTrunk->aData[8+nLeaf*4], iPage); if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){ sqlite3PagerDontWrite(pPage->pDbPage); } rc = btreeSetHasContent(pBt, iPage); } | | | | 6662 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 6678 6679 6680 6681 6682 6683 6684 6685 6686 6687 6688 6689 6690 6691 6692 6693 6694 6695 6696 6697 | put4byte(&pTrunk->aData[4], nLeaf+1); put4byte(&pTrunk->aData[8+nLeaf*4], iPage); if( pPage && (pBt->btsFlags & BTS_SECURE_DELETE)==0 ){ sqlite3PagerDontWrite(pPage->pDbPage); } rc = btreeSetHasContent(pBt, iPage); } TRACE(("FREE-PAGE: %d leaf on trunk page %d\n",pPage->pgno,pTrunk->pgno)); goto freepage_out; } } /* If control flows to this point, then it was not possible to add the ** the page being freed as a leaf page of the first trunk in the free-list. ** Possibly because the free-list is empty, or possibly because the ** first trunk in the free-list is full. Either way, the page being freed ** will become the new first trunk page in the free-list. */ if( pPage==0 && SQLITE_OK!=(rc = btreeGetPage(pBt, iPage, &pPage, 0)) ){ goto freepage_out; } rc = sqlite3PagerWrite(pPage->pDbPage); if( rc!=SQLITE_OK ){ goto freepage_out; } put4byte(pPage->aData, iTrunk); put4byte(&pPage->aData[4], 0); put4byte(&pPage1->aData[32], iPage); TRACE(("FREE-PAGE: %d new trunk page replacing %d\n", pPage->pgno, iTrunk)); freepage_out: if( pPage ){ pPage->isInit = 0; } releasePage(pPage); releasePage(pTrunk); |
︙ | ︙ | |||
7109 7110 7111 7112 7113 7114 7115 | ** If the cell content will fit on the page, then put it there. If it ** will not fit, then make a copy of the cell content into pTemp if ** pTemp is not null. Regardless of pTemp, allocate a new entry ** in pPage->apOvfl[] and make it point to the cell content (either ** in pTemp or the original pCell) and also record its index. ** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. | < < < < < < < < | 7042 7043 7044 7045 7046 7047 7048 7049 7050 7051 7052 7053 7054 7055 | ** If the cell content will fit on the page, then put it there. If it ** will not fit, then make a copy of the cell content into pTemp if ** pTemp is not null. Regardless of pTemp, allocate a new entry ** in pPage->apOvfl[] and make it point to the cell content (either ** in pTemp or the original pCell) and also record its index. ** Allocating a new entry in pPage->aCell[] implies that ** pPage->nOverflow is incremented. */ static int insertCell( MemPage *pPage, /* Page into which we are copying */ int i, /* New cell becomes the i-th cell of the page */ u8 *pCell, /* Content of the new cell */ int sz, /* Bytes of content in pCell */ u8 *pTemp, /* Temp storage space for pCell, if needed */ |
︙ | ︙ | |||
7139 7140 7141 7142 7143 7144 7145 | assert( MX_CELL(pPage->pBt)<=10921 ); assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); assert( pPage->nFree>=0 ); | < > | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 7064 7065 7066 7067 7068 7069 7070 7071 7072 7073 7074 7075 7076 7077 7078 7079 7080 7081 7082 7083 7084 7085 | assert( MX_CELL(pPage->pBt)<=10921 ); assert( pPage->nCell<=MX_CELL(pPage->pBt) || CORRUPT_DB ); assert( pPage->nOverflow<=ArraySize(pPage->apOvfl) ); assert( ArraySize(pPage->apOvfl)==ArraySize(pPage->aiOvfl) ); assert( sqlite3_mutex_held(pPage->pBt->mutex) ); assert( sz==pPage->xCellSize(pPage, pCell) || CORRUPT_DB ); assert( pPage->nFree>=0 ); if( pPage->nOverflow || sz+2>pPage->nFree ){ if( pTemp ){ memcpy(pTemp, pCell, sz); pCell = pTemp; } if( iChild ){ put4byte(pCell, iChild); } j = pPage->nOverflow++; /* Comparison against ArraySize-1 since we hold back one extra slot ** as a contingency. In other words, never need more than 3 overflow ** slots but 4 are allocated, just to be safe. */ assert( j < ArraySize(pPage->apOvfl)-1 ); pPage->apOvfl[j] = pCell; pPage->aiOvfl[j] = (u16)i; |
︙ | ︙ | |||
7267 7268 7269 7270 7271 7272 7273 | if( rc ){ return rc; } /* The allocateSpace() routine guarantees the following properties ** if it returns successfully */ assert( idx >= 0 ); assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); assert( idx+sz <= (int)pPage->pBt->usableSize ); pPage->nFree -= (u16)(2 + sz); | > > > > > > > > > | > | 7103 7104 7105 7106 7107 7108 7109 7110 7111 7112 7113 7114 7115 7116 7117 7118 7119 7120 7121 7122 7123 7124 7125 7126 7127 | if( rc ){ return rc; } /* The allocateSpace() routine guarantees the following properties ** if it returns successfully */ assert( idx >= 0 ); assert( idx >= pPage->cellOffset+2*pPage->nCell+2 || CORRUPT_DB ); assert( idx+sz <= (int)pPage->pBt->usableSize ); pPage->nFree -= (u16)(2 + sz); if( iChild ){ /* In a corrupt database where an entry in the cell index section of ** a btree page has a value of 3 or less, the pCell value might point ** as many as 4 bytes in front of the start of the aData buffer for ** the source page. Make sure this does not cause problems by not ** reading the first 4 bytes */ memcpy(&data[idx+4], pCell+4, sz-4); put4byte(&data[idx], iChild); }else{ memcpy(&data[idx], pCell, sz); } pIns = pPage->aCellIdx + i*2; memmove(pIns+2, pIns, 2*(pPage->nCell - i)); put2byte(pIns, idx); pPage->nCell++; /* increment the cell count */ if( (++data[pPage->hdrOffset+4])==0 ) data[pPage->hdrOffset+3]++; assert( get2byte(&data[pPage->hdrOffset+3])==pPage->nCell || CORRUPT_DB ); |
︙ | ︙ | |||
7452 7453 7454 7455 7456 7457 7458 | u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); u8 *pData; int k; /* Current slot in pCArray->apEnd[] */ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */ assert( i<iEnd ); j = get2byte(&aData[hdr+5]); | | | 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 7309 7310 7311 7312 | u8 *pTmp = sqlite3PagerTempSpace(pPg->pBt->pPager); u8 *pData; int k; /* Current slot in pCArray->apEnd[] */ u8 *pSrcEnd; /* Current pCArray->apEnd[k] value */ assert( i<iEnd ); j = get2byte(&aData[hdr+5]); if( j>(u32)usableSize ){ j = 0; } memcpy(&pTmp[j], &aData[j], usableSize - j); for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){} pSrcEnd = pCArray->apEnd[k]; pData = pEnd; while( 1/*exit by break*/ ){ |
︙ | ︙ | |||
7596 7597 7598 7599 7600 7601 7602 | int nCell, /* Cells to delete */ CellArray *pCArray /* Array of cells */ ){ u8 * const aData = pPg->aData; u8 * const pEnd = &aData[pPg->pBt->usableSize]; u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; int nRet = 0; | | | | < < < | < < < < < < < < < < | < | | | > | > > > > > | | < | | > | | 7442 7443 7444 7445 7446 7447 7448 7449 7450 7451 7452 7453 7454 7455 7456 7457 7458 7459 7460 7461 7462 7463 7464 7465 7466 7467 7468 7469 7470 7471 7472 7473 7474 7475 7476 7477 7478 7479 7480 7481 7482 7483 7484 7485 7486 7487 7488 7489 7490 7491 | int nCell, /* Cells to delete */ CellArray *pCArray /* Array of cells */ ){ u8 * const aData = pPg->aData; u8 * const pEnd = &aData[pPg->pBt->usableSize]; u8 * const pStart = &aData[pPg->hdrOffset + 8 + pPg->childPtrSize]; int nRet = 0; int i; int iEnd = iFirst + nCell; u8 *pFree = 0; /* \__ Parameters for pending call to */ int szFree = 0; /* / freeSpace() */ for(i=iFirst; i<iEnd; i++){ u8 *pCell = pCArray->apCell[i]; if( SQLITE_WITHIN(pCell, pStart, pEnd) ){ int sz; /* No need to use cachedCellSize() here. The sizes of all cells that ** are to be freed have already been computing while deciding which ** cells need freeing */ sz = pCArray->szCell[i]; assert( sz>0 ); if( pFree!=(pCell + sz) ){ if( pFree ){ assert( pFree>aData && (pFree - aData)<65536 ); freeSpace(pPg, (u16)(pFree - aData), szFree); } pFree = pCell; szFree = sz; if( pFree+sz>pEnd ){ return 0; } }else{ /* The current cell is adjacent to and before the pFree cell. ** Combine the two regions into one to reduce the number of calls ** to freeSpace(). */ pFree = pCell; szFree += sz; } nRet++; } } if( pFree ){ assert( pFree>aData && (pFree - aData)<65536 ); freeSpace(pPg, (u16)(pFree - aData), szFree); } return nRet; } /* ** pCArray contains pointers to and sizes of all cells in the page being ** balanced. The current page, pPg, has pPg->nCell cells starting with |
︙ | ︙ | |||
7694 7695 7696 7697 7698 7699 7700 | int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); assert( nCell>=nTail ); nCell -= nTail; } pData = &aData[get2byteNotZero(&aData[hdr+5])]; if( pData<pBegin ) goto editpage_fail; | | | 7532 7533 7534 7535 7536 7537 7538 7539 7540 7541 7542 7543 7544 7545 7546 | int nTail = pageFreeArray(pPg, iNewEnd, iOldEnd - iNewEnd, pCArray); assert( nCell>=nTail ); nCell -= nTail; } pData = &aData[get2byteNotZero(&aData[hdr+5])]; if( pData<pBegin ) goto editpage_fail; if( pData>pPg->aDataEnd ) goto editpage_fail; /* Add cells to the start of the page */ if( iNew<iOld ){ int nAdd = MIN(nNew,iOld-iNew); assert( (iOld-iNew)<nNew || nCell==0 || CORRUPT_DB ); assert( nAdd>=0 ); pCellptr = pPg->aCellIdx; |
︙ | ︙ | |||
8431 8432 8433 8434 8435 8436 8437 | ** must be true: ** (1) We found one or more cells (cntNew[0])>0), or ** (2) pPage is a virtual root page. A virtual root page is when ** the real root page is page 1 and we are the only child of ** that page. */ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); | | | 8269 8270 8271 8272 8273 8274 8275 8276 8277 8278 8279 8280 8281 8282 8283 | ** must be true: ** (1) We found one or more cells (cntNew[0])>0), or ** (2) pPage is a virtual root page. A virtual root page is when ** the real root page is page 1 and we are the only child of ** that page. */ assert( cntNew[0]>0 || (pParent->pgno==1 && pParent->nCell==0) || CORRUPT_DB); TRACE(("BALANCE: old: %d(nc=%d) %d(nc=%d) %d(nc=%d)\n", apOld[0]->pgno, apOld[0]->nCell, nOld>=2 ? apOld[1]->pgno : 0, nOld>=2 ? apOld[1]->nCell : 0, nOld>=3 ? apOld[2]->pgno : 0, nOld>=3 ? apOld[2]->nCell : 0 )); /* ** Allocate k new pages. Reuse old pages where possible. |
︙ | ︙ | |||
8515 8516 8517 8518 8519 8520 8521 | sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA); sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB); apNew[i]->pgno = pgnoB; apNew[iB]->pgno = pgnoA; } } | | | | 8353 8354 8355 8356 8357 8358 8359 8360 8361 8362 8363 8364 8365 8366 8367 8368 | sqlite3PagerRekey(apNew[iB]->pDbPage, pgnoA, fgA); sqlite3PagerRekey(apNew[i]->pDbPage, pgnoB, fgB); apNew[i]->pgno = pgnoB; apNew[iB]->pgno = pgnoA; } } TRACE(("BALANCE: new: %d(%d nc=%d) %d(%d nc=%d) %d(%d nc=%d) " "%d(%d nc=%d) %d(%d nc=%d)\n", apNew[0]->pgno, szNew[0], cntNew[0], nNew>=2 ? apNew[1]->pgno : 0, nNew>=2 ? szNew[1] : 0, nNew>=2 ? cntNew[1] - cntNew[0] - !leafData : 0, nNew>=3 ? apNew[2]->pgno : 0, nNew>=3 ? szNew[2] : 0, nNew>=3 ? cntNew[2] - cntNew[1] - !leafData : 0, nNew>=4 ? apNew[3]->pgno : 0, nNew>=4 ? szNew[3] : 0, nNew>=4 ? cntNew[3] - cntNew[2] - !leafData : 0, |
︙ | ︙ | |||
8761 8762 8763 8764 8765 8766 8767 | for(i=0; i<nNew; i++){ u32 key = get4byte(&apNew[i]->aData[8]); ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); } } assert( pParent->isInit ); | | | 8599 8600 8601 8602 8603 8604 8605 8606 8607 8608 8609 8610 8611 8612 8613 | for(i=0; i<nNew; i++){ u32 key = get4byte(&apNew[i]->aData[8]); ptrmapPut(pBt, key, PTRMAP_BTREE, apNew[i]->pgno, &rc); } } assert( pParent->isInit ); TRACE(("BALANCE: finished: old=%d new=%d cells=%d\n", nOld, nNew, b.nCell)); /* Free any old pages that were not reused as new pages. */ for(i=nNew; i<nOld; i++){ freePage(apOld[i], &rc); } |
︙ | ︙ | |||
8846 8847 8848 8849 8850 8851 8852 | releasePage(pChild); return rc; } assert( sqlite3PagerIswriteable(pChild->pDbPage) ); assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); | | | 8684 8685 8686 8687 8688 8689 8690 8691 8692 8693 8694 8695 8696 8697 8698 | releasePage(pChild); return rc; } assert( sqlite3PagerIswriteable(pChild->pDbPage) ); assert( sqlite3PagerIswriteable(pRoot->pDbPage) ); assert( pChild->nCell==pRoot->nCell || CORRUPT_DB ); TRACE(("BALANCE: copy root %d into %d\n", pRoot->pgno, pChild->pgno)); /* Copy the overflow cells from pRoot to pChild */ memcpy(pChild->aiOvfl, pRoot->aiOvfl, pRoot->nOverflow*sizeof(pRoot->aiOvfl[0])); memcpy(pChild->apOvfl, pRoot->apOvfl, pRoot->nOverflow*sizeof(pRoot->apOvfl[0])); pChild->nOverflow = pRoot->nOverflow; |
︙ | ︙ | |||
9329 9330 9331 9332 9333 9334 9335 | x2.nData = pX->nKey; x2.nZero = 0; return btreeOverwriteCell(pCur, &x2); } } } assert( pCur->eState==CURSOR_VALID | | | | 9167 9168 9169 9170 9171 9172 9173 9174 9175 9176 9177 9178 9179 9180 9181 9182 9183 9184 9185 9186 9187 9188 9189 9190 9191 9192 9193 9194 9195 9196 | x2.nData = pX->nKey; x2.nZero = 0; return btreeOverwriteCell(pCur, &x2); } } } assert( pCur->eState==CURSOR_VALID || (pCur->eState==CURSOR_INVALID && loc) ); pPage = pCur->pPage; assert( pPage->intKey || pX->nKey>=0 || (flags & BTREE_PREFORMAT) ); assert( pPage->leaf || !pPage->intKey ); if( pPage->nFree<0 ){ if( NEVER(pCur->eState>CURSOR_INVALID) ){ /* ^^^^^--- due to the moveToRoot() call above */ rc = SQLITE_CORRUPT_BKPT; }else{ rc = btreeComputeFreeSpace(pPage); } if( rc ) return rc; } TRACE(("INSERT: table=%d nkey=%lld ndata=%d page=%d %s\n", pCur->pgnoRoot, pX->nKey, pX->nData, pPage->pgno, loc==0 ? "overwrite" : "new entry")); assert( pPage->isInit || CORRUPT_DB ); newCell = p->pBt->pTmpSpace; assert( newCell!=0 ); assert( BTREE_PREFORMAT==OPFLAG_PREFORMAT ); if( flags & BTREE_PREFORMAT ){ |
︙ | ︙ | |||
9371 9372 9373 9374 9375 9376 9377 | }else{ rc = fillInCell(pPage, newCell, pX, &szNew); if( rc ) goto end_insert; } assert( szNew==pPage->xCellSize(pPage, newCell) ); assert( szNew <= MX_CELL_SIZE(p->pBt) ); idx = pCur->ix; | < | 9209 9210 9211 9212 9213 9214 9215 9216 9217 9218 9219 9220 9221 9222 | }else{ rc = fillInCell(pPage, newCell, pX, &szNew); if( rc ) goto end_insert; } assert( szNew==pPage->xCellSize(pPage, newCell) ); assert( szNew <= MX_CELL_SIZE(p->pBt) ); idx = pCur->ix; if( loc==0 ){ CellInfo info; assert( idx>=0 ); if( idx>=pPage->nCell ){ return SQLITE_CORRUPT_BKPT; } rc = sqlite3PagerWrite(pPage->pDbPage); |
︙ | ︙ | |||
9420 9421 9422 9423 9424 9425 9426 | }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->ix; pCur->curFlags &= ~BTCF_ValidNKey; }else{ assert( pPage->leaf ); } | | | 9257 9258 9259 9260 9261 9262 9263 9264 9265 9266 9267 9268 9269 9270 9271 | }else if( loc<0 && pPage->nCell>0 ){ assert( pPage->leaf ); idx = ++pCur->ix; pCur->curFlags &= ~BTCF_ValidNKey; }else{ assert( pPage->leaf ); } rc = insertCell(pPage, idx, newCell, szNew, 0, 0); assert( pPage->nOverflow==0 || rc==SQLITE_OK ); assert( rc!=SQLITE_OK || pPage->nCell>0 || pPage->nOverflow>0 ); /* If no error has occurred and pPage has an overflow cell, call balance() ** to redistribute the cells within the tree. Since balance() may move ** the cursor, zero the BtCursor.info.nSize and BTCF_ValidNKey ** variables. |
︙ | ︙ | |||
9444 9445 9446 9447 9448 9449 9450 9451 9452 9453 9454 9455 9456 9457 | ** happen while processing an "INSERT INTO ... SELECT" statement), it ** is advantageous to leave the cursor pointing to the last entry in ** the b-tree if possible. If the cursor is left pointing to the last ** entry in the table, and the next row inserted has an integer key ** larger than the largest existing key, it is possible to insert the ** row without seeking the cursor. This can be a big performance boost. */ if( pPage->nOverflow ){ assert( rc==SQLITE_OK ); pCur->curFlags &= ~(BTCF_ValidNKey); rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() ** fails. Internal data structure corruption will result otherwise. | > | 9281 9282 9283 9284 9285 9286 9287 9288 9289 9290 9291 9292 9293 9294 9295 | ** happen while processing an "INSERT INTO ... SELECT" statement), it ** is advantageous to leave the cursor pointing to the last entry in ** the b-tree if possible. If the cursor is left pointing to the last ** entry in the table, and the next row inserted has an integer key ** larger than the largest existing key, it is possible to insert the ** row without seeking the cursor. This can be a big performance boost. */ pCur->info.nSize = 0; if( pPage->nOverflow ){ assert( rc==SQLITE_OK ); pCur->curFlags &= ~(BTCF_ValidNKey); rc = balance(pCur); /* Must make sure nOverflow is reset to zero even if the balance() ** fails. Internal data structure corruption will result otherwise. |
︙ | ︙ | |||
9644 9645 9646 9647 9648 9649 9650 | if( pPage->nCell<=iCellIdx ){ return SQLITE_CORRUPT_BKPT; } pCell = findCell(pPage, iCellIdx); if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ return SQLITE_CORRUPT_BKPT; } | < < < | 9482 9483 9484 9485 9486 9487 9488 9489 9490 9491 9492 9493 9494 9495 | if( pPage->nCell<=iCellIdx ){ return SQLITE_CORRUPT_BKPT; } pCell = findCell(pPage, iCellIdx); if( pPage->nFree<0 && btreeComputeFreeSpace(pPage) ){ return SQLITE_CORRUPT_BKPT; } /* If the BTREE_SAVEPOSITION bit is on, then the cursor position must ** be preserved following this delete operation. If the current delete ** will cause a b-tree rebalance, then this is done by saving the cursor ** key and leaving the cursor in CURSOR_REQUIRESEEK state before ** returning. ** |
︙ | ︙ | |||
10395 10396 10397 10398 10399 10400 10401 | pCheck->mxErr--; pCheck->nErr++; va_start(ap, zFormat); if( pCheck->errMsg.nChar ){ sqlite3_str_append(&pCheck->errMsg, "\n", 1); } if( pCheck->zPfx ){ | | < | 10230 10231 10232 10233 10234 10235 10236 10237 10238 10239 10240 10241 10242 10243 10244 | pCheck->mxErr--; pCheck->nErr++; va_start(ap, zFormat); if( pCheck->errMsg.nChar ){ sqlite3_str_append(&pCheck->errMsg, "\n", 1); } if( pCheck->zPfx ){ sqlite3_str_appendf(&pCheck->errMsg, pCheck->zPfx, pCheck->v1, pCheck->v2); } sqlite3_str_vappendf(&pCheck->errMsg, zFormat, ap); va_end(ap); if( pCheck->errMsg.accError==SQLITE_NOMEM ){ checkOom(pCheck); } } |
︙ | ︙ | |||
10436 10437 10438 10439 10440 10441 10442 | ** Return 1 if there are 2 or more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ if( iPage>pCheck->nPage || iPage==0 ){ | | | | 10270 10271 10272 10273 10274 10275 10276 10277 10278 10279 10280 10281 10282 10283 10284 10285 10286 10287 10288 | ** Return 1 if there are 2 or more references to the page and 0 if ** if this is the first reference to the page. ** ** Also check that the page number is in bounds. */ static int checkRef(IntegrityCk *pCheck, Pgno iPage){ if( iPage>pCheck->nPage || iPage==0 ){ checkAppendMsg(pCheck, "invalid page number %d", iPage); return 1; } if( getPageReferenced(pCheck, iPage) ){ checkAppendMsg(pCheck, "2nd reference to page %d", iPage); return 1; } setPageReferenced(pCheck, iPage); return 0; } #ifndef SQLITE_OMIT_AUTOVACUUM |
︙ | ︙ | |||
10466 10467 10468 10469 10470 10471 10472 | int rc; u8 ePtrmapType; Pgno iPtrmapParent; rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) checkOom(pCheck); | | | | 10300 10301 10302 10303 10304 10305 10306 10307 10308 10309 10310 10311 10312 10313 10314 10315 10316 10317 10318 10319 10320 | int rc; u8 ePtrmapType; Pgno iPtrmapParent; rc = ptrmapGet(pCheck->pBt, iChild, &ePtrmapType, &iPtrmapParent); if( rc!=SQLITE_OK ){ if( rc==SQLITE_NOMEM || rc==SQLITE_IOERR_NOMEM ) checkOom(pCheck); checkAppendMsg(pCheck, "Failed to read ptrmap key=%d", iChild); return; } if( ePtrmapType!=eType || iPtrmapParent!=iParent ){ checkAppendMsg(pCheck, "Bad ptr map entry key=%d expected=(%d,%d) got=(%d,%d)", iChild, eType, iParent, ePtrmapType, iPtrmapParent); } } #endif /* ** Check the integrity of the freelist or of an overflow page list. |
︙ | ︙ | |||
10497 10498 10499 10500 10501 10502 10503 | int nErrAtStart = pCheck->nErr; while( iPage!=0 && pCheck->mxErr ){ DbPage *pOvflPage; unsigned char *pOvflData; if( checkRef(pCheck, iPage) ) break; N--; if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ | | | | 10331 10332 10333 10334 10335 10336 10337 10338 10339 10340 10341 10342 10343 10344 10345 10346 10347 10348 10349 10350 10351 10352 10353 10354 10355 10356 10357 10358 | int nErrAtStart = pCheck->nErr; while( iPage!=0 && pCheck->mxErr ){ DbPage *pOvflPage; unsigned char *pOvflData; if( checkRef(pCheck, iPage) ) break; N--; if( sqlite3PagerGet(pCheck->pPager, (Pgno)iPage, &pOvflPage, 0) ){ checkAppendMsg(pCheck, "failed to get page %d", iPage); break; } pOvflData = (unsigned char *)sqlite3PagerGetData(pOvflPage); if( isFreeList ){ u32 n = (u32)get4byte(&pOvflData[4]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pCheck->pBt->autoVacuum ){ checkPtrmap(pCheck, iPage, PTRMAP_FREEPAGE, 0); } #endif if( n>pCheck->pBt->usableSize/4-2 ){ checkAppendMsg(pCheck, "freelist leaf count too big on page %d", iPage); N--; }else{ for(i=0; i<(int)n; i++){ Pgno iFreePage = get4byte(&pOvflData[8+i*4]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pCheck->pBt->autoVacuum ){ checkPtrmap(pCheck, iFreePage, PTRMAP_FREEPAGE, 0); |
︙ | ︙ | |||
10542 10543 10544 10545 10546 10547 10548 | } #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); } if( N && nErrAtStart==pCheck->nErr ){ checkAppendMsg(pCheck, | | | 10376 10377 10378 10379 10380 10381 10382 10383 10384 10385 10386 10387 10388 10389 10390 | } #endif iPage = get4byte(pOvflData); sqlite3PagerUnref(pOvflPage); } if( N && nErrAtStart==pCheck->nErr ){ checkAppendMsg(pCheck, "%s is %d but should be %d", isFreeList ? "size" : "overflow list length", expected-N, expected); } } #endif /* SQLITE_OMIT_INTEGRITY_CHECK */ /* |
︙ | ︙ | |||
10657 10658 10659 10660 10661 10662 10663 | */ checkProgress(pCheck); if( pCheck->mxErr==0 ) goto end_of_check; pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; | | | | 10491 10492 10493 10494 10495 10496 10497 10498 10499 10500 10501 10502 10503 10504 10505 10506 | */ checkProgress(pCheck); if( pCheck->mxErr==0 ) goto end_of_check; pBt = pCheck->pBt; usableSize = pBt->usableSize; if( iPage==0 ) return 0; if( checkRef(pCheck, iPage) ) return 0; pCheck->zPfx = "Page %u: "; pCheck->v1 = iPage; if( (rc = btreeGetPage(pBt, iPage, &pPage, 0))!=0 ){ checkAppendMsg(pCheck, "unable to get the page. error code=%d", rc); goto end_of_check; } /* Clear MemPage.isInit to make sure the corruption detection code in |
︙ | ︙ | |||
10684 10685 10686 10687 10688 10689 10690 | checkAppendMsg(pCheck, "free space corruption", rc); goto end_of_check; } data = pPage->aData; hdr = pPage->hdrOffset; /* Set up for cell analysis */ | | | | 10518 10519 10520 10521 10522 10523 10524 10525 10526 10527 10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 10539 10540 10541 10542 10543 10544 10545 10546 10547 10548 10549 10550 10551 10552 | checkAppendMsg(pCheck, "free space corruption", rc); goto end_of_check; } data = pPage->aData; hdr = pPage->hdrOffset; /* Set up for cell analysis */ pCheck->zPfx = "On tree page %u cell %d: "; contentOffset = get2byteNotZero(&data[hdr+5]); assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */ /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the ** number of cells on the page. */ nCell = get2byte(&data[hdr+3]); assert( pPage->nCell==nCell ); /* EVIDENCE-OF: R-23882-45353 The cell pointer array of a b-tree page ** immediately follows the b-tree page header. */ cellStart = hdr + 12 - 4*pPage->leaf; assert( pPage->aCellIdx==&data[cellStart] ); pCellIdx = &data[cellStart + 2*(nCell-1)]; if( !pPage->leaf ){ /* Analyze the right-child page of internal pages */ pgno = get4byte(&data[hdr+8]); #ifndef SQLITE_OMIT_AUTOVACUUM if( pBt->autoVacuum ){ pCheck->zPfx = "On page %u at right child: "; checkPtrmap(pCheck, pgno, PTRMAP_BTREE, iPage); } #endif depth = checkTreePage(pCheck, pgno, &maxKey, maxKey); keyCanBeEqual = 0; }else{ /* For leaf pages, the coverage check will occur in the same loop |
︙ | ︙ | |||
10728 10729 10730 10731 10732 10733 10734 | /* Check cell size */ pCheck->v2 = i; assert( pCellIdx==&data[cellStart + i*2] ); pc = get2byteAligned(pCellIdx); pCellIdx -= 2; if( pc<contentOffset || pc>usableSize-4 ){ | | | 10562 10563 10564 10565 10566 10567 10568 10569 10570 10571 10572 10573 10574 10575 10576 | /* Check cell size */ pCheck->v2 = i; assert( pCellIdx==&data[cellStart + i*2] ); pc = get2byteAligned(pCellIdx); pCellIdx -= 2; if( pc<contentOffset || pc>usableSize-4 ){ checkAppendMsg(pCheck, "Offset %d out of range %d..%d", pc, contentOffset, usableSize-4); doCoverageCheck = 0; continue; } pCell = &data[pc]; pPage->xParseCell(pPage, pCell, &info); if( pc+info.nSize>usableSize ){ |
︙ | ︙ | |||
10860 10861 10862 10863 10864 10865 10866 | /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments ** is stored in the fifth field of the b-tree page header. ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the ** number of fragmented free bytes within the cell content area. */ if( heap[0]==0 && nFrag!=data[hdr+7] ){ checkAppendMsg(pCheck, | | | 10694 10695 10696 10697 10698 10699 10700 10701 10702 10703 10704 10705 10706 10707 10708 | /* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments ** is stored in the fifth field of the b-tree page header. ** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the ** number of fragmented free bytes within the cell content area. */ if( heap[0]==0 && nFrag!=data[hdr+7] ){ checkAppendMsg(pCheck, "Fragmentation of %d bytes reported as %d on page %u", nFrag, data[hdr+7], iPage); } } end_of_check: if( !doCoverageCheck ) pPage->isInit = savedIsInit; releasePage(pPage); |
︙ | ︙ | |||
10957 10958 10959 10960 10961 10962 10963 | i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); /* Check the integrity of the freelist */ if( bCkFreelist ){ | | | | 10791 10792 10793 10794 10795 10796 10797 10798 10799 10800 10801 10802 10803 10804 10805 10806 10807 10808 10809 10810 10811 10812 10813 10814 10815 10816 10817 10818 10819 10820 10821 10822 | i = PENDING_BYTE_PAGE(pBt); if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i); /* Check the integrity of the freelist */ if( bCkFreelist ){ sCheck.zPfx = "Main freelist: "; checkList(&sCheck, 1, get4byte(&pBt->pPage1->aData[32]), get4byte(&pBt->pPage1->aData[36])); sCheck.zPfx = 0; } /* Check all the tables. */ #ifndef SQLITE_OMIT_AUTOVACUUM if( !bPartial ){ if( pBt->autoVacuum ){ Pgno mx = 0; Pgno mxInHdr; for(i=0; (int)i<nRoot; i++) if( mx<aRoot[i] ) mx = aRoot[i]; mxInHdr = get4byte(&pBt->pPage1->aData[52]); if( mx!=mxInHdr ){ checkAppendMsg(&sCheck, "max rootpage (%d) disagrees with header (%d)", mx, mxInHdr ); } }else if( get4byte(&pBt->pPage1->aData[64])!=0 ){ checkAppendMsg(&sCheck, "incremental_vacuum enabled with a max rootpage of zero" ); |
︙ | ︙ | |||
11005 11006 11007 11008 11009 11010 11011 | /* Make sure every page in the file is referenced */ if( !bPartial ){ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( getPageReferenced(&sCheck, i)==0 ){ | | | | | 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 | /* Make sure every page in the file is referenced */ if( !bPartial ){ for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){ #ifdef SQLITE_OMIT_AUTOVACUUM if( getPageReferenced(&sCheck, i)==0 ){ checkAppendMsg(&sCheck, "Page %d is never used", i); } #else /* If the database supports auto-vacuum, make sure no tables contain ** references to pointer-map pages. */ if( getPageReferenced(&sCheck, i)==0 && (PTRMAP_PAGENO(pBt, i)!=i || !pBt->autoVacuum) ){ checkAppendMsg(&sCheck, "Page %d is never used", i); } if( getPageReferenced(&sCheck, i)!=0 && (PTRMAP_PAGENO(pBt, i)==i && pBt->autoVacuum) ){ checkAppendMsg(&sCheck, "Pointer map page %d is referenced", i); } #endif } } /* Clean up and report errors. */ |
︙ | ︙ |
Changes to src/btreeInt.h.
︙ | ︙ | |||
168 169 170 171 172 173 174 | ** contiguous or in order, but cell pointers are contiguous and in order. ** ** Cell content makes use of variable length integers. A variable ** length integer is 1 to 9 bytes where the lower 7 bits of each ** byte are used. The integer consists of all bytes that have bit 8 set and ** the first byte with bit 8 clear. The most significant byte of the integer ** appears first. A variable-length integer may not be more than 9 bytes long. | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | ** contiguous or in order, but cell pointers are contiguous and in order. ** ** Cell content makes use of variable length integers. A variable ** length integer is 1 to 9 bytes where the lower 7 bits of each ** byte are used. The integer consists of all bytes that have bit 8 set and ** the first byte with bit 8 clear. The most significant byte of the integer ** appears first. A variable-length integer may not be more than 9 bytes long. ** As a special case, all 8 bytes of the 9th byte are used as data. This ** allows a 64-bit integer to be encoded in 9 bytes. ** ** 0x00 becomes 0x00000000 ** 0x7f becomes 0x0000007f ** 0x81 0x00 becomes 0x00000080 ** 0x82 0x00 becomes 0x00000100 ** 0x80 0x7f becomes 0x0000007f |
︙ | ︙ | |||
697 698 699 700 701 702 703 | u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */ u32 nStep; /* Number of steps into the integrity_check process */ const char *zPfx; /* Error message prefix */ | | < | | 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | u8 *aPgRef; /* 1 bit per page in the db (see above) */ Pgno nPage; /* Number of pages in the database */ int mxErr; /* Stop accumulating errors when this reaches zero */ int nErr; /* Number of messages written to zErrMsg so far */ int rc; /* SQLITE_OK, SQLITE_NOMEM, or SQLITE_INTERRUPT */ u32 nStep; /* Number of steps into the integrity_check process */ const char *zPfx; /* Error message prefix */ Pgno v1; /* Value for first %u substitution in zPfx */ int v2; /* Value for second %d substitution in zPfx */ StrAccum errMsg; /* Accumulate the error message text here */ u32 *heap; /* Min-heap used for analyzing cell coverage */ sqlite3 *db; /* Database connection running the check */ }; /* ** Routines to read or write a two- and four-byte big-endian integer values. |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
1447 1448 1449 1450 1451 1452 1453 | void sqlite3AddReturning(Parse *pParse, ExprList *pList){ Returning *pRet; Hash *pHash; sqlite3 *db = pParse->db; if( pParse->pNewTrigger ){ sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger"); }else{ | | | 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 | void sqlite3AddReturning(Parse *pParse, ExprList *pList){ Returning *pRet; Hash *pHash; sqlite3 *db = pParse->db; if( pParse->pNewTrigger ){ sqlite3ErrorMsg(pParse, "cannot use RETURNING in a trigger"); }else{ assert( pParse->bReturning==0 ); } pParse->bReturning = 1; pRet = sqlite3DbMallocZero(db, sizeof(*pRet)); if( pRet==0 ){ sqlite3ExprListDelete(db, pList); return; } |
︙ | ︙ | |||
1473 1474 1475 1476 1477 1478 1479 | pRet->retTrig.pSchema = db->aDb[1].pSchema; pRet->retTrig.pTabSchema = db->aDb[1].pSchema; pRet->retTrig.step_list = &pRet->retTStep; pRet->retTStep.op = TK_RETURNING; pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); | | < | 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 | pRet->retTrig.pSchema = db->aDb[1].pSchema; pRet->retTrig.pTabSchema = db->aDb[1].pSchema; pRet->retTrig.step_list = &pRet->retTStep; pRet->retTStep.op = TK_RETURNING; pRet->retTStep.pTrig = &pRet->retTrig; pRet->retTStep.pExprList = pList; pHash = &(db->aDb[1].pSchema->trigHash); assert( sqlite3HashFind(pHash, RETURNING_TRIGGER_NAME)==0 || pParse->nErr ); if( sqlite3HashInsert(pHash, RETURNING_TRIGGER_NAME, &pRet->retTrig) ==&pRet->retTrig ){ sqlite3OomFault(db); } } /* |
︙ | ︙ | |||
2009 2010 2011 2012 2013 2014 2015 | if( ALWAYS(pExpr) && pExpr->op==TK_ID ){ /* The value of a generated column needs to be a real expression, not ** just a reference to another column, in order for covering index ** optimizations to work correctly. So if the value is not an expression, ** turn it into one by adding a unary "+" operator. */ pExpr = sqlite3PExpr(pParse, TK_UPLUS, pExpr, 0); } | < | 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 | if( ALWAYS(pExpr) && pExpr->op==TK_ID ){ /* The value of a generated column needs to be a real expression, not ** just a reference to another column, in order for covering index ** optimizations to work correctly. So if the value is not an expression, ** turn it into one by adding a unary "+" operator. */ pExpr = sqlite3PExpr(pParse, TK_UPLUS, pExpr, 0); } sqlite3ColumnSetExpr(pParse, pTab, pCol, pExpr); pExpr = 0; goto generated_done; generated_error: sqlite3ErrorMsg(pParse, "error in generated column \"%s\"", pCol->zCnName); |
︙ | ︙ |
Changes to src/date.c.
︙ | ︙ | |||
745 746 747 748 749 750 751 | } #ifndef SQLITE_OMIT_LOCALTIME else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ if( p->tzSet==0 ){ i64 iOrigJD; /* Original localtime */ i64 iGuess; /* Guess at the corresponding utc time */ int cnt = 0; /* Safety to prevent infinite loop */ | | | 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 | } #ifndef SQLITE_OMIT_LOCALTIME else if( sqlite3_stricmp(z, "utc")==0 && sqlite3NotPureFunc(pCtx) ){ if( p->tzSet==0 ){ i64 iOrigJD; /* Original localtime */ i64 iGuess; /* Guess at the corresponding utc time */ int cnt = 0; /* Safety to prevent infinite loop */ int iErr; /* Guess is off by this much */ computeJD(p); iGuess = iOrigJD = p->iJD; iErr = 0; do{ DateTime new; memset(&new, 0, sizeof(new)); |
︙ | ︙ |
Changes to src/dbpage.c.
︙ | ︙ | |||
74 75 76 77 78 79 80 | int rc = SQLITE_OK; (void)pAux; (void)argc; (void)argv; (void)pzErr; sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); | < | 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | int rc = SQLITE_OK; (void)pAux; (void)argc; (void)argv; (void)pzErr; sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY); rc = sqlite3_declare_vtab(db, "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)"); if( rc==SQLITE_OK ){ pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable)); if( pTab==0 ) rc = SQLITE_NOMEM_BKPT; } |
︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn<=0 && pIdxInfo->aOrderBy[0].desc==0 ){ pIdxInfo->orderByConsumed = 1; } return SQLITE_OK; } /* ** Open a new dbpagevfs cursor. */ static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ | > | 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | if( pIdxInfo->nOrderBy>=1 && pIdxInfo->aOrderBy[0].iColumn<=0 && pIdxInfo->aOrderBy[0].desc==0 ){ pIdxInfo->orderByConsumed = 1; } sqlite3VtabUsesAllSchemas(pIdxInfo); return SQLITE_OK; } /* ** Open a new dbpagevfs cursor. */ static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
110 111 112 113 114 115 116 | /* ** Check to make sure the given table is writable. ** ** If pTab is not writable -> generate an error message and return 1. ** If pTab is writable but other errors have occurred -> return 1. ** If pTab is writable and no prior errors -> return 0; */ | | | < < | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | /* ** Check to make sure the given table is writable. ** ** If pTab is not writable -> generate an error message and return 1. ** If pTab is writable but other errors have occurred -> return 1. ** If pTab is writable and no prior errors -> return 0; */ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){ if( tabIsReadOnly(pParse, pTab) ){ sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName); return 1; } #ifndef SQLITE_OMIT_VIEW if( !viewOk && IsView(pTab) ){ sqlite3ErrorMsg(pParse,"cannot modify %s because it is a view",pTab->zName); return 1; } #endif return 0; } |
︙ | ︙ | |||
372 373 374 375 376 377 378 | /* If pTab is really a view, make sure it has been initialized. */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto delete_from_cleanup; } | | | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 | /* If pTab is really a view, make sure it has been initialized. */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto delete_from_cleanup; } if( sqlite3IsReadOnly(pParse, pTab, (pTrigger?1:0)) ){ goto delete_from_cleanup; } iDb = sqlite3SchemaToIndex(db, pTab->pSchema); assert( iDb<db->nDb ); rcauth = sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, db->aDb[iDb].zDbSName); assert( rcauth==SQLITE_OK || rcauth==SQLITE_DENY || rcauth==SQLITE_IGNORE ); |
︙ | ︙ | |||
481 482 483 484 485 486 487 | sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; | | | 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 | sqlite3VdbeAddOp2(v, OP_Clear, pIdx->tnum, iDb); } } }else #endif /* SQLITE_OMIT_TRUNCATE_OPTIMIZATION */ { u16 wcf = WHERE_ONEPASS_DESIRED|WHERE_DUPLICATES_OK; if( sNC.ncFlags & NC_VarSelect ) bComplex = 1; wcf |= (bComplex ? 0 : WHERE_ONEPASS_MULTIROW); if( HasRowid(pTab) ){ /* For a rowid table, initialize the RowSet to an empty set */ pPk = 0; nPk = 1; iRowSet = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Null, 0, iRowSet); |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
274 275 276 277 278 279 280 | } if( p->flags & EP_Collate ){ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ Expr *pNext = p->pRight; /* The Expr.x union is never used at the same time as Expr.pRight */ | > | | | | 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | } if( p->flags & EP_Collate ){ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){ p = p->pLeft; }else{ Expr *pNext = p->pRight; /* The Expr.x union is never used at the same time as Expr.pRight */ assert( ExprUseXList(p) ); assert( p->x.pList==0 || p->pRight==0 ); if( p->x.pList!=0 && !db->mallocFailed ){ int i; for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){ pNext = p->x.pList->a[i].pExpr; break; } } } p = pNext; |
︙ | ︙ | |||
1109 1110 1111 1112 1113 1114 1115 | return pRet; } /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. ** | | | | | < < | | | | | | | < | 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 | return pRet; } /* ** Join two expressions using an AND operator. If either expression is ** NULL, then just return the other expression. ** ** If one side or the other of the AND is known to be false, then instead ** of returning an AND expression, just return a constant expression with ** a value of false. */ Expr *sqlite3ExprAnd(Parse *pParse, Expr *pLeft, Expr *pRight){ sqlite3 *db = pParse->db; if( pLeft==0 ){ return pRight; }else if( pRight==0 ){ return pLeft; }else if( (ExprAlwaysFalse(pLeft) || ExprAlwaysFalse(pRight)) && !IN_RENAME_OBJECT ){ sqlite3ExprDeferredDelete(pParse, pLeft); sqlite3ExprDeferredDelete(pParse, pRight); return sqlite3Expr(db, TK_INTEGER, "0"); }else{ return sqlite3PExpr(pParse, TK_AND, pLeft, pRight); } } /* ** Construct a new expression node for a function with multiple ** arguments. */ |
︙ | ︙ | |||
2648 2649 2650 2651 2652 2653 2654 | return 0; } /* ** pX is the RHS of an IN operator. If pX is a SELECT statement ** that can be simplified to a direct table access, then return ** a pointer to the SELECT statement. If pX is not a SELECT statement, | | | 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 | return 0; } /* ** pX is the RHS of an IN operator. If pX is a SELECT statement ** that can be simplified to a direct table access, then return ** a pointer to the SELECT statement. If pX is not a SELECT statement, ** or if the SELECT statement needs to be manifested into a transient ** table, then return NULL. */ #ifndef SQLITE_OMIT_SUBQUERY static Select *isCandidateForInOpt(const Expr *pX){ Select *p; SrcList *pSrc; ExprList *pEList; |
︙ | ︙ | |||
2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 | colUsed = 0; /* Columns of index used so far */ for(i=0; i<nExpr; i++){ Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); Expr *pRhs = pEList->a[i].pExpr; CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; for(j=0; j<nExpr; j++){ if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue; assert( pIdx->azColl[j] ); if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ continue; } break; | > | 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 | colUsed = 0; /* Columns of index used so far */ for(i=0; i<nExpr; i++){ Expr *pLhs = sqlite3VectorFieldSubexpr(pX->pLeft, i); Expr *pRhs = pEList->a[i].pExpr; CollSeq *pReq = sqlite3BinaryCompareCollSeq(pParse, pLhs, pRhs); int j; assert( pReq!=0 || pRhs->iColumn==XN_ROWID || pParse->nErr ); for(j=0; j<nExpr; j++){ if( pIdx->aiColumn[j]!=pRhs->iColumn ) continue; assert( pIdx->azColl[j] ); if( pReq!=0 && sqlite3StrICmp(pReq->zName, pIdx->azColl[j])!=0 ){ continue; } break; |
︙ | ︙ | |||
3836 3837 3838 3839 3840 3841 3842 | Parse *pParse, /* Parsing context */ Table *pTab, /* Table containing the generated column */ Column *pCol, /* The generated column */ int regOut /* Put the result in this register */ ){ int iAddr; Vdbe *v = pParse->pVdbe; | < | < < | 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 | Parse *pParse, /* Parsing context */ Table *pTab, /* Table containing the generated column */ Column *pCol, /* The generated column */ int regOut /* Put the result in this register */ ){ int iAddr; Vdbe *v = pParse->pVdbe; assert( v!=0 ); assert( pParse->iSelfTab!=0 ); if( pParse->iSelfTab>0 ){ iAddr = sqlite3VdbeAddOp3(v, OP_IfNullRow, pParse->iSelfTab-1, 0, regOut); }else{ iAddr = 0; } sqlite3ExprCodeCopy(pParse, sqlite3ColumnExpr(pTab,pCol), regOut); if( pCol->affinity>=SQLITE_AFF_TEXT ){ sqlite3VdbeAddOp4(v, OP_Affinity, regOut, 1, 0, &pCol->affinity, 1); } if( iAddr ) sqlite3VdbeJumpHere(v, iAddr); } #endif /* SQLITE_OMIT_GENERATED_COLUMNS */ /* ** Generate code to extract the value of the iCol-th column of a table. */ void sqlite3ExprCodeGetColumnOfTable( Vdbe *v, /* Parsing context */ Table *pTab, /* The table containing the value */ int iTabCur, /* The table cursor. Or the PK cursor for WITHOUT ROWID */ int iCol, /* Index of the column to extract */ int regOut /* Extract the value into this register */ ){ Column *pCol; assert( v!=0 ); assert( pTab!=0 ); if( iCol<0 || iCol==pTab->iPKey ){ sqlite3VdbeAddOp2(v, OP_Rowid, iTabCur, regOut); VdbeComment((v, "%s.rowid", pTab->zName)); }else{ int op; int x; if( IsVirtual(pTab) ){ |
︙ | ︙ | |||
4103 4104 4105 4106 4107 4108 4109 | } case INLINEFUNC_affinity: { /* The AFFINITY() function evaluates to a string that describes ** the type affinity of the argument. This is used for testing of ** the SQLite type logic. */ | | < < < | | 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 | } case INLINEFUNC_affinity: { /* The AFFINITY() function evaluates to a string that describes ** the type affinity of the argument. This is used for testing of ** the SQLite type logic. */ const char *azAff[] = { "blob", "text", "numeric", "integer", "real" }; char aff; assert( nFarg==1 ); aff = sqlite3ExprAffinity(pFarg->a[0].pExpr); sqlite3VdbeLoadString(v, target, (aff<=SQLITE_AFF_NONE) ? "none" : azAff[aff-SQLITE_AFF_BLOB]); break; } #endif /* !defined(SQLITE_UNTESTABLE) */ } return target; } |
︙ | ︙ | |||
4133 4134 4135 4136 4137 4138 4139 | Parse *pParse, /* The parsing context */ Expr *pExpr, /* The expression to potentially bypass */ int target /* Where to store the result of the expression */ ){ IndexedExpr *p; Vdbe *v; for(p=pParse->pIdxEpr; p; p=p->pIENext){ | < < < < < < < < < < < | 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 | Parse *pParse, /* The parsing context */ Expr *pExpr, /* The expression to potentially bypass */ int target /* Where to store the result of the expression */ ){ IndexedExpr *p; Vdbe *v; for(p=pParse->pIdxEpr; p; p=p->pIENext){ int iDataCur = p->iDataCur; if( iDataCur<0 ) continue; if( pParse->iSelfTab ){ if( p->iDataCur!=pParse->iSelfTab-1 ) continue; iDataCur = -1; } if( sqlite3ExprCompare(0, pExpr, p->pExpr, iDataCur)!=0 ) continue; v = pParse->pVdbe; assert( v!=0 ); if( p->bMaybeNullRow ){ /* If the index is on a NULL row due to an outer join, then we ** cannot extract the value from the index. The value must be ** computed using the original expression. */ int addr = sqlite3VdbeCurrentAddr(v); |
︙ | ︙ | |||
4219 4220 4221 4222 4223 4224 4225 | op = pExpr->op; } switch( op ){ case TK_AGG_COLUMN: { AggInfo *pAggInfo = pExpr->pAggInfo; struct AggInfo_col *pCol; assert( pAggInfo!=0 ); | | < < < < < < < < < < < < | 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 | op = pExpr->op; } switch( op ){ case TK_AGG_COLUMN: { AggInfo *pAggInfo = pExpr->pAggInfo; struct AggInfo_col *pCol; assert( pAggInfo!=0 ); assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn ); pCol = &pAggInfo->aCol[pExpr->iAgg]; if( !pAggInfo->directMode ){ return AggInfoColumnReg(pAggInfo, pExpr->iAgg); }else if( pAggInfo->useSortingIdx ){ Table *pTab = pCol->pTab; sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pCol->iSorterColumn, target); |
︙ | ︙ | |||
4406 4407 4408 4409 4410 4411 4412 | } case TK_REGISTER: { return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ | | | > > > | 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 | } case TK_REGISTER: { return pExpr->iTable; } #ifndef SQLITE_OMIT_CAST case TK_CAST: { /* Expressions of the form: CAST(pLeft AS token) */ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); if( inReg!=target ){ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); inReg = target; } assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeAddOp2(v, OP_Cast, target, sqlite3AffinityType(pExpr->u.zToken, 0)); return inReg; } #endif /* SQLITE_OMIT_CAST */ case TK_IS: |
︙ | ︙ | |||
4739 4740 4741 4742 4743 4744 4745 | ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { exprCodeBetween(pParse, pExpr, target, 0, 0); return target; } case TK_COLLATE: { | | | < < < < | > | > > > > | | | 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 | ** Z is stored in pExpr->pList->a[1].pExpr. */ case TK_BETWEEN: { exprCodeBetween(pParse, pExpr, target, 0, 0); return target; } case TK_COLLATE: { if( !ExprHasProperty(pExpr, EP_Collate) && ALWAYS(pExpr->pLeft) && pExpr->pLeft->op==TK_FUNCTION ){ inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); if( inReg!=target ){ sqlite3VdbeAddOp2(v, OP_SCopy, inReg, target); inReg = target; } sqlite3VdbeAddOp1(v, OP_ClrSubtype, inReg); return inReg; }else{ pExpr = pExpr->pLeft; goto expr_code_doover; /* 2018-04-28: Prevent deep recursion. */ } } case TK_SPAN: case TK_UPLUS: { |
︙ | ︙ | |||
4849 4850 4851 4852 4853 4854 4855 | sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pAggInfo->aCol[pExpr->iAgg].iSorterColumn, target); inReg = target; break; } } | | < < < | > | | < | | < > | 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 | sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdxPTab, pAggInfo->aCol[pExpr->iAgg].iSorterColumn, target); inReg = target; break; } } addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable); /* Temporarily disable factoring of constant expressions, since ** even though expressions may appear to be constant, they are not ** really constant because they originate from the right-hand side ** of a LEFT JOIN. */ pParse->okConstFactor = 0; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); pParse->okConstFactor = okConstFactor; sqlite3VdbeJumpHere(v, addrINR); sqlite3VdbeChangeP3(v, addrINR, inReg); break; } /* ** Form A: ** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END ** |
︙ | ︙ | |||
5098 5099 5100 5101 5102 5103 5104 | assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) ); assert( target>0 && target<=pParse->nMem ); assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); if( pParse->pVdbe==0 ) return; inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); if( inReg!=target ){ u8 op; | | < < | 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 | assert( pExpr==0 || !ExprHasVVAProperty(pExpr,EP_Immutable) ); assert( target>0 && target<=pParse->nMem ); assert( pParse->pVdbe!=0 || pParse->db->mallocFailed ); if( pParse->pVdbe==0 ) return; inReg = sqlite3ExprCodeTarget(pParse, pExpr, target); if( inReg!=target ){ u8 op; if( ALWAYS(pExpr) && ExprHasProperty(pExpr,EP_Subquery) ){ op = OP_Copy; }else{ op = OP_SCopy; } sqlite3VdbeAddOp2(pParse->pVdbe, op, inReg, target); } } |
︙ | ︙ | |||
6285 6286 6287 6288 6289 6290 6291 | if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced)) && pExpr->pAggInfo!=0 ){ AggInfo *pAggInfo = pExpr->pAggInfo; int iAgg = pExpr->iAgg; Parse *pParse = pWalker->pParse; sqlite3 *db = pParse->db; | < | | < | | < | 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 | if( ALWAYS(!ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced)) && pExpr->pAggInfo!=0 ){ AggInfo *pAggInfo = pExpr->pAggInfo; int iAgg = pExpr->iAgg; Parse *pParse = pWalker->pParse; sqlite3 *db = pParse->db; if( pExpr->op!=TK_AGG_FUNCTION ){ assert( iAgg>=0 && iAgg<pAggInfo->nColumn ); if( pAggInfo->aCol[iAgg].pCExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aCol[iAgg].pCExpr = pExpr; sqlite3ExprDeferredDelete(pParse, pExpr); } } }else{ assert( pExpr->op==TK_AGG_FUNCTION ); assert( iAgg>=0 && iAgg<pAggInfo->nFunc ); if( pAggInfo->aFunc[iAgg].pFExpr==pExpr ){ pExpr = sqlite3ExprDup(db, pExpr, 0); if( pExpr ){ pAggInfo->aFunc[iAgg].pFExpr = pExpr; sqlite3ExprDeferredDelete(pParse, pExpr); } } } |
︙ | ︙ | |||
6450 6451 6452 6453 6454 6455 6456 | for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){ int iDataCur = pIEpr->iDataCur; if( iDataCur<0 ) continue; if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break; } if( pIEpr==0 ) break; if( NEVER(!ExprUseYTab(pExpr)) ) break; | < < < < | < < < < | 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 | for(pIEpr=pParse->pIdxEpr; pIEpr; pIEpr=pIEpr->pIENext){ int iDataCur = pIEpr->iDataCur; if( iDataCur<0 ) continue; if( sqlite3ExprCompare(0, pExpr, pIEpr->pExpr, iDataCur)==0 ) break; } if( pIEpr==0 ) break; if( NEVER(!ExprUseYTab(pExpr)) ) break; if( pExpr->pAggInfo!=0 ) break; /* Already resolved by outer context */ /* If we reach this point, it means that expression pExpr can be ** translated into a reference to an index column as described by ** pIEpr. */ memset(&tmp, 0, sizeof(tmp)); tmp.op = TK_AGG_COLUMN; tmp.iTable = pIEpr->iIdxCur; tmp.iColumn = pIEpr->iIdxCol; findOrCreateAggInfoColumn(pParse, pAggInfo, &tmp); pAggInfo->aCol[tmp.iAgg].pCExpr = pExpr; pExpr->pAggInfo = pAggInfo; pExpr->iAgg = tmp.iAgg; return WRC_Prune; } case TK_IF_NULL_ROW: case TK_AGG_COLUMN: |
︙ | ︙ | |||
6492 6493 6494 6495 6496 6497 6498 | assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ findOrCreateAggInfoColumn(pParse, pAggInfo, pExpr); break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } | | | 6450 6451 6452 6453 6454 6455 6456 6457 6458 6459 6460 6461 6462 6463 6464 | assert( !ExprHasProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ findOrCreateAggInfoColumn(pParse, pAggInfo, pExpr); break; } /* endif pExpr->iTable==pItem->iCursor */ } /* end loop over pSrcList */ } return WRC_Prune; } case TK_AGG_FUNCTION: { if( (pNC->ncFlags & NC_InAggFunc)==0 && pWalker->walkerDepth==pExpr->op2 ){ /* Check to see if pExpr is a duplicate of another aggregate ** function that is already in the pAggInfo structure |
︙ | ︙ | |||
6645 6646 6647 6648 6649 6650 6651 | ** invokes the sub/co-routine. */ void sqlite3ClearTempRegCache(Parse *pParse){ pParse->nTempReg = 0; pParse->nRangeReg = 0; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 6603 6604 6605 6606 6607 6608 6609 6610 6611 6612 6613 6614 6615 6616 6617 6618 6619 6620 6621 6622 6623 6624 6625 6626 6627 6628 6629 6630 6631 | ** invokes the sub/co-routine. */ void sqlite3ClearTempRegCache(Parse *pParse){ pParse->nTempReg = 0; pParse->nRangeReg = 0; } /* ** Validate that no temporary register falls within the range of ** iFirst..iLast, inclusive. This routine is only call from within assert() ** statements. */ #ifdef SQLITE_DEBUG int sqlite3NoTempsInRange(Parse *pParse, int iFirst, int iLast){ int i; if( pParse->nRangeReg>0 && pParse->iRangeReg+pParse->nRangeReg > iFirst && pParse->iRangeReg <= iLast ){ return 0; } for(i=0; i<pParse->nTempReg; i++){ if( pParse->aTempReg[i]>=iFirst && pParse->aTempReg[i]<=iLast ){ return 0; } } return 1; } #endif /* SQLITE_DEBUG */ |
Changes to src/fkey.c.
︙ | ︙ | |||
1313 1314 1315 1316 1317 1318 1319 | sqlite3DbFree(db, aiCol); zFrom = pFKey->pFrom->zName; nFrom = sqlite3Strlen30(zFrom); if( action==OE_Restrict ){ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | | > > > > > > < < < < < < | | 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 | sqlite3DbFree(db, aiCol); zFrom = pFKey->pFrom->zName; nFrom = sqlite3Strlen30(zFrom); if( action==OE_Restrict ){ int iDb = sqlite3SchemaToIndex(db, pTab->pSchema); Token tFrom; Token tDb; Expr *pRaise; tFrom.z = zFrom; tFrom.n = nFrom; tDb.z = db->aDb[iDb].zDbSName; tDb.n = sqlite3Strlen30(tDb.z); pRaise = sqlite3Expr(db, TK_RAISE, "FOREIGN KEY constraint failed"); if( pRaise ){ pRaise->affExpr = OE_Abort; } pSelect = sqlite3SelectNew(pParse, sqlite3ExprListAppend(pParse, 0, pRaise), sqlite3SrcListAppend(pParse, 0, &tDb, &tFrom), pWhere, 0, 0, 0, 0, 0 ); pWhere = 0; } /* Disable lookaside memory allocation */ |
︙ | ︙ |
Changes to src/func.c.
︙ | ︙ | |||
1265 1266 1267 1268 1269 1270 1271 | sqlite3_value **argv ){ const u8 *zPass = (const u8*)""; int nPass = 0; const u8 *zHex = sqlite3_value_text(argv[0]); int nHex = sqlite3_value_bytes(argv[0]); #ifdef SQLITE_DEBUG | | | 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 | sqlite3_value **argv ){ const u8 *zPass = (const u8*)""; int nPass = 0; const u8 *zHex = sqlite3_value_text(argv[0]); int nHex = sqlite3_value_bytes(argv[0]); #ifdef SQLITE_DEBUG const u8 *zEnd = &zHex[nHex]; #endif u8 *pBlob = 0; u8 *p = 0; assert( argc==1 || argc==2 ); if( argc==2 ){ zPass = sqlite3_value_text(argv[1]); |
︙ | ︙ | |||
2156 2157 2158 2159 2160 2161 2162 | /* ** On some systems, ceil() and floor() are intrinsic function. You are ** unable to take a pointer to these functions. Hence, we here wrap them ** in our own actual functions. */ static double xCeil(double x){ return ceil(x); } static double xFloor(double x){ return floor(x); } | < < < < < < < < < < < < | 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 | /* ** On some systems, ceil() and floor() are intrinsic function. You are ** unable to take a pointer to these functions. Hence, we here wrap them ** in our own actual functions. */ static double xCeil(double x){ return ceil(x); } static double xFloor(double x){ return floor(x); } /* ** Implementation of SQL functions: ** ** ln(X) - natural logarithm ** log(X) - log X base 10 ** log10(X) - log X base 10 |
︙ | ︙ |
Changes to src/global.c.
︙ | ︙ | |||
93 94 95 96 97 98 99 | ** ** isspace() 0x01 ** isalpha() 0x02 ** isdigit() 0x04 ** isalnum() 0x06 ** isxdigit() 0x08 ** toupper() 0x20 | | | 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | ** ** isspace() 0x01 ** isalpha() 0x02 ** isdigit() 0x04 ** isalnum() 0x06 ** isxdigit() 0x08 ** toupper() 0x20 ** SQLite identifier character 0x40 ** Quote character 0x80 ** ** Bit 0x20 is set if the mapped character requires translation to upper ** case. i.e. if the character is a lower-case ASCII character. ** If x is a lower-case ASCII character, then its upper-case equivalent ** is (x - 0x20). Therefore toupper() can be implemented as: ** |
︙ | ︙ | |||
287 288 289 290 291 292 293 | #endif 0, /* bLocaltimeFault */ 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ #ifdef SQLITE_DEBUG | | | 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 | #endif 0, /* bLocaltimeFault */ 0, /* xAltLocaltime */ 0x7ffffffe, /* iOnceResetThreshold */ SQLITE_DEFAULT_SORTERREF_SIZE, /* szSorterRef */ 0, /* iPrngSeed */ #ifdef SQLITE_DEBUG {0,0,0,0,0,0} /* aTune */ #endif }; /* ** Hash table for global functions - functions common to all ** database connections. After initialization, this table is ** read-only. |
︙ | ︙ |
Changes to src/insert.c.
︙ | ︙ | |||
66 67 68 69 70 71 72 | ** An extra 'D' is appended to the end of the string to cover the ** rowid that appears as the last column in every index. ** ** Memory for the buffer containing the column index affinity string ** is managed along with the rest of the Index structure. It will be ** released when sqlite3DeleteIndex() is called. */ | | > | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | < | | < < | 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 | ** An extra 'D' is appended to the end of the string to cover the ** rowid that appears as the last column in every index. ** ** Memory for the buffer containing the column index affinity string ** is managed along with the rest of the Index structure. It will be ** released when sqlite3DeleteIndex() is called. */ const char *sqlite3IndexAffinityStr(sqlite3 *db, Index *pIdx){ if( !pIdx->zColAff ){ /* The first time a column affinity string for a particular index is ** required, it is allocated and populated here. It is then stored as ** a member of the Index structure for subsequent use. ** ** The column affinity string will eventually be deleted by ** sqliteDeleteIndex() when the Index structure itself is cleaned ** up. */ int n; Table *pTab = pIdx->pTable; pIdx->zColAff = (char *)sqlite3DbMallocRaw(0, pIdx->nColumn+1); if( !pIdx->zColAff ){ sqlite3OomFault(db); return 0; } for(n=0; n<pIdx->nColumn; n++){ i16 x = pIdx->aiColumn[n]; char aff; if( x>=0 ){ aff = pTab->aCol[x].affinity; }else if( x==XN_ROWID ){ aff = SQLITE_AFF_INTEGER; }else{ assert( x==XN_EXPR ); assert( pIdx->bHasExpr ); assert( pIdx->aColExpr!=0 ); aff = sqlite3ExprAffinity(pIdx->aColExpr->a[n].pExpr); } if( aff<SQLITE_AFF_BLOB ) aff = SQLITE_AFF_BLOB; if( aff>SQLITE_AFF_NUMERIC) aff = SQLITE_AFF_NUMERIC; pIdx->zColAff[n] = aff; } pIdx->zColAff[n] = 0; } return pIdx->zColAff; } /* ** Compute an affinity string for a table. Space is obtained ** from sqlite3DbMalloc(). The caller is responsible for freeing ** the space when done. */ char *sqlite3TableAffinityStr(sqlite3 *db, const Table *pTab){ |
︙ | ︙ | |||
792 793 794 795 796 797 798 | */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } /* Cannot insert into a read-only table. */ | | | 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 | */ if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto insert_cleanup; } /* Cannot insert into a read-only table. */ if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ goto insert_cleanup; } /* Allocate a VDBE */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto insert_cleanup; |
︙ | ︙ | |||
1239 1240 1241 1242 1243 1244 1245 | addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); } /* Copy the new data already generated. */ | | | 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 | addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, regCols); VdbeCoverage(v); sqlite3VdbeAddOp2(v, OP_Integer, -1, regCols); sqlite3VdbeJumpHere(v, addr1); sqlite3VdbeAddOp1(v, OP_MustBeInt, regCols); VdbeCoverage(v); } /* Copy the new data already generated. */ assert( pTab->nNVCol>0 ); sqlite3VdbeAddOp3(v, OP_Copy, regRowid+1, regCols+1, pTab->nNVCol-1); #ifndef SQLITE_OMIT_GENERATED_COLUMNS /* Compute the new value for generated columns after all other ** columns have already been computed. This must be done after ** computing the ROWID in case one of the generated columns ** refers to the ROWID. */ |
︙ | ︙ |
Changes to src/json.c.
︙ | ︙ | |||
100 101 102 103 104 105 106 | #define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ #define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ #define JNODE_REMOVE 0x04 /* Do not output */ #define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */ #define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */ #define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ #define JNODE_LABEL 0x40 /* Is a label of an object */ | < | 100 101 102 103 104 105 106 107 108 109 110 111 112 113 | #define JNODE_RAW 0x01 /* Content is raw, not JSON encoded */ #define JNODE_ESCAPE 0x02 /* Content is text with \ escapes */ #define JNODE_REMOVE 0x04 /* Do not output */ #define JNODE_REPLACE 0x08 /* Replace with JsonNode.u.iReplace */ #define JNODE_PATCH 0x10 /* Patch with JsonNode.u.pPatch */ #define JNODE_APPEND 0x20 /* More ARRAY/OBJECT entries at u.iAppend */ #define JNODE_LABEL 0x40 /* Is a label of an object */ /* A single node of parsed JSON */ struct JsonNode { u8 eType; /* One of the JSON_ type values */ u8 jnFlags; /* JNODE flags */ |
︙ | ︙ | |||
127 128 129 130 131 132 133 | */ struct JsonParse { u32 nNode; /* Number of slots of aNode[] used */ u32 nAlloc; /* Number of slots of aNode[] allocated */ JsonNode *aNode; /* Array of nodes containing the parse */ const char *zJson; /* Original JSON string */ u32 *aUp; /* Index of parent of each node */ | | | < < | 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | */ struct JsonParse { u32 nNode; /* Number of slots of aNode[] used */ u32 nAlloc; /* Number of slots of aNode[] allocated */ JsonNode *aNode; /* Array of nodes containing the parse */ const char *zJson; /* Original JSON string */ u32 *aUp; /* Index of parent of each node */ u8 oom; /* Set to true if out of memory */ u8 nErr; /* Number of errors seen */ u16 iDepth; /* Nesting depth */ int nJson; /* Length of the zJson string in bytes */ u32 iHold; /* Replace cache line with the lowest iHold value */ }; /* ** Maximum nesting depth of JSON for this implementation. ** ** This limit is needed to avoid a stack overflow in the recursive |
︙ | ︙ | |||
292 293 294 295 296 297 298 | c = "0123456789abcdef"[c&0xf]; } p->zBuf[p->nUsed++] = c; } p->zBuf[p->nUsed++] = '"'; assert( p->nUsed<p->nAlloc ); } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < | | 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 | c = "0123456789abcdef"[c&0xf]; } p->zBuf[p->nUsed++] = c; } p->zBuf[p->nUsed++] = '"'; assert( p->nUsed<p->nAlloc ); } /* ** Append a function parameter value to the JSON string under ** construction. */ static void jsonAppendValue( JsonString *p, /* Append to this JSON string */ sqlite3_value *pValue /* Value to append */ ){ switch( sqlite3_value_type(pValue) ){ case SQLITE_NULL: { jsonAppendRaw(p, "null", 4); break; } case SQLITE_INTEGER: case SQLITE_FLOAT: { const char *z = (const char*)sqlite3_value_text(pValue); u32 n = (u32)sqlite3_value_bytes(pValue); jsonAppendRaw(p, z, n); break; } case SQLITE_TEXT: { const char *z = (const char*)sqlite3_value_text(pValue); |
︙ | ︙ | |||
546 547 548 549 550 551 552 | break; } case JSON_FALSE: { jsonAppendRaw(pOut, "false", 5); break; } case JSON_STRING: { | < | < < < < | < < < < < < | | < < < < < < < | > < < < | < | 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 | break; } case JSON_FALSE: { jsonAppendRaw(pOut, "false", 5); break; } case JSON_STRING: { if( pNode->jnFlags & JNODE_RAW ){ assert( pNode->eU==1 ); jsonAppendString(pOut, pNode->u.zJContent, pNode->n); break; } /* no break */ deliberate_fall_through } case JSON_REAL: case JSON_INT: { assert( pNode->eU==1 ); jsonAppendRaw(pOut, pNode->u.zJContent, pNode->n); break; } case JSON_ARRAY: { u32 j = 1; jsonAppendChar(pOut, '['); for(;;){ while( j<=pNode->n ){ |
︙ | ︙ | |||
693 694 695 696 697 698 699 | } case JSON_FALSE: { sqlite3_result_int(pCtx, 0); break; } case JSON_INT: { sqlite3_int64 i = 0; | < < < < | | | > > > > | < | | > | | | > > > > > > > > > < > > > > > > > > > > | < | | > > | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 | } case JSON_FALSE: { sqlite3_result_int(pCtx, 0); break; } case JSON_INT: { sqlite3_int64 i = 0; const char *z; assert( pNode->eU==1 ); z = pNode->u.zJContent; if( z[0]=='-' ){ z++; } while( z[0]>='0' && z[0]<='9' ){ unsigned v = *(z++) - '0'; if( i>=LARGEST_INT64/10 ){ if( i>LARGEST_INT64/10 ) goto int_as_real; if( z[0]>='0' && z[0]<='9' ) goto int_as_real; if( v==9 ) goto int_as_real; if( v==8 ){ if( pNode->u.zJContent[0]=='-' ){ sqlite3_result_int64(pCtx, SMALLEST_INT64); goto int_done; }else{ goto int_as_real; } } } i = i*10 + v; } if( pNode->u.zJContent[0]=='-' ){ i = -i; } sqlite3_result_int64(pCtx, i); int_done: break; int_as_real: ; /* no break */ deliberate_fall_through } case JSON_REAL: { double r; #ifdef SQLITE_AMALGAMATION const char *z; assert( pNode->eU==1 ); z = pNode->u.zJContent; sqlite3AtoF(z, &r, sqlite3Strlen30(z), SQLITE_UTF8); #else assert( pNode->eU==1 ); r = strtod(pNode->u.zJContent, 0); #endif sqlite3_result_double(pCtx, r); break; } case JSON_STRING: { #if 0 /* Never happens because JNODE_RAW is only set by json_set(), ** json_insert() and json_replace() and those routines do not ** call jsonReturn() */ if( pNode->jnFlags & JNODE_RAW ){ assert( pNode->eU==1 ); sqlite3_result_text(pCtx, pNode->u.zJContent, pNode->n, SQLITE_TRANSIENT); }else #endif assert( (pNode->jnFlags & JNODE_RAW)==0 ); if( (pNode->jnFlags & JNODE_ESCAPE)==0 ){ /* JSON formatted without any backslash-escapes */ assert( pNode->eU==1 ); sqlite3_result_text(pCtx, pNode->u.zJContent+1, pNode->n-2, SQLITE_TRANSIENT); }else{ /* Translate JSON formatted string into raw text */ u32 i; u32 n = pNode->n; const char *z; char *zOut; u32 j; assert( pNode->eU==1 ); z = pNode->u.zJContent; zOut = sqlite3_malloc( n+1 ); if( zOut==0 ){ sqlite3_result_error_nomem(pCtx); break; } for(i=1, j=0; i<n-1; i++){ char c = z[i]; if( c!='\\' ){ zOut[j++] = c; }else{ c = z[++i]; if( c=='u' ){ u32 v = jsonHexToInt4(z+i+1); i += 4; if( v==0 ) break; if( v<=0x7f ){ zOut[j++] = (char)v; |
︙ | ︙ | |||
781 782 783 784 785 786 787 | zOut[j++] = 0x80 | (v&0x3f); }else{ zOut[j++] = 0xe0 | (v>>12); zOut[j++] = 0x80 | ((v>>6)&0x3f); zOut[j++] = 0x80 | (v&0x3f); } } | | | | | | | | | | | | < < < < < < < < < < < < < < < < < < < | < | < > > > | 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 | zOut[j++] = 0x80 | (v&0x3f); }else{ zOut[j++] = 0xe0 | (v>>12); zOut[j++] = 0x80 | ((v>>6)&0x3f); zOut[j++] = 0x80 | (v&0x3f); } } }else{ if( c=='b' ){ c = '\b'; }else if( c=='f' ){ c = '\f'; }else if( c=='n' ){ c = '\n'; }else if( c=='r' ){ c = '\r'; }else if( c=='t' ){ c = '\t'; } zOut[j++] = c; } } } zOut[j] = 0; sqlite3_result_text(pCtx, zOut, j, sqlite3_free); } break; } case JSON_ARRAY: case JSON_OBJECT: { |
︙ | ︙ | |||
882 883 884 885 886 887 888 | const char *zContent /* Content */ ){ JsonNode *p; if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){ return jsonParseAddNodeExpand(pParse, eType, n, zContent); } p = &pParse->aNode[pParse->nNode]; | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < | > | < < < < | | < < < < > > | < | < < < < < < < < < < < < < < < < < < < < < < | < < > > > < < < | < | | < < < | < < < < | < < < < < | < < < < < < | < | | | | < | < < < < < < < < < < < < < < < | < < < < > > > | | < < < < < > | | | | < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < | | < < < | | < < < < < < < < < < < | | > < | > | | | | < | < < | | | < < < < | < < < < | | < < < | < < < | | < < < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < < < | | < < | < < < < < < < < < < < | | | < | < | | < < < < < < < < | < < < < | | < < < | < < < < < < < < < | > < | < < | < < < < < < < < < < | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 | const char *zContent /* Content */ ){ JsonNode *p; if( pParse->aNode==0 || pParse->nNode>=pParse->nAlloc ){ return jsonParseAddNodeExpand(pParse, eType, n, zContent); } p = &pParse->aNode[pParse->nNode]; p->eType = (u8)eType; p->jnFlags = 0; VVA( p->eU = zContent ? 1 : 0 ); p->n = n; p->u.zJContent = zContent; return pParse->nNode++; } /* ** Return true if z[] begins with 4 (or more) hexadecimal digits */ static int jsonIs4Hex(const char *z){ int i; for(i=0; i<4; i++) if( !sqlite3Isxdigit(z[i]) ) return 0; return 1; } /* ** Parse a single JSON value which begins at pParse->zJson[i]. Return the ** index of the first character past the end of the value parsed. ** ** Return negative for a syntax error. Special cases: return -2 if the ** first non-whitespace character is '}' and return -3 if the first ** non-whitespace character is ']'. */ static int jsonParseValue(JsonParse *pParse, u32 i){ char c; u32 j; int iThis; int x; JsonNode *pNode; const char *z = pParse->zJson; while( fast_isspace(z[i]) ){ i++; } if( (c = z[i])=='{' ){ /* Parse object */ iThis = jsonParseAddNode(pParse, JSON_OBJECT, 0, 0); if( iThis<0 ) return -1; for(j=i+1;;j++){ while( fast_isspace(z[j]) ){ j++; } if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; x = jsonParseValue(pParse, j); if( x<0 ){ pParse->iDepth--; if( x==(-2) && pParse->nNode==(u32)iThis+1 ) return j+1; return -1; } if( pParse->oom ) return -1; pNode = &pParse->aNode[pParse->nNode-1]; if( pNode->eType!=JSON_STRING ) return -1; pNode->jnFlags |= JNODE_LABEL; j = x; while( fast_isspace(z[j]) ){ j++; } if( z[j]!=':' ) return -1; j++; x = jsonParseValue(pParse, j); pParse->iDepth--; if( x<0 ) return -1; j = x; while( fast_isspace(z[j]) ){ j++; } c = z[j]; if( c==',' ) continue; if( c!='}' ) return -1; break; } pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; return j+1; }else if( c=='[' ){ /* Parse array */ iThis = jsonParseAddNode(pParse, JSON_ARRAY, 0, 0); if( iThis<0 ) return -1; memset(&pParse->aNode[iThis].u, 0, sizeof(pParse->aNode[iThis].u)); for(j=i+1;;j++){ while( fast_isspace(z[j]) ){ j++; } if( ++pParse->iDepth > JSON_MAX_DEPTH ) return -1; x = jsonParseValue(pParse, j); pParse->iDepth--; if( x<0 ){ if( x==(-3) && pParse->nNode==(u32)iThis+1 ) return j+1; return -1; } j = x; while( fast_isspace(z[j]) ){ j++; } c = z[j]; if( c==',' ) continue; if( c!=']' ) return -1; break; } pParse->aNode[iThis].n = pParse->nNode - (u32)iThis - 1; return j+1; }else if( c=='"' ){ /* Parse string */ u8 jnFlags = 0; j = i+1; for(;;){ c = z[j]; if( (c & ~0x1f)==0 ){ /* Control characters are not allowed in strings */ return -1; } if( c=='\\' ){ c = z[++j]; if( c=='"' || c=='\\' || c=='/' || c=='b' || c=='f' || c=='n' || c=='r' || c=='t' || (c=='u' && jsonIs4Hex(z+j+1)) ){ jnFlags = JNODE_ESCAPE; }else{ return -1; } }else if( c=='"' ){ break; } j++; } jsonParseAddNode(pParse, JSON_STRING, j+1-i, &z[i]); if( !pParse->oom ) pParse->aNode[pParse->nNode-1].jnFlags = jnFlags; return j+1; }else if( c=='n' && strncmp(z+i,"null",4)==0 && !sqlite3Isalnum(z[i+4]) ){ jsonParseAddNode(pParse, JSON_NULL, 0, 0); return i+4; }else if( c=='t' && strncmp(z+i,"true",4)==0 && !sqlite3Isalnum(z[i+4]) ){ jsonParseAddNode(pParse, JSON_TRUE, 0, 0); return i+4; }else if( c=='f' && strncmp(z+i,"false",5)==0 && !sqlite3Isalnum(z[i+5]) ){ jsonParseAddNode(pParse, JSON_FALSE, 0, 0); return i+5; }else if( c=='-' || (c>='0' && c<='9') ){ /* Parse number */ u8 seenDP = 0; u8 seenE = 0; assert( '-' < '0' ); if( c<='0' ){ j = c=='-' ? i+1 : i; if( z[j]=='0' && z[j+1]>='0' && z[j+1]<='9' ) return -1; } j = i+1; for(;; j++){ c = z[j]; if( c>='0' && c<='9' ) continue; if( c=='.' ){ if( z[j-1]=='-' ) return -1; if( seenDP ) return -1; seenDP = 1; continue; } if( c=='e' || c=='E' ){ if( z[j-1]<'0' ) return -1; if( seenE ) return -1; seenDP = seenE = 1; c = z[j+1]; if( c=='+' || c=='-' ){ j++; c = z[j+1]; } if( c<'0' || c>'9' ) return -1; continue; } break; } if( z[j-1]<'0' ) return -1; jsonParseAddNode(pParse, seenDP ? JSON_REAL : JSON_INT, j - i, &z[i]); return j; }else if( c=='}' ){ return -2; /* End of {...} */ }else if( c==']' ){ return -3; /* End of [...] */ }else if( c==0 ){ return 0; /* End of file */ }else{ return -1; /* Syntax error */ } } /* ** Parse a complete JSON string. Return 0 on success or non-zero if there ** are any errors. If an error occurs, free all memory associated with ** pParse. ** |
︙ | ︙ | |||
1516 1517 1518 1519 1520 1521 1522 | if( zJson==0 ) return 1; pParse->zJson = zJson; i = jsonParseValue(pParse, 0); if( pParse->oom ) i = -1; if( i>0 ){ assert( pParse->iDepth==0 ); while( fast_isspace(zJson[i]) ) i++; | | < < < < < < < | 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 | if( zJson==0 ) return 1; pParse->zJson = zJson; i = jsonParseValue(pParse, 0); if( pParse->oom ) i = -1; if( i>0 ){ assert( pParse->iDepth==0 ); while( fast_isspace(zJson[i]) ) i++; if( zJson[i] ) i = -1; } if( i<=0 ){ if( pCtx!=0 ){ if( pParse->oom ){ sqlite3_result_error_nomem(pCtx); }else{ sqlite3_result_error(pCtx, "malformed JSON", -1); |
︙ | ︙ | |||
1594 1595 1596 1597 1598 1599 1600 | /* ** Obtain a complete parse of the JSON found in the first argument ** of the argv array. Use the sqlite3_get_auxdata() cache for this ** parse if it is available. If the cache is not available or if it ** is no longer valid, parse the JSON again and return the new parse, ** and also register the new parse so that it will be available for ** future sqlite3_get_auxdata() calls. | < < < < < < < < < | 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 | /* ** Obtain a complete parse of the JSON found in the first argument ** of the argv array. Use the sqlite3_get_auxdata() cache for this ** parse if it is available. If the cache is not available or if it ** is no longer valid, parse the JSON again and return the new parse, ** and also register the new parse so that it will be available for ** future sqlite3_get_auxdata() calls. */ static JsonParse *jsonParseCached( sqlite3_context *pCtx, sqlite3_value **argv, sqlite3_context *pErrCtx ){ const char *zJson = (const char*)sqlite3_value_text(argv[0]); |
︙ | ︙ | |||
1652 1653 1654 1655 1656 1657 1658 | sqlite3_result_error_nomem(pCtx); return 0; } memset(p, 0, sizeof(*p)); p->zJson = (char*)&p[1]; memcpy((char*)p->zJson, zJson, nJson+1); if( jsonParse(p, pErrCtx, p->zJson) ){ | < < < < | < < < < < < < < < | 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 | sqlite3_result_error_nomem(pCtx); return 0; } memset(p, 0, sizeof(*p)); p->zJson = (char*)&p[1]; memcpy((char*)p->zJson, zJson, nJson+1); if( jsonParse(p, pErrCtx, p->zJson) ){ sqlite3_free(p); return 0; } p->nJson = nJson; p->iHold = iMaxHold+1; sqlite3_set_auxdata(pCtx, JSON_CACHE_ID+iMinKey, p, (void(*)(void*))jsonParseFree); return (JsonParse*)sqlite3_get_auxdata(pCtx, JSON_CACHE_ID+iMinKey); } /* ** Compare the OBJECT label at pNode against zKey,nKey. Return true on ** a match. */ static int jsonLabelCompare(JsonNode *pNode, const char *zKey, u32 nKey){ assert( pNode->eU==1 ); if( pNode->jnFlags & JNODE_RAW ){ if( pNode->n!=nKey ) return 0; return strncmp(pNode->u.zJContent, zKey, nKey)==0; }else{ if( pNode->n!=nKey+2 ) return 0; return strncmp(pNode->u.zJContent+1, zKey, nKey)==0; } } /* forward declaration */ static JsonNode *jsonLookupAppend(JsonParse*,const char*,int*,const char**); /* ** Search along zPath to find the node specified. Return a pointer ** to that node, or NULL if zPath is malformed or if there is no such |
︙ | ︙ | |||
2159 2160 2161 2162 2163 2164 2165 | p = jsonParseCached(ctx, argv, ctx); if( p==0 ) return; if( argc==2 ){ /* With a single PATH argument */ zPath = (const char*)sqlite3_value_text(argv[1]); if( zPath==0 ) return; if( flags & JSON_ABPATH ){ | | | 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 | p = jsonParseCached(ctx, argv, ctx); if( p==0 ) return; if( argc==2 ){ /* With a single PATH argument */ zPath = (const char*)sqlite3_value_text(argv[1]); if( zPath==0 ) return; if( flags & JSON_ABPATH ){ if( zPath[0]!='$' ){ /* The -> and ->> operators accept abbreviated PATH arguments. This ** is mostly for compatibility with PostgreSQL, but also for ** convenience. ** ** NUMBER ==> $[NUMBER] // PG compatible ** LABEL ==> $.LABEL // PG compatible ** [NUMBER] ==> $[NUMBER] // Not PG. Purely for convenience |
︙ | ︙ | |||
2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 | u32 nKey; const char *zKey; assert( pPatch[i].eType==JSON_STRING ); assert( pPatch[i].jnFlags & JNODE_LABEL ); assert( pPatch[i].eU==1 ); nKey = pPatch[i].n; zKey = pPatch[i].u.zJContent; for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){ assert( pTarget[j].eType==JSON_STRING ); assert( pTarget[j].jnFlags & JNODE_LABEL ); | > | > | 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 | u32 nKey; const char *zKey; assert( pPatch[i].eType==JSON_STRING ); assert( pPatch[i].jnFlags & JNODE_LABEL ); assert( pPatch[i].eU==1 ); nKey = pPatch[i].n; zKey = pPatch[i].u.zJContent; assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); for(j=1; j<pTarget->n; j += jsonNodeSize(&pTarget[j+1])+1 ){ assert( pTarget[j].eType==JSON_STRING ); assert( pTarget[j].jnFlags & JNODE_LABEL ); assert( (pPatch[i].jnFlags & JNODE_RAW)==0 ); if( pTarget[j].n==nKey && strncmp(pTarget[j].u.zJContent,zKey,nKey)==0 ){ if( pTarget[j+1].jnFlags & (JNODE_REMOVE|JNODE_PATCH) ) break; if( pPatch[i+1].eType==JSON_NULL ){ pTarget[j+1].jnFlags |= JNODE_REMOVE; }else{ JsonNode *pNew = jsonMergePatch(pParse, iTarget+j+1, &pPatch[i+1]); if( pNew==0 ) return 0; pTarget = &pParse->aNode[iTarget]; |
︙ | ︙ | |||
2540 2541 2542 2543 2544 2545 2546 | sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); } } /* ** json_valid(JSON) ** | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < | 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 | sqlite3_result_text(ctx, jsonType[pNode->eType], -1, SQLITE_STATIC); } } /* ** json_valid(JSON) ** ** Return 1 if JSON is a well-formed JSON string according to RFC-7159. ** Return 0 otherwise. */ static void jsonValidFunc( sqlite3_context *ctx, int argc, sqlite3_value **argv ){ JsonParse *p; /* The parse */ UNUSED_PARAMETER(argc); p = jsonParseCached(ctx, argv, 0); sqlite3_result_int(ctx, p!=0); } /**************************************************************************** ** Aggregate SQL function implementations ****************************************************************************/ /* |
︙ | ︙ | |||
2956 2957 2958 2959 2960 2961 2962 | int jj, nn; const char *z; assert( pNode->eType==JSON_STRING ); assert( pNode->jnFlags & JNODE_LABEL ); assert( pNode->eU==1 ); z = pNode->u.zJContent; nn = pNode->n; | < | | | | | | | | < | 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 | int jj, nn; const char *z; assert( pNode->eType==JSON_STRING ); assert( pNode->jnFlags & JNODE_LABEL ); assert( pNode->eU==1 ); z = pNode->u.zJContent; nn = pNode->n; assert( nn>=2 ); assert( z[0]=='"' ); assert( z[nn-1]=='"' ); if( nn>2 && sqlite3Isalpha(z[1]) ){ for(jj=2; jj<nn-1 && sqlite3Isalnum(z[jj]); jj++){} if( jj==nn-1 ){ z++; nn -= 2; } } jsonPrintf(nn+2, pStr, ".%.*s", nn, z); } /* Append the name of the path for element i to pStr */ |
︙ | ︙ | |||
3325 3326 3327 3328 3329 3330 3331 | void sqlite3RegisterJsonFunctions(void){ #ifndef SQLITE_OMIT_JSON static FuncDef aJsonFunc[] = { JFUNCTION(json, 1, 0, jsonRemoveFunc), JFUNCTION(json_array, -1, 0, jsonArrayFunc), JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), | < | 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 | void sqlite3RegisterJsonFunctions(void){ #ifndef SQLITE_OMIT_JSON static FuncDef aJsonFunc[] = { JFUNCTION(json, 1, 0, jsonRemoveFunc), JFUNCTION(json_array, -1, 0, jsonArrayFunc), JFUNCTION(json_array_length, 1, 0, jsonArrayLengthFunc), JFUNCTION(json_array_length, 2, 0, jsonArrayLengthFunc), JFUNCTION(json_extract, -1, 0, jsonExtractFunc), JFUNCTION(->, 2, JSON_JSON, jsonExtractFunc), JFUNCTION(->>, 2, JSON_SQL, jsonExtractFunc), JFUNCTION(json_insert, -1, 0, jsonSetFunc), JFUNCTION(json_object, -1, 0, jsonObjectFunc), JFUNCTION(json_patch, 2, 0, jsonPatchFunc), JFUNCTION(json_quote, 1, 0, jsonQuoteFunc), |
︙ | ︙ |
Changes to src/loadext.c.
︙ | ︙ | |||
581 582 583 584 585 586 587 | } zEntry = zProc ? zProc : "sqlite3_extension_init"; /* tag-20210611-1. Some dlopen() implementations will segfault if given ** an oversize filename. Most filesystems have a pathname limit of 4K, ** so limit the extension filename length to about twice that. | | < < < < < | < | 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 | } zEntry = zProc ? zProc : "sqlite3_extension_init"; /* tag-20210611-1. Some dlopen() implementations will segfault if given ** an oversize filename. Most filesystems have a pathname limit of 4K, ** so limit the extension filename length to about twice that. ** https://sqlite.org/forum/forumpost/08a0d6d9bf */ if( nMsg>SQLITE_MAX_PATHLEN ) goto extension_not_found; handle = sqlite3OsDlOpen(pVfs, zFile); #if SQLITE_OS_UNIX || SQLITE_OS_WIN for(ii=0; ii<ArraySize(azEndings) && handle==0; ii++){ char *zAltFile = sqlite3_mprintf("%s.%s", zFile, azEndings[ii]); if( zAltFile==0 ) return SQLITE_NOMEM_BKPT; handle = sqlite3OsDlOpen(pVfs, zAltFile); sqlite3_free(zAltFile); } #endif if( handle==0 ) goto extension_not_found; xInit = (sqlite3_loadext_entry)sqlite3OsDlSym(pVfs, handle, zEntry); /* If no entry point was specified and the default legacy |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
426 427 428 429 430 431 432 | ** threadsafe. Failure to heed these warnings can lead to unpredictable ** behavior. */ int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; | | | < < | < < < < < < < < < < | 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 | ** threadsafe. Failure to heed these warnings can lead to unpredictable ** behavior. */ int sqlite3_config(int op, ...){ va_list ap; int rc = SQLITE_OK; /* sqlite3_config() shall return SQLITE_MISUSE if it is invoked while ** the SQLite library is in use. */ if( sqlite3GlobalConfig.isInit ) return SQLITE_MISUSE_BKPT; va_start(ap, op); switch( op ){ /* Mutex configuration options are only available in a threadsafe ** compile. */ |
︙ | ︙ | |||
509 510 511 512 513 514 515 | ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is ** filled with the currently defined memory allocation routines. */ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } case SQLITE_CONFIG_MEMSTATUS: { | < | 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | ** sqlite3_mem_methods structure. The sqlite3_mem_methods structure is ** filled with the currently defined memory allocation routines. */ if( sqlite3GlobalConfig.m.xMalloc==0 ) sqlite3MemSetDefault(); *va_arg(ap, sqlite3_mem_methods*) = sqlite3GlobalConfig.m; break; } case SQLITE_CONFIG_MEMSTATUS: { /* EVIDENCE-OF: R-61275-35157 The SQLITE_CONFIG_MEMSTATUS option takes ** single argument of type int, interpreted as a boolean, which enables ** or disables the collection of memory allocation statistics. */ sqlite3GlobalConfig.bMemstat = va_arg(ap, int); break; } case SQLITE_CONFIG_SMALL_MALLOC: { |
︙ | ︙ | |||
633 634 635 636 637 638 639 | */ case SQLITE_CONFIG_LOG: { /* MSVC is picky about pulling func ptrs from va lists. ** http://support.microsoft.com/kb/47961 ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); */ typedef void(*LOGFUNC_t)(void*,int,const char*); | | | < < | < | 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 | */ case SQLITE_CONFIG_LOG: { /* MSVC is picky about pulling func ptrs from va lists. ** http://support.microsoft.com/kb/47961 ** sqlite3GlobalConfig.xLog = va_arg(ap, void(*)(void*,int,const char*)); */ typedef void(*LOGFUNC_t)(void*,int,const char*); sqlite3GlobalConfig.xLog = va_arg(ap, LOGFUNC_t); sqlite3GlobalConfig.pLogArg = va_arg(ap, void*); break; } /* EVIDENCE-OF: R-55548-33817 The compile-time setting for URI filenames ** can be changed at start-time using the ** sqlite3_config(SQLITE_CONFIG_URI,1) or ** sqlite3_config(SQLITE_CONFIG_URI,0) configuration calls. */ case SQLITE_CONFIG_URI: { /* EVIDENCE-OF: R-25451-61125 The SQLITE_CONFIG_URI option takes a single ** argument of type int. If non-zero, then URI handling is globally ** enabled. If the parameter is zero, then URI handling is globally ** disabled. */ sqlite3GlobalConfig.bOpenUri = va_arg(ap, int); break; } case SQLITE_CONFIG_COVERING_INDEX_SCAN: { /* EVIDENCE-OF: R-36592-02772 The SQLITE_CONFIG_COVERING_INDEX_SCAN ** option takes a single integer argument which is interpreted as a ** boolean in order to enable or disable the use of covering indices for |
︙ | ︙ | |||
966 967 968 969 970 971 972 | { SQLITE_DBCONFIG_WRITABLE_SCHEMA, SQLITE_WriteSchema| SQLITE_NoSchemaError }, { SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter }, { SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL }, { SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML }, { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, SQLITE_LegacyFileFmt }, { SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema }, | < < | 950 951 952 953 954 955 956 957 958 959 960 961 962 963 | { SQLITE_DBCONFIG_WRITABLE_SCHEMA, SQLITE_WriteSchema| SQLITE_NoSchemaError }, { SQLITE_DBCONFIG_LEGACY_ALTER_TABLE, SQLITE_LegacyAlter }, { SQLITE_DBCONFIG_DQS_DDL, SQLITE_DqsDDL }, { SQLITE_DBCONFIG_DQS_DML, SQLITE_DqsDML }, { SQLITE_DBCONFIG_LEGACY_FILE_FORMAT, SQLITE_LegacyFileFmt }, { SQLITE_DBCONFIG_TRUSTED_SCHEMA, SQLITE_TrustedSchema }, }; unsigned int i; rc = SQLITE_ERROR; /* IMP: R-42790-23372 */ for(i=0; i<ArraySize(aFlagOp); i++){ if( aFlagOp[i].op==op ){ int onoff = va_arg(ap, int); int *pRes = va_arg(ap, int*); |
︙ | ︙ | |||
2953 2954 2955 2956 2957 2958 2959 | const char *zVfs = zDefaultVfs; char *zFile; char c; int nUri = sqlite3Strlen30(zUri); assert( *pzErrMsg==0 ); | | | | | 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 | const char *zVfs = zDefaultVfs; char *zFile; char c; int nUri = sqlite3Strlen30(zUri); assert( *pzErrMsg==0 ); if( ((flags & SQLITE_OPEN_URI) /* IMP: R-48725-32206 */ || sqlite3GlobalConfig.bOpenUri) /* IMP: R-51689-46548 */ && nUri>=5 && memcmp(zUri, "file:", 5)==0 /* IMP: R-57884-37496 */ ){ char *zOpt; int eState; /* Parser state when parsing URI */ int iIn; /* Input character index */ int iOut = 0; /* Output character index */ u64 nByte = nUri+8; /* Bytes of space to allocate */ |
︙ | ︙ | |||
3362 3363 3364 3365 3366 3367 3368 | #endif #if defined(SQLITE_DEFAULT_DEFENSIVE) | SQLITE_Defensive #endif #if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE) | SQLITE_LegacyAlter #endif | < < < | 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 | #endif #if defined(SQLITE_DEFAULT_DEFENSIVE) | SQLITE_Defensive #endif #if defined(SQLITE_DEFAULT_LEGACY_ALTER_TABLE) | SQLITE_LegacyAlter #endif ; sqlite3HashInit(&db->aCollSeq); #ifndef SQLITE_OMIT_VIRTUALTABLE sqlite3HashInit(&db->aModule); #endif /* Add the default collation sequence BINARY. BINARY works for both UTF-8 |
︙ | ︙ | |||
3929 3930 3931 3932 3933 3934 3935 | int rc; pVfs = sqlite3_vfs_find(0); if( pVfs==0 ) return 0; /* This function works in milliseconds, but the underlying OsSleep() ** API uses microseconds. Hence the 1000's. */ | | | 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 | int rc; pVfs = sqlite3_vfs_find(0); if( pVfs==0 ) return 0; /* This function works in milliseconds, but the underlying OsSleep() ** API uses microseconds. Hence the 1000's. */ rc = (sqlite3OsSleep(pVfs, 1000*ms)/1000); return rc; } /* ** Enable or disable the extended result codes. */ int sqlite3_extended_result_codes(sqlite3 *db, int onoff){ |
︙ | ︙ |
Changes to src/msvc.h.
︙ | ︙ | |||
34 35 36 37 38 39 40 | #endif /* defined(_MSC_VER) */ #if defined(_MSC_VER) && !defined(_WIN64) #undef SQLITE_4_BYTE_ALIGNED_MALLOC #define SQLITE_4_BYTE_ALIGNED_MALLOC #endif /* defined(_MSC_VER) && !defined(_WIN64) */ | < < < < | 34 35 36 37 38 39 40 41 | #endif /* defined(_MSC_VER) */ #if defined(_MSC_VER) && !defined(_WIN64) #undef SQLITE_4_BYTE_ALIGNED_MALLOC #define SQLITE_4_BYTE_ALIGNED_MALLOC #endif /* defined(_MSC_VER) && !defined(_WIN64) */ #endif /* SQLITE_MSVC_H */ |
Changes to src/os_unix.c.
︙ | ︙ | |||
68 69 70 71 72 73 74 | # define SQLITE_ENABLE_LOCKING_STYLE 1 # else # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif #endif /* Use pread() and pwrite() if they are available */ | | | 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 | # define SQLITE_ENABLE_LOCKING_STYLE 1 # else # define SQLITE_ENABLE_LOCKING_STYLE 0 # endif #endif /* Use pread() and pwrite() if they are available */ #if defined(__APPLE__) # define HAVE_PREAD 1 # define HAVE_PWRITE 1 #endif #if defined(HAVE_PREAD64) && defined(HAVE_PWRITE64) # undef USE_PREAD # define USE_PREAD64 1 #elif defined(HAVE_PREAD) && defined(HAVE_PWRITE) |
︙ | ︙ | |||
91 92 93 94 95 96 97 | #include <sys/stat.h> /* amalgamator: keep */ #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> /* amalgamator: keep */ #include <time.h> #include <sys/time.h> /* amalgamator: keep */ #include <errno.h> | | < | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | #include <sys/stat.h> /* amalgamator: keep */ #include <fcntl.h> #include <sys/ioctl.h> #include <unistd.h> /* amalgamator: keep */ #include <time.h> #include <sys/time.h> /* amalgamator: keep */ #include <errno.h> #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 # include <sys/mman.h> #endif #if SQLITE_ENABLE_LOCKING_STYLE # include <sys/ioctl.h> # include <sys/file.h> # include <sys/param.h> |
︙ | ︙ | |||
180 181 182 183 184 185 186 | #define MAX_PATHNAME 512 /* ** Maximum supported symbolic links */ #define SQLITE_MAX_SYMLINKS 100 | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 | #define MAX_PATHNAME 512 /* ** Maximum supported symbolic links */ #define SQLITE_MAX_SYMLINKS 100 /* Always cast the getpid() return type for compatibility with ** kernel modules in VxWorks. */ #define osGetpid(X) (pid_t)getpid() /* ** Only set the lastErrno if the error code is a real error and not ** a normal expected return code of SQLITE_BUSY or SQLITE_OK */ #define IS_LOCK_ERROR(x) ((x != SQLITE_OK) && (x != SQLITE_BUSY)) |
︙ | ︙ | |||
491 492 493 494 495 496 497 | { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, #else { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\ aSyscall[13].pCurrent) | < < < < | 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | { "pwrite64", (sqlite3_syscall_ptr)pwrite64, 0 }, #else { "pwrite64", (sqlite3_syscall_ptr)0, 0 }, #endif #define osPwrite64 ((ssize_t(*)(int,const void*,size_t,off64_t))\ aSyscall[13].pCurrent) { "fchmod", (sqlite3_syscall_ptr)fchmod, 0 }, #define osFchmod ((int(*)(int,mode_t))aSyscall[14].pCurrent) #if defined(HAVE_POSIX_FALLOCATE) && HAVE_POSIX_FALLOCATE { "fallocate", (sqlite3_syscall_ptr)posix_fallocate, 0 }, #else { "fallocate", (sqlite3_syscall_ptr)0, 0 }, #endif |
︙ | ︙ | |||
531 532 533 534 535 536 537 | #if defined(HAVE_FCHOWN) { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, #else { "geteuid", (sqlite3_syscall_ptr)0, 0 }, #endif #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) | | < | < | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | #if defined(HAVE_FCHOWN) { "geteuid", (sqlite3_syscall_ptr)geteuid, 0 }, #else { "geteuid", (sqlite3_syscall_ptr)0, 0 }, #endif #define osGeteuid ((uid_t(*)(void))aSyscall[21].pCurrent) #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 { "mmap", (sqlite3_syscall_ptr)mmap, 0 }, #else { "mmap", (sqlite3_syscall_ptr)0, 0 }, #endif #define osMmap ((void*(*)(void*,size_t,int,int,int,off_t))aSyscall[22].pCurrent) #if !defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0 { "munmap", (sqlite3_syscall_ptr)munmap, 0 }, #else { "munmap", (sqlite3_syscall_ptr)0, 0 }, #endif #define osMunmap ((int(*)(void*,size_t))aSyscall[23].pCurrent) #if HAVE_MREMAP && (!defined(SQLITE_OMIT_WAL) || SQLITE_MAX_MMAP_SIZE>0) |
︙ | ︙ | |||
3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 | ** division). Those methods that are common to all locking modes ** are gather together into this division. */ /* ** Seek to the offset passed as the second argument, then read cnt ** bytes into pBuf. Return the number of bytes actually read. ** ** To avoid stomping the errno value on a failed read the lastErrno value ** is set before returning. */ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ int got; int prior = 0; | > > > > > > | 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 | ** division). Those methods that are common to all locking modes ** are gather together into this division. */ /* ** Seek to the offset passed as the second argument, then read cnt ** bytes into pBuf. Return the number of bytes actually read. ** ** NB: If you define USE_PREAD or USE_PREAD64, then it might also ** be necessary to define _XOPEN_SOURCE to be 500. This varies from ** one system to another. Since SQLite does not define USE_PREAD ** in any form by default, we will not attempt to define _XOPEN_SOURCE. ** See tickets #2741 and #2681. ** ** To avoid stomping the errno value on a failed read the lastErrno value ** is set before returning. */ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){ int got; int prior = 0; |
︙ | ︙ |
Changes to src/os_win.c.
︙ | ︙ | |||
5193 5194 5195 5196 5197 5198 5199 | dwShareMode, dwCreationDisposition, &extendedParameters); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); | | | | | 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 | dwShareMode, dwCreationDisposition, &extendedParameters); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); #else do{ h = osCreateFileW((LPCWSTR)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); #endif } #ifdef SQLITE_WIN32_HAS_ANSI else{ do{ h = osCreateFileA((LPCSTR)zConverted, dwDesiredAccess, dwShareMode, NULL, dwCreationDisposition, dwFlagsAndAttributes, NULL); if( h!=INVALID_HANDLE_VALUE ) break; if( isReadWrite ){ int rc2, isRO = 0; sqlite3BeginBenignMalloc(); rc2 = winAccess(pVfs, zName, SQLITE_ACCESS_READ, &isRO); sqlite3EndBenignMalloc(); if( rc2==SQLITE_OK && isRO ) break; } }while( winRetryIoerr(&cnt, &lastErrno) ); } #endif winLogIoerr(cnt, __LINE__); |
︙ | ︙ | |||
5453 5454 5455 5456 5457 5458 5459 | void *zConverted; UNUSED_PARAMETER(pVfs); SimulateIOError( return SQLITE_IOERR_ACCESS; ); OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", zFilename, flags, pResOut)); | < < < < < < < | 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 | void *zConverted; UNUSED_PARAMETER(pVfs); SimulateIOError( return SQLITE_IOERR_ACCESS; ); OSTRACE(("ACCESS name=%s, flags=%x, pResOut=%p\n", zFilename, flags, pResOut)); zConverted = winConvertFromUtf8Filename(zFilename); if( zConverted==0 ){ OSTRACE(("ACCESS name=%s, rc=SQLITE_IOERR_NOMEM\n", zFilename)); return SQLITE_IOERR_NOMEM_BKPT; } if( osIsNT() ){ int cnt = 0; |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
2591 2592 2593 2594 2595 2596 2597 | ** If successful, return SQLITE_OK. If an IO error occurs while modifying ** the database file, return the error code to the caller. */ static int pager_truncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; assert( pPager->eState!=PAGER_ERROR ); assert( pPager->eState!=PAGER_READER ); | < < | 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 | ** If successful, return SQLITE_OK. If an IO error occurs while modifying ** the database file, return the error code to the caller. */ static int pager_truncate(Pager *pPager, Pgno nPage){ int rc = SQLITE_OK; assert( pPager->eState!=PAGER_ERROR ); assert( pPager->eState!=PAGER_READER ); if( isOpen(pPager->fd) && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN) ){ i64 currentSize, newSize; int szPage = pPager->pageSize; assert( pPager->eLock==EXCLUSIVE_LOCK ); |
︙ | ︙ | |||
3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 | ** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the ** synchronous=FULL versus synchronous=NORMAL setting determines when ** the xSync primitive is called and is relevant to all platforms. ** ** Numeric values associated with these states are OFF==1, NORMAL=2, ** and FULL=3. */ void sqlite3PagerSetFlags( Pager *pPager, /* The pager to set safety level for */ unsigned pgFlags /* Various flags */ ){ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; if( pPager->tempFile ){ pPager->noSync = 1; | > | 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 | ** and SQLITE_SYNC_NORMAL on platforms other than MacOSX. But the ** synchronous=FULL versus synchronous=NORMAL setting determines when ** the xSync primitive is called and is relevant to all platforms. ** ** Numeric values associated with these states are OFF==1, NORMAL=2, ** and FULL=3. */ #ifndef SQLITE_OMIT_PAGER_PRAGMAS void sqlite3PagerSetFlags( Pager *pPager, /* The pager to set safety level for */ unsigned pgFlags /* Various flags */ ){ unsigned level = pgFlags & PAGER_SYNCHRONOUS_MASK; if( pPager->tempFile ){ pPager->noSync = 1; |
︙ | ︙ | |||
3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 | } if( pgFlags & PAGER_CACHESPILL ){ pPager->doNotSpill &= ~SPILLFLAG_OFF; }else{ pPager->doNotSpill |= SPILLFLAG_OFF; } } /* ** The following global variable is incremented whenever the library ** attempts to open a temporary file. This information is used for ** testing and analysis only. */ #ifdef SQLITE_TEST | > | 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 | } if( pgFlags & PAGER_CACHESPILL ){ pPager->doNotSpill &= ~SPILLFLAG_OFF; }else{ pPager->doNotSpill |= SPILLFLAG_OFF; } } #endif /* ** The following global variable is incremented whenever the library ** attempts to open a temporary file. This information is used for ** testing and analysis only. */ #ifdef SQLITE_TEST |
︙ | ︙ | |||
4988 4989 4990 4991 4992 4993 4994 | || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); pPager->exclusiveMode = (u8)tempFile; pPager->changeCountDone = pPager->tempFile; pPager->memDb = (u8)memDb; pPager->readOnly = (u8)readOnly; assert( useJournal || pPager->tempFile ); | > | > > > > > > > > > > | 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 | || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE ); assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 ); pPager->exclusiveMode = (u8)tempFile; pPager->changeCountDone = pPager->tempFile; pPager->memDb = (u8)memDb; pPager->readOnly = (u8)readOnly; assert( useJournal || pPager->tempFile ); pPager->noSync = pPager->tempFile; if( pPager->noSync ){ assert( pPager->fullSync==0 ); assert( pPager->extraSync==0 ); assert( pPager->syncFlags==0 ); assert( pPager->walSyncFlags==0 ); }else{ pPager->fullSync = 1; pPager->extraSync = 0; pPager->syncFlags = SQLITE_SYNC_NORMAL; pPager->walSyncFlags = SQLITE_SYNC_NORMAL | (SQLITE_SYNC_NORMAL<<2); } /* pPager->pFirst = 0; */ /* pPager->pFirstSynced = 0; */ /* pPager->pLast = 0; */ pPager->nExtra = (u16)nExtra; pPager->journalSizeLimit = SQLITE_DEFAULT_JOURNAL_SIZE_LIMIT; assert( isOpen(pPager->fd) || tempFile ); setSectorSize(pPager); |
︙ | ︙ | |||
5517 5518 5519 5520 5521 5522 5523 | pPg->pPager = pPager; assert( !isOpen(pPager->fd) || !MEMDB ); if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){ if( pgno>pPager->mxPgno ){ rc = SQLITE_FULL; | < < < < | 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 | pPg->pPager = pPager; assert( !isOpen(pPager->fd) || !MEMDB ); if( !isOpen(pPager->fd) || pPager->dbSize<pgno || noContent ){ if( pgno>pPager->mxPgno ){ rc = SQLITE_FULL; goto pager_acquire_err; } if( noContent ){ /* Failure to set the bits in the InJournal bit-vectors is benign. ** It merely means that we might do some extra work to journal a ** page that does not need to be journaled. Nevertheless, be sure ** to test the case where a malloc error occurs while trying to set |
︙ | ︙ | |||
5685 5686 5687 5688 5689 5690 5691 | if( pPage==0 ) return 0; return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); } /* ** Release a page reference. ** | | | | < < | | 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 | if( pPage==0 ) return 0; return sqlite3PcacheFetchFinish(pPager->pPCache, pgno, pPage); } /* ** Release a page reference. ** ** The sqlite3PagerUnref() and sqlite3PagerUnrefNotNull() may only be ** used if we know that the page being released is not the last page. ** The btree layer always holds page1 open until the end, so these first ** to routines can be used to release any page other than BtShared.pPage1. ** ** Use sqlite3PagerUnrefPageOne() to release page1. This latter routine ** checks the total number of outstanding pages and if the number of ** pages reaches zero it drops the database lock. */ void sqlite3PagerUnrefNotNull(DbPage *pPg){ TESTONLY( Pager *pPager = pPg->pPager; ) assert( pPg!=0 ); if( pPg->flags & PGHDR_MMAP ){ assert( pPg->pgno!=1 ); /* Page1 is never memory mapped */ pagerReleaseMapPage(pPg); }else{ sqlite3PcacheRelease(pPg); } /* Do not use this routine to release the last reference to page1 */ assert( sqlite3PcacheRefCount(pPager->pPCache)>0 ); } void sqlite3PagerUnref(DbPage *pPg){ if( pPg ) sqlite3PagerUnrefNotNull(pPg); } void sqlite3PagerUnrefPageOne(DbPage *pPg){ Pager *pPager; assert( pPg!=0 ); |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
291 292 293 294 295 296 297 298 299 300 301 302 | %right BITNOT. %nonassoc ON. // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %token_class id ID|INDEXED. // And "ids" is an identifer-or-string. // %token_class ids ID|STRING. | > < < < < | > | 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 | %right BITNOT. %nonassoc ON. // An IDENTIFIER can be a generic identifier, or one of several // keywords. Any non-standard keyword can also be an identifier. // %token_class id ID|INDEXED. // And "ids" is an identifer-or-string. // %token_class ids ID|STRING. // The name of a column or table can be any of the following: // %type nm {Token} nm(A) ::= id(A). nm(A) ::= STRING(A). nm(A) ::= JOIN_KW(A). // A typetoken is really zero or more tokens that form a type name such // as can be found after the column name in a CREATE TABLE statement. // Multiple tokens are concatenated to form the value of the typetoken. // %type typetoken {Token} typetoken(A) ::= . {A.n = 0; A.z = 0;} |
︙ | ︙ | |||
711 712 713 714 715 716 717 | %ifndef SQLITE_OMIT_SUBQUERY seltablist(A) ::= stl_prefix(A) LP select(S) RP as(Z) on_using(N). { A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N); } seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP as(Z) on_using(N). { if( A==0 && Z.n==0 && N.pOn==0 && N.pUsing==0 ){ A = F; | | | 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 | %ifndef SQLITE_OMIT_SUBQUERY seltablist(A) ::= stl_prefix(A) LP select(S) RP as(Z) on_using(N). { A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,S,&N); } seltablist(A) ::= stl_prefix(A) LP seltablist(F) RP as(Z) on_using(N). { if( A==0 && Z.n==0 && N.pOn==0 && N.pUsing==0 ){ A = F; }else if( F->nSrc==1 ){ A = sqlite3SrcListAppendFromTerm(pParse,A,0,0,&Z,0,&N); if( A ){ SrcItem *pNew = &A->a[A->nSrc-1]; SrcItem *pOld = F->a; pNew->zName = pOld->zName; pNew->zDatabase = pOld->zDatabase; pNew->pSelect = pOld->pSelect; |
︙ | ︙ | |||
1082 1083 1084 1085 1086 1087 1088 | return p; } } expr(A) ::= term(A). expr(A) ::= LP expr(X) RP. {A = X;} | | > | 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 | return p; } } expr(A) ::= term(A). expr(A) ::= LP expr(X) RP. {A = X;} expr(A) ::= id(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} expr(A) ::= JOIN_KW(X). {A=tokenExpr(pParse,TK_ID,X); /*A-overwrites-X*/} expr(A) ::= nm(X) DOT nm(Y). { Expr *temp1 = tokenExpr(pParse,TK_ID,X); Expr *temp2 = tokenExpr(pParse,TK_ID,Y); A = sqlite3PExpr(pParse, TK_DOT, temp1, temp2); } expr(A) ::= nm(X) DOT nm(Y) DOT nm(Z). { Expr *temp1 = tokenExpr(pParse,TK_ID,X); |
︙ | ︙ | |||
1135 1136 1137 1138 1139 1140 1141 | expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. { A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1); sqlite3ExprAttachSubtrees(pParse->db, A, E, 0); } %endif SQLITE_OMIT_CAST | | | | | | 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 | expr(A) ::= CAST LP expr(E) AS typetoken(T) RP. { A = sqlite3ExprAlloc(pParse->db, TK_CAST, &T, 1); sqlite3ExprAttachSubtrees(pParse->db, A, E, 0); } %endif SQLITE_OMIT_CAST expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP. { A = sqlite3ExprFunction(pParse, Y, &X, D); } expr(A) ::= id(X) LP STAR RP. { A = sqlite3ExprFunction(pParse, 0, &X, 0); } %ifndef SQLITE_OMIT_WINDOWFUNC expr(A) ::= id(X) LP distinct(D) exprlist(Y) RP filter_over(Z). { A = sqlite3ExprFunction(pParse, Y, &X, D); sqlite3WindowAttach(pParse, A, Z); } expr(A) ::= id(X) LP STAR RP filter_over(Z). { A = sqlite3ExprFunction(pParse, 0, &X, 0); sqlite3WindowAttach(pParse, A, Z); } %endif term(A) ::= CTIME_KW(OP). { A = sqlite3ExprFunction(pParse, 0, &OP, 0); |
︙ | ︙ | |||
1299 1300 1301 1302 1303 1304 1305 | }else{ Expr *pRHS = Y->a[0].pExpr; if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){ Y->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, Y); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); A = sqlite3PExpr(pParse, TK_EQ, A, pRHS); | < < < < < | 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 | }else{ Expr *pRHS = Y->a[0].pExpr; if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && A->op!=TK_VECTOR ){ Y->a[0].pExpr = 0; sqlite3ExprListDelete(pParse->db, Y); pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0); A = sqlite3PExpr(pParse, TK_EQ, A, pRHS); }else{ A = sqlite3PExpr(pParse, TK_IN, A, 0); if( A==0 ){ sqlite3ExprListDelete(pParse->db, Y); }else if( A->pLeft->op==TK_VECTOR ){ int nExpr = A->pLeft->x.pList->nExpr; Select *pSelectRHS = sqlite3ExprListToValues(pParse, nExpr, Y); |
︙ | ︙ | |||
1374 1375 1376 1377 1378 1379 1380 | } %type case_else {Expr*} %destructor case_else {sqlite3ExprDelete(pParse->db, $$);} case_else(A) ::= ELSE expr(X). {A = X;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} %destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} | | | 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 | } %type case_else {Expr*} %destructor case_else {sqlite3ExprDelete(pParse->db, $$);} case_else(A) ::= ELSE expr(X). {A = X;} case_else(A) ::= . {A = 0;} %type case_operand {Expr*} %destructor case_operand {sqlite3ExprDelete(pParse->db, $$);} case_operand(A) ::= expr(X). {A = X; /*A-overwrites-X*/} case_operand(A) ::= . {A = 0;} %type exprlist {ExprList*} %destructor exprlist {sqlite3ExprListDelete(pParse->db, $$);} %type nexprlist {ExprList*} %destructor nexprlist {sqlite3ExprListDelete(pParse->db, $$);} |
︙ | ︙ |
Changes to src/pcache.c.
︙ | ︙ | |||
37 38 39 40 41 42 43 | ** clear PGHDR_NEED_SYNC flag or to a page that is older than this one ** (so that the right page to eject can be found by following pDirtyPrev ** pointers). */ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ | | | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | ** clear PGHDR_NEED_SYNC flag or to a page that is older than this one ** (so that the right page to eject can be found by following pDirtyPrev ** pointers). */ struct PCache { PgHdr *pDirty, *pDirtyTail; /* List of dirty pages in LRU order */ PgHdr *pSynced; /* Last synced page in dirty page list */ int nRefSum; /* Sum of ref counts over all pages */ int szCache; /* Configured cache size */ int szSpill; /* Size before spilling occurs */ int szPage; /* Size of every page in this cache */ int szExtra; /* Size of extra space for each page */ u8 bPurgeable; /* True if pages are on backing store */ u8 eCreate; /* eCreate value for for xFetch() */ int (*xStress)(void*,PgHdr*); /* Call to try make a page clean */ |
︙ | ︙ | |||
66 67 68 69 70 71 72 | int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */ int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */ # define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;} static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){ PgHdr *pPg; unsigned char *a; int j; | < < < | | | | | < > | | 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 | int sqlite3PcacheTrace = 2; /* 0: off 1: simple 2: cache dumps */ int sqlite3PcacheMxDump = 9999; /* Max cache entries for pcacheDump() */ # define pcacheTrace(X) if(sqlite3PcacheTrace){sqlite3DebugPrintf X;} static void pcachePageTrace(int i, sqlite3_pcache_page *pLower){ PgHdr *pPg; unsigned char *a; int j; pPg = (PgHdr*)pLower->pExtra; printf("%3d: nRef %2d flgs %02x data ", i, pPg->nRef, pPg->flags); a = (unsigned char *)pLower->pBuf; for(j=0; j<12; j++) printf("%02x", a[j]); printf(" ptr %p\n", pPg); } static void pcacheDump(PCache *pCache){ int N; int i; sqlite3_pcache_page *pLower; if( sqlite3PcacheTrace<2 ) return; if( pCache->pCache==0 ) return; N = sqlite3PcachePagecount(pCache); if( N>sqlite3PcacheMxDump ) N = sqlite3PcacheMxDump; for(i=1; i<=N; i++){ pLower = sqlite3GlobalConfig.pcache2.xFetch(pCache->pCache, i, 0); if( pLower==0 ) continue; pcachePageTrace(i, pLower); if( ((PgHdr*)pLower)->pPage==0 ){ sqlite3GlobalConfig.pcache2.xUnpin(pCache->pCache, pLower, 0); } } } #else # define pcacheTrace(X) # define pcachePageTrace(PGNO, X) |
︙ | ︙ | |||
814 815 816 817 818 819 820 | /* ** Return the total number of references to all pages held by the cache. ** ** This is not the total number of pages referenced, but the sum of the ** reference count for all pages. */ | | | | 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 | /* ** Return the total number of references to all pages held by the cache. ** ** This is not the total number of pages referenced, but the sum of the ** reference count for all pages. */ int sqlite3PcacheRefCount(PCache *pCache){ return pCache->nRefSum; } /* ** Return the number of references to the page supplied as an argument. */ int sqlite3PcachePageRefcount(PgHdr *p){ return p->nRef; } /* ** Return the total number of pages in the cache. */ int sqlite3PcachePagecount(PCache *pCache){ |
︙ | ︙ |
Changes to src/pcache.h.
︙ | ︙ | |||
36 37 38 39 40 41 42 | u16 flags; /* PGHDR flags defined below */ /********************************************************************** ** Elements above, except pCache, are public. All that follow are ** private to pcache.c and should not be accessed by other modules. ** pCache is grouped with the public elements for efficiency. */ | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | u16 flags; /* PGHDR flags defined below */ /********************************************************************** ** Elements above, except pCache, are public. All that follow are ** private to pcache.c and should not be accessed by other modules. ** pCache is grouped with the public elements for efficiency. */ i16 nRef; /* Number of users of this page */ PgHdr *pDirtyNext; /* Next element in list of dirty pages */ PgHdr *pDirtyPrev; /* Previous element in list of dirty pages */ /* NB: pDirtyNext and pDirtyPrev are undefined if the ** PgHdr object is not dirty */ }; /* Bit values for PgHdr.flags */ |
︙ | ︙ | |||
117 118 119 120 121 122 123 | /* Clear flags from pages of the page cache */ void sqlite3PcacheClearSyncFlags(PCache *); /* Discard the contents of the cache */ void sqlite3PcacheClear(PCache*); /* Return the total number of outstanding page references */ | | | | 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | /* Clear flags from pages of the page cache */ void sqlite3PcacheClearSyncFlags(PCache *); /* Discard the contents of the cache */ void sqlite3PcacheClear(PCache*); /* Return the total number of outstanding page references */ int sqlite3PcacheRefCount(PCache*); /* Increment the reference count of an existing page */ void sqlite3PcacheRef(PgHdr*); int sqlite3PcachePageRefcount(PgHdr*); /* Return the total number of pages stored in the cache */ int sqlite3PcachePagecount(PCache*); #if defined(SQLITE_CHECK_PAGES) || defined(SQLITE_DEBUG) /* Iterate through all dirty pages currently stored in the cache. This ** interface is only available if SQLITE_CHECK_PAGES is defined when the |
︙ | ︙ |
Changes to src/pragma.c.
︙ | ︙ | |||
1521 1522 1523 1524 1525 1526 1527 | k = sqliteHashNext(k); } if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); | | | 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 | k = sqliteHashNext(k); } if( pTab==0 || !IsOrdinaryTable(pTab) || pTab->u.tab.pFKey==0 ) continue; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); zDb = db->aDb[iDb].zDbSName; sqlite3CodeVerifySchema(pParse, iDb); sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); if( pTab->nCol+regRow>pParse->nMem ) pParse->nMem = pTab->nCol + regRow; sqlite3OpenTable(pParse, 0, iDb, pTab, OP_OpenRead); sqlite3VdbeLoadString(v, regResult, pTab->zName); assert( IsOrdinaryTable(pTab) ); for(i=1, pFK=pTab->u.tab.pFKey; pFK; i++, pFK=pFK->pNextFrom){ pParent = sqlite3FindTable(db, pFK->zTo, zDb); if( pParent==0 ) continue; pIdx = 0; |
︙ | ︙ | |||
1562 1563 1564 1565 1566 1567 1568 | } addrOk = sqlite3VdbeMakeLabel(pParse); /* Generate code to read the child key values into registers ** regRow..regRow+n. If any of the child key values are NULL, this ** row cannot cause an FK violation. Jump directly to addrOk in ** this case. */ | | | 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 | } addrOk = sqlite3VdbeMakeLabel(pParse); /* Generate code to read the child key values into registers ** regRow..regRow+n. If any of the child key values are NULL, this ** row cannot cause an FK violation. Jump directly to addrOk in ** this case. */ if( regRow+pFK->nCol>pParse->nMem ) pParse->nMem = regRow+pFK->nCol; for(j=0; j<pFK->nCol; j++){ int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom; sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j); sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v); } /* Generate code to query the parent index for a matching parent |
︙ | ︙ | |||
1691 1692 1693 1694 1695 1696 1697 | int cnt = 0; /* Number of entries in aRoot[] */ int mxIdx = 0; /* Maximum number of indexes for any table */ if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; sqlite3CodeVerifySchema(pParse, i); | < | 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 | int cnt = 0; /* Number of entries in aRoot[] */ int mxIdx = 0; /* Maximum number of indexes for any table */ if( OMIT_TEMPDB && i==1 ) continue; if( iDb>=0 && i!=iDb ) continue; sqlite3CodeVerifySchema(pParse, i); /* Do an integrity check of the B-Tree ** ** Begin by finding the root pages numbers ** for all tables and indices in the database. */ assert( sqlite3SchemaMutexHeld(db, i, 0) ); |
︙ | ︙ | |||
1727 1728 1729 1730 1731 1732 1733 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ aRoot[++cnt] = pIdx->tnum; } } aRoot[0] = cnt; /* Make sure sufficient number of registers have been allocated */ | | | 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 | for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ aRoot[++cnt] = pIdx->tnum; } } aRoot[0] = cnt; /* Make sure sufficient number of registers have been allocated */ pParse->nMem = MAX( pParse->nMem, 8+mxIdx ); sqlite3ClearTempRegCache(pParse); /* Do the b-tree integrity checks */ sqlite3VdbeAddOp4(v, OP_IntegrityCk, 2, cnt, 1, (char*)aRoot,P4_INTARRAY); sqlite3VdbeChangeP5(v, (u8)i); addr = sqlite3VdbeAddOp1(v, OP_IsNull, 2); VdbeCoverage(v); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, |
︙ | ︙ | |||
1877 1878 1879 1880 1881 1882 1883 | } } labelError = sqlite3VdbeMakeLabel(pParse); labelOk = sqlite3VdbeMakeLabel(pParse); if( pCol->notNull ){ /* (1) NOT NULL columns may not contain a NULL */ | < < < | < < < < < < < < < | < < | 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 | } } labelError = sqlite3VdbeMakeLabel(pParse); labelOk = sqlite3VdbeMakeLabel(pParse); if( pCol->notNull ){ /* (1) NOT NULL columns may not contain a NULL */ int jmp2 = sqlite3VdbeAddOp4Int(v, OP_IsType, p1, labelOk, p3, p4); sqlite3VdbeChangeP5(v, 0x0f); VdbeCoverage(v); zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName, pCol->zCnName); sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC); if( doTypeCheck ){ sqlite3VdbeGoto(v, labelError); sqlite3VdbeJumpHere(v, jmp2); }else{ /* VDBE byte code will fall thru */ } } if( bStrict && doTypeCheck ){ /* (2) Datatype must be exact for non-ANY columns in STRICT tables*/ static unsigned char aStdTypeMask[] = { |
︙ | ︙ | |||
1999 2000 2001 2002 2003 2004 2005 | sqlite3VdbeLoadString(v, 4, " missing from index "); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); jmp4 = integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, jmp2); | < < < < < < < < < < < < < < < < < | 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 | sqlite3VdbeLoadString(v, 4, " missing from index "); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName); sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3); jmp4 = integrityCheckResultRow(v); sqlite3VdbeJumpHere(v, jmp2); /* Any indexed columns with non-BINARY collations must still hold ** the exact same text value as the table. */ label6 = 0; for(kk=0; kk<pIdx->nKeyCol; kk++){ if( pIdx->azColl[kk]==sqlite3StrBINARY ) continue; if( label6==0 ) label6 = sqlite3VdbeMakeLabel(pParse); sqlite3VdbeAddOp3(v, OP_Column, iIdxCur+j, kk, 3); |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
302 303 304 305 306 307 308 | #ifndef SQLITE_OMIT_UTF16 /* If opening the main database, set ENC(db). */ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; if( encoding==0 ) encoding = SQLITE_UTF8; #else encoding = SQLITE_UTF8; #endif | | < < | 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | #ifndef SQLITE_OMIT_UTF16 /* If opening the main database, set ENC(db). */ encoding = (u8)meta[BTREE_TEXT_ENCODING-1] & 3; if( encoding==0 ) encoding = SQLITE_UTF8; #else encoding = SQLITE_UTF8; #endif if( db->nVdbeActive>0 && encoding!=ENC(db) ){ rc = SQLITE_LOCKED; goto initone_error_out; }else{ sqlite3SetTextEncoding(db, encoding); } }else{ /* If opening an attached database, the encoding much match ENC(db) */ |
︙ | ︙ | |||
698 699 700 701 702 703 704 | memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ); memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); sParse.pOuterParse = db->pParse; db->pParse = &sParse; sParse.db = db; sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); | < | < < < | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 | memset(PARSE_HDR(&sParse), 0, PARSE_HDR_SZ); memset(PARSE_TAIL(&sParse), 0, PARSE_TAIL_SZ); sParse.pOuterParse = db->pParse; db->pParse = &sParse; sParse.db = db; sParse.pReprepare = pReprepare; assert( ppStmt && *ppStmt==0 ); if( db->mallocFailed ) sqlite3ErrorMsg(&sParse, "out of memory"); assert( sqlite3_mutex_held(db->mutex) ); /* For a long-term use prepared statement avoid the use of ** lookaside memory. */ if( prepFlags & SQLITE_PREPARE_PERSISTENT ){ sParse.disableLookaside++; |
︙ | ︙ |
Changes to src/printf.c.
︙ | ︙ | |||
138 139 140 141 142 143 144 | d = digit; digit += '0'; *val = (*val - d)*10.0; return (char)digit; } #endif /* SQLITE_OMIT_FLOATING_POINT */ | < < < < < < < < < < < < < < | 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | d = digit; digit += '0'; *val = (*val - d)*10.0; return (char)digit; } #endif /* SQLITE_OMIT_FLOATING_POINT */ /* ** Set the StrAccum object to an error mode. */ void sqlite3StrAccumSetError(StrAccum *p, u8 eError){ assert( eError==SQLITE_NOMEM || eError==SQLITE_TOOBIG ); p->accError = eError; if( p->mxAlloc ) sqlite3_str_reset(p); |
︙ | ︙ | |||
244 245 246 247 248 249 250 | etByte done; /* Loop termination flag */ etByte cThousand; /* Thousands separator for %d and %u */ etByte xtype = etINVALID; /* Conversion paradigm */ u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ | < < | 230 231 232 233 234 235 236 237 238 239 240 241 242 243 | etByte done; /* Loop termination flag */ etByte cThousand; /* Thousands separator for %d and %u */ etByte xtype = etINVALID; /* Conversion paradigm */ u8 bArgList; /* True for SQLITE_PRINTF_SQLFUNC */ char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */ sqlite_uint64 longvalue; /* Value for integer types */ LONGDOUBLE_TYPE realvalue; /* Value for real types */ const et_info *infop; /* Pointer to the appropriate info structure */ char *zOut; /* Rendering buffer */ int nOut; /* Size of the rendering buffer */ char *zExtra = 0; /* Malloced memory used by some conversion */ #ifndef SQLITE_OMIT_FLOATING_POINT int exp, e2; /* exponent of real numbers */ int nsd; /* Number of significant digits returned */ |
︙ | ︙ | |||
552 553 554 555 556 557 558 | #endif if( realvalue<0.0 ){ realvalue = -realvalue; prefix = '-'; }else{ prefix = flag_prefix; } | < < < < < < < < < < < < < < < | | | | | | | | | | | | > > | < < < < | | < | | < < | | | | | | | | | < < < < | | | | | | | < < < < < < | > > > > < < > < < < < < | < < < < | < | 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 | #endif if( realvalue<0.0 ){ realvalue = -realvalue; prefix = '-'; }else{ prefix = flag_prefix; } if( xtype==etGENERIC && precision>0 ) precision--; testcase( precision>0xfff ); idx = precision & 0xfff; rounder = arRound[idx%10]; while( idx>=10 ){ rounder *= 1.0e-10; idx -= 10; } if( xtype==etFLOAT ){ double rx = (double)realvalue; sqlite3_uint64 u; int ex; memcpy(&u, &rx, sizeof(u)); ex = -1023 + (int)((u>>52)&0x7ff); if( precision+(ex/3) < 15 ) rounder += realvalue*3e-16; realvalue += rounder; } /* Normalize realvalue to within 10.0 > realvalue >= 1.0 */ exp = 0; if( sqlite3IsNaN((double)realvalue) ){ bufpt = "NaN"; length = 3; break; } if( realvalue>0.0 ){ LONGDOUBLE_TYPE scale = 1.0; while( realvalue>=1e100*scale && exp<=350 ){ scale *= 1e100;exp+=100;} while( realvalue>=1e10*scale && exp<=350 ){ scale *= 1e10; exp+=10; } while( realvalue>=10.0*scale && exp<=350 ){ scale *= 10.0; exp++; } realvalue /= scale; while( realvalue<1e-8 ){ realvalue *= 1e8; exp-=8; } while( realvalue<1.0 ){ realvalue *= 10.0; exp--; } if( exp>350 ){ bufpt = buf; buf[0] = prefix; memcpy(buf+(prefix!=0),"Inf",4); length = 3+(prefix!=0); break; } } bufpt = buf; /* ** If the field type is etGENERIC, then convert to either etEXP ** or etFLOAT, as appropriate. */ if( xtype!=etFLOAT ){ realvalue += rounder; if( realvalue>=10.0 ){ realvalue *= 0.1; exp++; } } if( xtype==etGENERIC ){ flag_rtz = !flag_alternateform; if( exp<-4 || exp>precision ){ xtype = etEXP; }else{ precision = precision - exp; xtype = etFLOAT; } }else{ flag_rtz = flag_altform2; } if( xtype==etEXP ){ e2 = 0; }else{ e2 = exp; } { i64 szBufNeeded; /* Size of a temporary buffer needed */ szBufNeeded = MAX(e2,0)+(i64)precision+(i64)width+15; if( szBufNeeded > etBUFSIZE ){ bufpt = zExtra = printfTempBuf(pAccum, szBufNeeded); if( bufpt==0 ) return; } } zOut = bufpt; nsd = 16 + flag_altform2*10; flag_dp = (precision>0 ?1:0) | flag_alternateform | flag_altform2; /* The sign in front of the number */ if( prefix ){ *(bufpt++) = prefix; } /* Digits prior to the decimal point */ if( e2<0 ){ *(bufpt++) = '0'; }else{ for(; e2>=0; e2--){ *(bufpt++) = et_getdigit(&realvalue,&nsd); } } /* The decimal point */ if( flag_dp ){ *(bufpt++) = '.'; } /* "0" digits after the decimal point but before the first ** significant digit of the number */ for(e2++; e2<0; precision--, e2++){ assert( precision>0 ); *(bufpt++) = '0'; } /* Significant digits after the decimal point */ while( (precision--)>0 ){ *(bufpt++) = et_getdigit(&realvalue,&nsd); } /* Remove trailing zeros and the "." if no digits follow the "." */ if( flag_rtz && flag_dp ){ while( bufpt[-1]=='0' ) *(--bufpt) = 0; assert( bufpt>zOut ); if( bufpt[-1]=='.' ){ if( flag_altform2 ){ |
︙ | ︙ | |||
1367 1368 1369 1370 1371 1372 1373 | #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3_str_vappendf(&acc, zFormat, ap); zBuf[acc.nChar] = 0; return zBuf; } char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ | | < < < < < < < < < | < | | 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 | #endif sqlite3StrAccumInit(&acc, 0, zBuf, n, 0); sqlite3_str_vappendf(&acc, zFormat, ap); zBuf[acc.nChar] = 0; return zBuf; } char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){ char *z; va_list ap; va_start(ap,zFormat); z = sqlite3_vsnprintf(n, zBuf, zFormat, ap); va_end(ap); return z; } /* ** This is the routine that actually formats the sqlite3_log() message. ** We house it in a separate routine from sqlite3_log() to avoid using ** stack space on small-stack systems when logging is disabled. ** |
︙ | ︙ |
Changes to src/resolve.c.
︙ | ︙ | |||
463 464 465 466 467 468 469 | pTab = 0; #ifndef SQLITE_OMIT_TRIGGER if( pParse->pTriggerTab!=0 ){ int op = pParse->eTriggerOp; assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); if( pParse->bReturning ){ if( (pNC->ncFlags & NC_UBaseReg)!=0 | < | | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | pTab = 0; #ifndef SQLITE_OMIT_TRIGGER if( pParse->pTriggerTab!=0 ){ int op = pParse->eTriggerOp; assert( op==TK_DELETE || op==TK_UPDATE || op==TK_INSERT ); if( pParse->bReturning ){ if( (pNC->ncFlags & NC_UBaseReg)!=0 && (zTab==0 || sqlite3StrICmp(zTab,pParse->pTriggerTab->zName)==0) ){ pExpr->iTable = op!=TK_DELETE; pTab = pParse->pTriggerTab; } }else if( op!=TK_DELETE && zTab && sqlite3StrICmp("new",zTab) == 0 ){ pExpr->iTable = 1; pTab = pParse->pTriggerTab; |
︙ | ︙ | |||
944 945 946 947 948 949 950 | for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ anRef[i] = p->nRef; } sqlite3WalkExpr(pWalker, pExpr->pLeft); if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ testcase( ExprHasProperty(pExpr, EP_OuterON) ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); | | | > > | > | > | 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 | for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ anRef[i] = p->nRef; } sqlite3WalkExpr(pWalker, pExpr->pLeft); if( 0==sqlite3ExprCanBeNull(pExpr->pLeft) && !IN_RENAME_OBJECT ){ testcase( ExprHasProperty(pExpr, EP_OuterON) ); assert( !ExprHasProperty(pExpr, EP_IntValue) ); if( pExpr->op==TK_NOTNULL ){ pExpr->u.zToken = "true"; ExprSetProperty(pExpr, EP_IsTrue); }else{ pExpr->u.zToken = "false"; ExprSetProperty(pExpr, EP_IsFalse); } pExpr->op = TK_TRUEFALSE; for(i=0, p=pNC; p && i<ArraySize(anRef); p=p->pNext, i++){ p->nRef = anRef[i]; } sqlite3ExprDelete(pParse->db, pExpr->pLeft); pExpr->pLeft = 0; } return WRC_Prune; |
︙ | ︙ | |||
1249 1250 1251 1252 1253 1254 1255 1256 | notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ sqlite3WalkSelect(pWalker, pExpr->x.pSelect); } assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); } | > < | 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 | notValidImpl(pParse, pNC, "subqueries", pExpr, pExpr); }else{ sqlite3WalkSelect(pWalker, pExpr->x.pSelect); } assert( pNC->nRef>=nRef ); if( nRef!=pNC->nRef ){ ExprSetProperty(pExpr, EP_VarSelect); pNC->ncFlags |= NC_VarSelect; } } break; } case TK_VARIABLE: { testcase( pNC->ncFlags & NC_IsCheck ); testcase( pNC->ncFlags & NC_PartIdx ); testcase( pNC->ncFlags & NC_IdxExpr ); |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
2314 2315 2316 2317 2318 2319 2320 | struct ExprList_item *a; NameContext sNC; assert( pSelect!=0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 ); assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); | | > > < < < | | | | | | < | | | > > > | 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 | struct ExprList_item *a; NameContext sNC; assert( pSelect!=0 ); assert( (pSelect->selFlags & SF_Resolved)!=0 ); assert( pTab->nCol==pSelect->pEList->nExpr || pParse->nErr>0 ); assert( aff==SQLITE_AFF_NONE || aff==SQLITE_AFF_BLOB ); if( db->mallocFailed ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; a = pSelect->pEList->a; memset(&sNC, 0, sizeof(sNC)); sNC.pSrcList = pSelect->pSrc; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ const char *zType; i64 n; pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); if( pCol->affinity<=SQLITE_AFF_NONE ){ pCol->affinity = aff; }else if( pCol->affinity>=SQLITE_AFF_NUMERIC && p->op==TK_CAST ){ pCol->affinity = SQLITE_AFF_FLEXNUM; } if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){ int m = 0; Select *pS2; for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){ m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); } if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ pCol->affinity = SQLITE_AFF_BLOB; }else if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){ pCol->affinity = SQLITE_AFF_BLOB; } } zType = columnType(&sNC, p, 0, 0, 0); if( zType==0 || pCol->affinity!=sqlite3AffinityType(zType, 0) ){ if( pCol->affinity==SQLITE_AFF_NUMERIC || pCol->affinity==SQLITE_AFF_FLEXNUM ){ zType = "NUM"; }else{ zType = 0; for(j=1; j<SQLITE_N_STDTYPE; j++){ if( sqlite3StdTypeAffinity[j]==pCol->affinity ){ zType = sqlite3StdType[j]; break; } } } } if( zType ){ i64 m = sqlite3Strlen30(zType); n = sqlite3Strlen30(pCol->zCnName); pCol->zCnName = sqlite3DbReallocOrFree(db, pCol->zCnName, n+m+2); if( pCol->zCnName ){ memcpy(&pCol->zCnName[n+1], zType, m+1); pCol->colFlags |= COLFLAG_HASTYPE; }else{ testcase( pCol->colFlags & COLFLAG_HASTYPE ); pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); } } pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ assert( pTab->pIndex==0 ); sqlite3ColumnSetColl(db, pCol, pColl->zName); } |
︙ | ︙ | |||
3856 3857 3858 3859 3860 3861 3862 | Expr ifNullRow; assert( pSubst->pEList!=0 && iColumn<pSubst->pEList->nExpr ); assert( pExpr->pRight==0 ); if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ sqlite3 *db = pSubst->pParse->db; | | < < | 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 | Expr ifNullRow; assert( pSubst->pEList!=0 && iColumn<pSubst->pEList->nExpr ); assert( pExpr->pRight==0 ); if( sqlite3ExprIsVector(pCopy) ){ sqlite3VectorErrorMsg(pSubst->pParse, pCopy); }else{ sqlite3 *db = pSubst->pParse->db; if( pSubst->isOuterJoin && pCopy->op!=TK_COLUMN ){ memset(&ifNullRow, 0, sizeof(ifNullRow)); ifNullRow.op = TK_IF_NULL_ROW; ifNullRow.pLeft = pCopy; ifNullRow.iTable = pSubst->iNewTable; ifNullRow.iColumn = -99; ifNullRow.flags = EP_IfNullRow; pCopy = &ifNullRow; |
︙ | ︙ | |||
4235 4236 4237 4238 4239 4240 4241 | ** (17d2) DISTINCT ** (17e) the subquery may not contain window functions, and ** (17f) the subquery must not be the RHS of a LEFT JOIN. ** (17g) either the subquery is the first element of the outer ** query or there are no RIGHT or FULL JOINs in any arm ** of the subquery. (This is a duplicate of condition (27b).) ** (17h) The corresponding result set expressions in all arms of the | | > | 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 | ** (17d2) DISTINCT ** (17e) the subquery may not contain window functions, and ** (17f) the subquery must not be the RHS of a LEFT JOIN. ** (17g) either the subquery is the first element of the outer ** query or there are no RIGHT or FULL JOINs in any arm ** of the subquery. (This is a duplicate of condition (27b).) ** (17h) The corresponding result set expressions in all arms of the ** compound must have the same affinity. (See restriction (9) ** on the push-down optimization.) ** ** The parent and sub-query may contain WHERE clauses. Subject to ** rules (11), (13) and (14), they may also contain ORDER BY, ** LIMIT and OFFSET clauses. The subquery cannot use any compound ** operator other than UNION ALL because all the other compound ** operators have an implied DISTINCT which is disallowed by ** restriction (4). |
︙ | ︙ | |||
5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 | ** be materialized. (This restriction is implemented in the calling ** routine.) ** ** (8) If the subquery is a compound that uses UNION, INTERSECT, ** or EXCEPT, then all of the result set columns for all arms of ** the compound must use the BINARY collating sequence. ** ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ | > > > > | 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 | ** be materialized. (This restriction is implemented in the calling ** routine.) ** ** (8) If the subquery is a compound that uses UNION, INTERSECT, ** or EXCEPT, then all of the result set columns for all arms of ** the compound must use the BINARY collating sequence. ** ** (9) If the subquery is a compound, then all arms of the compound must ** have the same affinity. (This is the same as restriction (17h) ** for query flattening.) ** ** ** Return 0 if no changes are made and non-zero if one or more WHERE clause ** terms are duplicated into the subquery. */ static int pushDownWhereTerms( Parse *pParse, /* Parse context (for malloc() and error reporting) */ Select *pSubq, /* The subquery whose WHERE clause is to be augmented */ |
︙ | ︙ | |||
5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 | || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT ); if( op!=TK_ALL && op!=TK_SELECT ){ notUnionAll = 1; } #ifndef SQLITE_OMIT_WINDOWFUNC if( pSel->pWin ) return 0; /* restriction (6b) */ #endif } if( notUnionAll ){ /* If any of the compound arms are connected using UNION, INTERSECT, ** or EXCEPT, then we must ensure that none of the columns use a ** non-BINARY collating sequence. */ for(pSel=pSubq; pSel; pSel=pSel->pPrior){ int ii; | > > > | 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 | || op==TK_UNION || op==TK_INTERSECT || op==TK_EXCEPT ); if( op!=TK_ALL && op!=TK_SELECT ){ notUnionAll = 1; } #ifndef SQLITE_OMIT_WINDOWFUNC if( pSel->pWin ) return 0; /* restriction (6b) */ #endif } if( compoundHasDifferentAffinities(pSubq) ){ return 0; /* restriction (9) */ } if( notUnionAll ){ /* If any of the compound arms are connected using UNION, INTERSECT, ** or EXCEPT, then we must ensure that none of the columns use a ** non-BINARY collating sequence. */ for(pSel=pSubq; pSel; pSel=pSel->pPrior){ int ii; |
︙ | ︙ | |||
5223 5224 5225 5226 5227 5228 5229 | } pSubq = pSubq->pPrior; } } return nChng; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 | } pSubq = pSubq->pPrior; } } return nChng; } #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */ /* ** The pFunc is the only aggregate function in the query. Check to see ** if the query is a candidate for the min/max optimization. ** ** If the query is a candidate for the min/max optimization, then set ** *ppMinMax to be an ORDER BY clause to be used for the optimization |
︙ | ︙ | |||
6438 6439 6440 6441 6442 6443 6444 | static void optimizeAggregateUseOfIndexedExpr( Parse *pParse, /* Parsing context */ Select *pSelect, /* The SELECT statement being processed */ AggInfo *pAggInfo, /* The aggregate info */ NameContext *pNC /* Name context used to resolve agg-func args */ ){ assert( pAggInfo->iFirstReg==0 ); | < < < < | | < | | > > | 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 | static void optimizeAggregateUseOfIndexedExpr( Parse *pParse, /* Parsing context */ Select *pSelect, /* The SELECT statement being processed */ AggInfo *pAggInfo, /* The aggregate info */ NameContext *pNC /* Name context used to resolve agg-func args */ ){ assert( pAggInfo->iFirstReg==0 ); pAggInfo->nColumn = pAggInfo->nAccumulator; if( ALWAYS(pAggInfo->nSortingColumn>0) ){ if( pAggInfo->nColumn==0 ){ pAggInfo->nSortingColumn = 0; }else{ pAggInfo->nSortingColumn = pAggInfo->aCol[pAggInfo->nColumn-1].iSorterColumn+1; } } analyzeAggFuncArgs(pAggInfo, pNC); #if TREETRACE_ENABLED if( sqlite3TreeTrace & 0x20 ){ IndexedExpr *pIEpr; TREETRACE(0x20, pParse, pSelect, ("AggInfo (possibly) adjusted for Indexed Exprs\n")); |
︙ | ︙ | |||
6482 6483 6484 6485 6486 6487 6488 | struct AggInfo_col *pCol; UNUSED_PARAMETER(pWalker); if( pExpr->pAggInfo==0 ) return WRC_Continue; if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue; if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue; if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue; pAggInfo = pExpr->pAggInfo; | < | < | 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425 6426 6427 6428 6429 6430 6431 6432 | struct AggInfo_col *pCol; UNUSED_PARAMETER(pWalker); if( pExpr->pAggInfo==0 ) return WRC_Continue; if( pExpr->op==TK_AGG_COLUMN ) return WRC_Continue; if( pExpr->op==TK_AGG_FUNCTION ) return WRC_Continue; if( pExpr->op==TK_IF_NULL_ROW ) return WRC_Continue; pAggInfo = pExpr->pAggInfo; assert( pExpr->iAgg>=0 && pExpr->iAgg<pAggInfo->nColumn ); pCol = &pAggInfo->aCol[pExpr->iAgg]; pExpr->op = TK_AGG_COLUMN; pExpr->iTable = pCol->iTable; pExpr->iColumn = pCol->iColumn; return WRC_Prune; } /* ** Convert every pAggInfo->aFunc[].pExpr such that any node within ** those expressions that has pAppInfo set is changed into a TK_AGG_COLUMN ** opcode. |
︙ | ︙ | |||
6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 | */ static void agginfoFree(sqlite3 *db, AggInfo *p){ sqlite3DbFree(db, p->aCol); sqlite3DbFree(db, p->aFunc); sqlite3DbFreeNN(db, p); } /* ** Attempt to transform a query of the form ** ** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) ** ** Into this: ** | > | 6772 6773 6774 6775 6776 6777 6778 6779 6780 6781 6782 6783 6784 6785 6786 | */ static void agginfoFree(sqlite3 *db, AggInfo *p){ sqlite3DbFree(db, p->aCol); sqlite3DbFree(db, p->aFunc); sqlite3DbFreeNN(db, p); } #ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION /* ** Attempt to transform a query of the form ** ** SELECT count(*) FROM (SELECT x FROM t1 UNION ALL SELECT y FROM t2) ** ** Into this: ** |
︙ | ︙ | |||
6869 6870 6871 6872 6873 6874 6875 | Select *pSub, *pPrior; Expr *pExpr; Expr *pCount; sqlite3 *db; if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ if( p->pWhere ) return 0; | < < < | < < | | 6800 6801 6802 6803 6804 6805 6806 6807 6808 6809 6810 6811 6812 6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 6823 6824 6825 6826 6827 6828 6829 6830 | Select *pSub, *pPrior; Expr *pExpr; Expr *pCount; sqlite3 *db; if( (p->selFlags & SF_Aggregate)==0 ) return 0; /* This is an aggregate */ if( p->pEList->nExpr!=1 ) return 0; /* Single result column */ if( p->pWhere ) return 0; if( p->pGroupBy ) return 0; pExpr = p->pEList->a[0].pExpr; if( pExpr->op!=TK_AGG_FUNCTION ) return 0; /* Result is an aggregate */ assert( ExprUseUToken(pExpr) ); if( sqlite3_stricmp(pExpr->u.zToken,"count") ) return 0; /* Is count() */ assert( ExprUseXList(pExpr) ); if( pExpr->x.pList!=0 ) return 0; /* Must be count(*) */ if( p->pSrc->nSrc!=1 ) return 0; /* One table in FROM */ pSub = p->pSrc->a[0].pSelect; if( pSub==0 ) return 0; /* The FROM is a subquery */ if( pSub->pPrior==0 ) return 0; /* Must be a compound ry */ do{ if( pSub->op!=TK_ALL && pSub->pPrior ) return 0; /* Must be UNION ALL */ if( pSub->pWhere ) return 0; /* No WHERE clause */ if( pSub->pLimit ) return 0; /* No LIMIT clause */ if( pSub->selFlags & SF_Aggregate ) return 0; /* Not an aggregate */ pSub = pSub->pPrior; /* Repeat over compound */ }while( pSub ); /* If we reach this point then it is OK to perform the transformation */ db = pParse->db; pCount = pExpr; pExpr = 0; |
︙ | ︙ | |||
6933 6934 6935 6936 6937 6938 6939 6940 6941 6942 6943 6944 6945 6946 | if( sqlite3TreeTrace & 0x200 ){ TREETRACE(0x200,pParse,p,("After count-of-view optimization:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif return 1; } /* ** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same ** as pSrcItem but has the same alias as p0, then return true. ** Otherwise return false. */ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ | > | 6859 6860 6861 6862 6863 6864 6865 6866 6867 6868 6869 6870 6871 6872 6873 | if( sqlite3TreeTrace & 0x200 ){ TREETRACE(0x200,pParse,p,("After count-of-view optimization:\n")); sqlite3TreeViewSelect(0, p, 0); } #endif return 1; } #endif /* SQLITE_COUNTOFVIEW_OPTIMIZATION */ /* ** If any term of pSrc, or any SF_NestedFrom sub-query, is not the same ** as pSrcItem but has the same alias as p0, then return true. ** Otherwise return false. */ static int sameSrcAlias(SrcItem *p0, SrcList *pSrc){ |
︙ | ︙ | |||
7321 7322 7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 | sqlite3TreeViewSelect(0, p, 0); } #endif }else{ TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n")); } if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) && countOfViewOptimization(pParse, p) ){ if( db->mallocFailed ) goto select_end; pTabList = p->pSrc; } /* For each term in the FROM clause, do two things: ** (1) Authorized unreferenced tables ** (2) Generate code for all sub-queries */ for(i=0; i<pTabList->nSrc; i++){ SrcItem *pItem = &pTabList->a[i]; | > > > | 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 | sqlite3TreeViewSelect(0, p, 0); } #endif }else{ TREETRACE(0x2000,pParse,p,("Constant propagation not helpful\n")); } #ifdef SQLITE_COUNTOFVIEW_OPTIMIZATION if( OptimizationEnabled(db, SQLITE_QueryFlattener|SQLITE_CountOfView) && countOfViewOptimization(pParse, p) ){ if( db->mallocFailed ) goto select_end; pEList = p->pEList; pTabList = p->pSrc; } #endif /* For each term in the FROM clause, do two things: ** (1) Authorized unreferenced tables ** (2) Generate code for all sub-queries */ for(i=0; i<pTabList->nSrc; i++){ SrcItem *pItem = &pTabList->a[i]; |
︙ | ︙ | |||
7399 7400 7401 7402 7403 7404 7405 | } #endif assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ TREETRACE(0x4000,pParse,p,("Push-down not possible\n")); } | < < < < < < < < < < < < < < < < | 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 | } #endif assert( pItem->pSelect && (pItem->pSelect->selFlags & SF_PushDown)!=0 ); }else{ TREETRACE(0x4000,pParse,p,("Push-down not possible\n")); } zSavedAuthContext = pParse->zAuthContext; pParse->zAuthContext = pItem->zName; /* Generate code to implement the subquery */ if( fromClauseTermCanBeCoroutine(pParse, pTabList, i, p->selFlags) ){ /* Implement a co-routine that will return a single row of the result |
︙ | ︙ | |||
7957 7958 7959 7960 7961 7962 7963 | sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); pAggInfo->useSortingIdx = 1; } | | | 7871 7872 7873 7874 7875 7876 7877 7878 7879 7880 7881 7882 7883 7884 7885 | sortOut = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_OpenPseudo, sortPTab, sortOut, nCol); sqlite3VdbeAddOp2(v, OP_SorterSort, pAggInfo->sortingIdx, addrEnd); VdbeComment((v, "GROUP BY sort")); VdbeCoverage(v); pAggInfo->useSortingIdx = 1; } /* If there entries in pAgggInfo->aFunc[] that contain subexpressions ** that are indexed (and that were previously identified and tagged ** in optimizeAggregateUseOfIndexedExpr()) then those subexpressions ** must now be converted into a TK_AGG_COLUMN node so that the value ** is correctly pulled from the index rather than being recomputed. */ if( pParse->pIdxEpr ){ aggregateConvertIndexedExprRefToColumn(pAggInfo); #if TREETRACE_ENABLED |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
95 96 97 98 99 100 101 | # define _POSIX_SOURCE #endif #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> | < | | 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 | # define _POSIX_SOURCE #endif #include <stdlib.h> #include <string.h> #include <stdio.h> #include <assert.h> #include "sqlite3.h" typedef sqlite3_int64 i64; typedef sqlite3_uint64 u64; typedef unsigned char u8; #if SQLITE_USER_AUTHENTICATION # include "sqlite3userauth.h" #endif #include <ctype.h> #include <stdarg.h> #if !defined(_WIN32) && !defined(WIN32) # include <signal.h> # if !defined(__RTP__) && !defined(_WRS_KERNEL) # include <pwd.h> # endif #endif #if (!defined(_WIN32) && !defined(WIN32)) || defined(__MINGW32__) # include <unistd.h> # include <dirent.h> # define GETPID getpid |
︙ | ︙ | |||
165 166 167 168 169 170 171 | # define shell_stifle_history(X) # define SHELL_USE_LOCAL_GETLINE 1 #endif #ifndef deliberate_fall_through /* Quiet some compilers about some of our intentional code. */ | | | 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 | # define shell_stifle_history(X) # define SHELL_USE_LOCAL_GETLINE 1 #endif #ifndef deliberate_fall_through /* Quiet some compilers about some of our intentional code. */ # if GCC_VERSION>=7000000 # define deliberate_fall_through __attribute__((fallthrough)); # else # define deliberate_fall_through # endif #endif #if defined(_WIN32) || defined(WIN32) |
︙ | ︙ | |||
197 198 199 200 201 202 203 | # undef pclose # define pclose _pclose # endif #else /* Make sure isatty() has a prototype. */ extern int isatty(int); | | | 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 | # undef pclose # define pclose _pclose # endif #else /* Make sure isatty() has a prototype. */ extern int isatty(int); # if !defined(__RTP__) && !defined(_WRS_KERNEL) /* popen and pclose are not C89 functions and so are ** sometimes omitted from the <stdio.h> header */ extern FILE *popen(const char*,const char*); extern int pclose(FILE*); # else # define SQLITE_OMIT_POPEN 1 # endif |
︙ | ︙ | |||
224 225 226 227 228 229 230 | #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) #if defined(_WIN32) || defined(WIN32) #if SQLITE_OS_WINRT #include <intrin.h> #endif | < | 223 224 225 226 227 228 229 230 231 232 233 234 235 236 | #define IsDigit(X) isdigit((unsigned char)X) #define ToLower(X) (char)tolower((unsigned char)X) #if defined(_WIN32) || defined(WIN32) #if SQLITE_OS_WINRT #include <intrin.h> #endif #include <windows.h> /* string conversion routines only needed on Win32 */ extern char *sqlite3_win32_unicode_to_utf8(LPCWSTR); extern char *sqlite3_win32_mbcs_to_utf8_v2(const char *, int); extern char *sqlite3_win32_utf8_to_mbcs_v2(const char *, int); extern LPWSTR sqlite3_win32_utf8_to_unicode(const char *zText); |
︙ | ︙ | |||
439 440 441 442 443 444 445 | /* ** If the following flag is set, then command execution stops ** at an error if we are not interactive. */ static int bail_on_error = 0; /* | | < < < < < < < < < < < < < < | 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 | /* ** If the following flag is set, then command execution stops ** at an error if we are not interactive. */ static int bail_on_error = 0; /* ** Threat stdin as an interactive input if the following variable ** is true. Otherwise, assume stdin is connected to a file or pipe. */ static int stdin_is_interactive = 1; /* ** On Windows systems we have to know if standard output is a console ** in order to translate UTF-8 into MBCS. The following variable is ** true if translation is required. */ static int stdout_is_console = 1; |
︙ | ︙ | |||
590 591 592 593 594 595 596 | shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); } } return dynPrompt.dynamicPrompt; } #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < | < | < < < < | 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 | shell_strncpy(dynPrompt.dynamicPrompt+3, continuePrompt+3, PROMPT_LEN_MAX-4); } } return dynPrompt.dynamicPrompt; } #endif /* !defined(SQLITE_OMIT_DYNAPROMPT) */ /* ** Render output like fprintf(). Except, if the output is going to the ** console and if this is running on a Windows machine, translate the ** output from UTF-8 into MBCS. */ #if defined(_WIN32) || defined(WIN32) void utf8_printf(FILE *out, const char *zFormat, ...){ va_list ap; va_start(ap, zFormat); if( stdout_is_console && (out==stdout || out==stderr) ){ char *z1 = sqlite3_vmprintf(zFormat, ap); char *z2 = sqlite3_win32_utf8_to_mbcs_v2(z1, 0); sqlite3_free(z1); fputs(z2, out); sqlite3_free(z2); }else{ vfprintf(out, zFormat, ap); |
︙ | ︙ | |||
761 762 763 764 765 766 767 | raw_printf(stderr,"Error: out of memory\n"); exit(1); } /* Check a pointer to see if it is NULL. If it is NULL, exit with an ** out-of-memory error. */ | | | 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 | raw_printf(stderr,"Error: out of memory\n"); exit(1); } /* Check a pointer to see if it is NULL. If it is NULL, exit with an ** out-of-memory error. */ static void shell_check_oom(void *p){ if( p==0 ) shell_out_of_memory(); } /* ** Write I/O traces to the following stream. */ #ifdef SQLITE_ENABLE_IOTRACE |
︙ | ︙ | |||
940 941 942 943 944 945 946 | n--; if( n>0 && zLine[n-1]=='\r' ) n--; zLine[n] = 0; break; } } #if defined(_WIN32) || defined(WIN32) | | | < | < < < < | 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 | n--; if( n>0 && zLine[n-1]=='\r' ) n--; zLine[n] = 0; break; } } #if defined(_WIN32) || defined(WIN32) /* For interactive input on Windows systems, translate the ** multi-byte characterset characters into UTF-8. */ if( stdin_is_interactive && in==stdin ){ char *zTrans = sqlite3_win32_mbcs_to_utf8_v2(zLine, 0); if( zTrans ){ i64 nTrans = strlen(zTrans)+1; if( nTrans>nLine ){ zLine = realloc(zLine, nTrans); shell_check_oom(zLine); } |
︙ | ︙ | |||
988 989 990 991 992 993 994 | if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt; #if SHELL_USE_LOCAL_GETLINE printf("%s", zPrompt); fflush(stdout); | < | < < < < < < < < < < | 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 | if( in!=0 ){ zResult = local_getline(zPrior, in); }else{ zPrompt = isContinuation ? CONTINUATION_PROMPT : mainPrompt; #if SHELL_USE_LOCAL_GETLINE printf("%s", zPrompt); fflush(stdout); zResult = local_getline(zPrior, stdin); #else free(zPrior); zResult = shell_readline(zPrompt); if( zResult && *zResult ) shell_add_history(zResult); #endif } return zResult; } #endif /* !SQLITE_SHELL_FIDDLE */ |
︙ | ︙ | |||
1142 1143 1144 1145 1146 1147 1148 | ** SQLite keyword. Be conservative in this estimate: When in doubt assume ** that quoting is required. ** ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ int i; | < | 980 981 982 983 984 985 986 987 988 989 990 991 992 993 | ** SQLite keyword. Be conservative in this estimate: When in doubt assume ** that quoting is required. ** ** Return '"' if quoting is required. Return 0 if no quoting is required. */ static char quoteChar(const char *zName){ int i; if( !isalpha((unsigned char)zName[0]) && zName[0]!='_' ) return '"'; for(i=0; zName[i]; i++){ if( !isalnum((unsigned char)zName[i]) && zName[i]!='_' ) return '"'; } return sqlite3_keyword_check(zName, i) ? '"' : 0; } |
︙ | ︙ | |||
1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) #define SQLITE_SHELL_HAVE_RECOVER 1 #else #define SQLITE_SHELL_HAVE_RECOVER 0 #endif #if SQLITE_SHELL_HAVE_RECOVER INCLUDE ../ext/recover/sqlite3recover.h INCLUDE ../ext/recover/dbdata.c INCLUDE ../ext/recover/sqlite3recover.c #endif #ifdef SQLITE_SHELL_EXTSRC # include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC) #endif #if defined(SQLITE_ENABLE_SESSION) /* | > > | 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 | #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) #define SQLITE_SHELL_HAVE_RECOVER 1 #else #define SQLITE_SHELL_HAVE_RECOVER 0 #endif #if SQLITE_SHELL_HAVE_RECOVER INCLUDE ../ext/recover/sqlite3recover.h # ifndef SQLITE_HAVE_SQLITE3R INCLUDE ../ext/recover/dbdata.c INCLUDE ../ext/recover/sqlite3recover.c # endif #endif #ifdef SQLITE_SHELL_EXTSRC # include SHELL_STRINGIFY(SQLITE_SHELL_EXTSRC) #endif #if defined(SQLITE_ENABLE_SESSION) /* |
︙ | ︙ | |||
1524 1525 1526 1527 1528 1529 1530 | #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */ #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ #define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */ #define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */ #define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */ #define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */ | < | 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 | #define SHFLG_PreserveRowid 0x00000008 /* .dump preserves rowid values */ #define SHFLG_Newlines 0x00000010 /* .dump --newline flag */ #define SHFLG_CountChanges 0x00000020 /* .changes setting */ #define SHFLG_Echo 0x00000040 /* .echo on/off, or --echo setting */ #define SHFLG_HeaderSet 0x00000080 /* showHeader has been specified */ #define SHFLG_DumpDataOnly 0x00000100 /* .dump show data only */ #define SHFLG_DumpNoSys 0x00000200 /* .dump omits system tables */ /* ** Macros for testing and setting shellFlgs */ #define ShellHasFlag(P,X) (((P)->shellFlgs & (X))!=0) #define ShellSetFlag(P,X) ((P)->shellFlgs|=(X)) #define ShellClearFlag(P,X) ((P)->shellFlgs&=(~(X))) |
︙ | ︙ | |||
1858 1859 1860 1861 1862 1863 1864 | ** ** See also: output_quoted_escaped_string() */ static void output_quoted_string(FILE *out, const char *z){ int i; char c; setBinaryMode(out, 1); | < | 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 | ** ** See also: output_quoted_escaped_string() */ static void output_quoted_string(FILE *out, const char *z){ int i; char c; setBinaryMode(out, 1); for(i=0; (c = z[i])!=0 && c!='\''; i++){} if( c==0 ){ utf8_printf(out,"'%s'",z); }else{ raw_printf(out, "'"); while( *z ){ for(i=0; (c = z[i])!=0 && c!='\''; i++){} |
︙ | ︙ | |||
1988 1989 1990 1991 1992 1993 1994 | } /* ** Output the given string as a quoted according to JSON quoting rules. */ static void output_json_string(FILE *out, const char *z, i64 n){ unsigned int c; | < | 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 | } /* ** Output the given string as a quoted according to JSON quoting rules. */ static void output_json_string(FILE *out, const char *z, i64 n){ unsigned int c; if( n<0 ) n = strlen(z); fputc('"', out); while( n-- ){ c = *(z++); if( c=='\\' || c=='"' ){ fputc('\\', out); fputc(c, out); |
︙ | ︙ | |||
2113 2114 2115 2116 2117 2118 2119 | } /* ** This routine runs when the user presses Ctrl-C */ static void interrupt_handler(int NotUsed){ UNUSED_PARAMETER(NotUsed); | | > | 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 | } /* ** This routine runs when the user presses Ctrl-C */ static void interrupt_handler(int NotUsed){ UNUSED_PARAMETER(NotUsed); seenInterrupt++; if( seenInterrupt>2 ) exit(1); if( globalDb ) sqlite3_interrupt(globalDb); } #if (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) /* ** This routine runs for console events (e.g. Ctrl-C) on Win32 */ |
︙ | ︙ | |||
2247 2248 2249 2250 2251 2252 2253 | if( zTail==0 ) return; if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){ const char *zOrig = z; static const char *azTerm[] = { "", "*/", "\n" }; int i; for(i=0; i<ArraySize(azTerm); i++){ char *zNew = sqlite3_mprintf("%s%s;", zOrig, azTerm[i]); | < | 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 | if( zTail==0 ) return; if( zTail[0]==';' && (strstr(z, "/*")!=0 || strstr(z,"--")!=0) ){ const char *zOrig = z; static const char *azTerm[] = { "", "*/", "\n" }; int i; for(i=0; i<ArraySize(azTerm); i++){ char *zNew = sqlite3_mprintf("%s%s;", zOrig, azTerm[i]); if( sqlite3_complete(zNew) ){ size_t n = strlen(zNew); zNew[n-1] = 0; zToFree = zNew; z = zNew; break; } |
︙ | ︙ | |||
2682 2683 2684 2685 2686 2687 2688 | utf8_printf(p->out,"%s", azArg[i]); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_uint64 ur; memcpy(&ur,&r,sizeof(r)); if( ur==0x7ff0000000000000LL ){ | | | | 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 | utf8_printf(p->out,"%s", azArg[i]); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_uint64 ur; memcpy(&ur,&r,sizeof(r)); if( ur==0x7ff0000000000000LL ){ raw_printf(p->out, "1e999"); }else if( ur==0xfff0000000000000LL ){ raw_printf(p->out, "-1e999"); }else{ sqlite3_int64 ir = (sqlite3_int64)r; if( r==(double)ir ){ sqlite3_snprintf(50,z,"%lld.0", ir); }else{ sqlite3_snprintf(50,z,"%!.20g", r); } |
︙ | ︙ | |||
2728 2729 2730 2731 2732 2733 2734 | fputs("null",p->out); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_uint64 ur; memcpy(&ur,&r,sizeof(r)); if( ur==0x7ff0000000000000LL ){ | | | | 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 | fputs("null",p->out); }else if( aiType && aiType[i]==SQLITE_FLOAT ){ char z[50]; double r = sqlite3_column_double(p->pStmt, i); sqlite3_uint64 ur; memcpy(&ur,&r,sizeof(r)); if( ur==0x7ff0000000000000LL ){ raw_printf(p->out, "1e999"); }else if( ur==0xfff0000000000000LL ){ raw_printf(p->out, "-1e999"); }else{ sqlite3_snprintf(50,z,"%!.20g", r); raw_printf(p->out, "%s", z); } }else if( aiType && aiType[i]==SQLITE_BLOB && p->pStmt ){ const void *pBlob = sqlite3_column_blob(p->pStmt, i); int nBlob = sqlite3_column_bytes(p->pStmt, i); |
︙ | ︙ | |||
2934 2935 2936 2937 2938 2939 2940 | size_t len; char *zCode; char *zMsg; int i; if( db==0 || zSql==0 || (iOffset = sqlite3_error_offset(db))<0 | < | | 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 | size_t len; char *zCode; char *zMsg; int i; if( db==0 || zSql==0 || (iOffset = sqlite3_error_offset(db))<0 ){ return sqlite3_mprintf(""); } while( iOffset>50 ){ iOffset--; zSql++; while( (zSql[0]&0xc0)==0x80 ){ zSql++; iOffset--; } } len = strlen(zSql); if( len>78 ){ len = 78; while( (zSql[len]&0xc0)==0x80 ) len--; } zCode = sqlite3_mprintf("%.*s", len, zSql); shell_check_oom(zCode); for(i=0; zCode[i]; i++){ if( IsSpace(zSql[i]) ) zCode[i] = ' '; } if( iOffset<25 ){ zMsg = sqlite3_mprintf("\n %z\n %*s^--- error here", zCode,iOffset,""); }else{ |
︙ | ︙ | |||
3547 3548 3549 3550 3551 3552 3553 | int rc; sqlite3_stmt *pQ = 0; nVar = sqlite3_bind_parameter_count(pStmt); if( nVar==0 ) return; /* Nothing to do */ if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters", "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){ | | < < > | | | < > | < < < < < < < < | 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 | int rc; sqlite3_stmt *pQ = 0; nVar = sqlite3_bind_parameter_count(pStmt); if( nVar==0 ) return; /* Nothing to do */ if( sqlite3_table_column_metadata(pArg->db, "TEMP", "sqlite_parameters", "key", 0, 0, 0, 0, 0)!=SQLITE_OK ){ return; /* Parameter table does not exist */ } rc = sqlite3_prepare_v2(pArg->db, "SELECT value FROM temp.sqlite_parameters" " WHERE key=?1", -1, &pQ, 0); if( rc || pQ==0 ) return; for(i=1; i<=nVar; i++){ char zNum[30]; const char *zVar = sqlite3_bind_parameter_name(pStmt, i); if( zVar==0 ){ sqlite3_snprintf(sizeof(zNum),zNum,"?%d",i); zVar = zNum; } sqlite3_bind_text(pQ, 1, zVar, -1, SQLITE_STATIC); if( sqlite3_step(pQ)==SQLITE_ROW ){ sqlite3_bind_value(pStmt, i, sqlite3_column_value(pQ, 0)); }else{ sqlite3_bind_null(pStmt, i); } sqlite3_reset(pQ); } sqlite3_finalize(pQ); } |
︙ | ︙ | |||
3815 3816 3817 3818 3819 3820 3821 | if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); shell_check_oom(azData); azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) ); | | | 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 | if( rc!=SQLITE_ROW ) return; nColumn = sqlite3_column_count(pStmt); nAlloc = nColumn*4; if( nAlloc<=0 ) nAlloc = 1; azData = sqlite3_malloc64( nAlloc*sizeof(char*) ); shell_check_oom(azData); azNextLine = sqlite3_malloc64( nColumn*sizeof(char*) ); shell_check_oom((void*)azNextLine); memset((void*)azNextLine, 0, nColumn*sizeof(char*) ); if( p->cmOpts.bQuote ){ azQuoted = sqlite3_malloc64( nColumn*sizeof(char*) ); shell_check_oom(azQuoted); memset(azQuoted, 0, nColumn*sizeof(char*) ); } abRowDiv = sqlite3_malloc64( nAlloc/nColumn ); |
︙ | ︙ | |||
3845 3846 3847 3848 3849 3850 3851 | const unsigned char *zNotUsed; int wx = p->colWidth[i]; if( wx==0 ){ wx = p->cmOpts.iWrap; } if( wx<0 ) wx = -wx; uz = (const unsigned char*)sqlite3_column_name(pStmt,i); | < | 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 | const unsigned char *zNotUsed; int wx = p->colWidth[i]; if( wx==0 ){ wx = p->cmOpts.iWrap; } if( wx<0 ) wx = -wx; uz = (const unsigned char*)sqlite3_column_name(pStmt,i); azData[i] = translateForDisplayAndDup(uz, &zNotUsed, wx, bw); } do{ int useNextLine = bNextLine; bNextLine = 0; if( (nRow+2)*nColumn >= nAlloc ){ nAlloc *= 2; |
︙ | ︙ | |||
4779 4780 4781 4782 4783 4784 4785 | " determines the column names.", " * If neither --csv or --ascii are used, the input mode is derived", " from the \".mode\" output mode", " * If FILE begins with \"|\" then it is a command that generates the", " input text.", #endif #ifndef SQLITE_OMIT_TEST_CONTROL | | | | | < < | 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 | " determines the column names.", " * If neither --csv or --ascii are used, the input mode is derived", " from the \".mode\" output mode", " * If FILE begins with \"|\" then it is a command that generates the", " input text.", #endif #ifndef SQLITE_OMIT_TEST_CONTROL ".imposter INDEX TABLE Create imposter table TABLE on index INDEX", #endif ".indexes ?TABLE? Show names of indexes", " If TABLE is specified, only show indexes for", " tables matching TABLE using the LIKE operator.", #ifdef SQLITE_ENABLE_IOTRACE ".iotrace FILE Enable I/O diagnostic logging to FILE", #endif ".limit ?LIMIT? ?VAL? Display or change the value of an SQLITE_LIMIT", ".lint OPTIONS Report potential schema issues.", " Options:", " fkey-indexes Find missing foreign key indexes", #if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE) ".load FILE ?ENTRY? Load an extension library", #endif #ifndef SQLITE_SHELL_FIDDLE ".log FILE|off Turn logging on or off. FILE can be stderr/stdout", #endif ".mode MODE ?OPTIONS? Set output mode", " MODE is one of:", " ascii Columns/rows delimited by 0x1F and 0x1E", " box Tables using unicode box-drawing characters", " csv Comma-separated values", " column Output in columns. (See .width)", |
︙ | ︙ | |||
4894 4895 4896 4897 4898 4899 4900 | ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)", #endif ".scanstats on|off|est Turn sqlite3_stmt_scanstatus() metrics on or off", ".schema ?PATTERN? Show the CREATE statements matching PATTERN", " Options:", " --indent Try to pretty-print the schema", " --nosys Omit objects whose names start with \"sqlite_\"", | | | 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 | ".save ?OPTIONS? FILE Write database to FILE (an alias for .backup ...)", #endif ".scanstats on|off|est Turn sqlite3_stmt_scanstatus() metrics on or off", ".schema ?PATTERN? Show the CREATE statements matching PATTERN", " Options:", " --indent Try to pretty-print the schema", " --nosys Omit objects whose names start with \"sqlite_\"", ".selftest ?OPTIONS? Run tests defined in the SELFTEST table", " Options:", " --init Create a new SELFTEST table", " -v Verbose output", ".separator COL ?ROW? Change the column and row separators", #if defined(SQLITE_ENABLE_SESSION) ".session ?NAME? CMD ... Create or control sessions", " Subcommands:", |
︙ | ︙ | |||
4936 4937 4938 4939 4940 4941 4942 | " stmt Show statement stats", " vmstep Show the virtual machine step count only", #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", #ifndef SQLITE_SHELL_FIDDLE | | | | 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 | " stmt Show statement stats", " vmstep Show the virtual machine step count only", #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) ".system CMD ARGS... Run CMD ARGS... in a system shell", #endif ".tables ?TABLE? List names of tables matching LIKE pattern TABLE", #ifndef SQLITE_SHELL_FIDDLE ".testcase NAME Begin redirecting output to 'testcase-out.txt'", #endif ".testctrl CMD ... Run various sqlite3_test_control() operations", " Run \".testctrl\" with no arguments for details", ".timeout MS Try opening locked tables for MS milliseconds", ".timer on|off Turn SQL timer on or off", #ifndef SQLITE_OMIT_TRACE ".trace ?OPTIONS? Output each SQL statement as it is run", " FILE Send output to FILE", " stdout Send output to stdout", |
︙ | ︙ | |||
4990 4991 4992 4993 4994 4995 4996 | char *zPat; if( zPattern==0 || zPattern[0]=='0' || cli_strcmp(zPattern,"-a")==0 || cli_strcmp(zPattern,"-all")==0 || cli_strcmp(zPattern,"--all")==0 ){ | < < | < < < < < < | < < | < < < < < < < < < < < < < < < | < > | | | | | | < < < < | | 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 | char *zPat; if( zPattern==0 || zPattern[0]=='0' || cli_strcmp(zPattern,"-a")==0 || cli_strcmp(zPattern,"-all")==0 || cli_strcmp(zPattern,"--all")==0 ){ /* Show all commands, but only one line per command */ if( zPattern==0 ) zPattern = ""; for(i=0; i<ArraySize(azHelp); i++){ if( azHelp[i][0]=='.' || zPattern[0] ){ utf8_printf(out, "%s\n", azHelp[i]); n++; } } }else{ /* Look for commands that for which zPattern is an exact prefix */ zPat = sqlite3_mprintf(".%s*", zPattern); shell_check_oom(zPat); for(i=0; i<ArraySize(azHelp); i++){ if( sqlite3_strglob(zPat, azHelp[i])==0 ){ utf8_printf(out, "%s\n", azHelp[i]); j = i+1; n++; } } sqlite3_free(zPat); if( n ){ if( n==1 ){ /* when zPattern is a prefix of exactly one command, then include the ** details of that command, which should begin at offset j */ while( j<ArraySize(azHelp)-1 && azHelp[j][0]!='.' ){ utf8_printf(out, "%s\n", azHelp[j]); j++; } } return n; } /* Look for commands that contain zPattern anywhere. Show the complete ** text of all commands that match. */ zPat = sqlite3_mprintf("%%%s%%", zPattern); shell_check_oom(zPat); for(i=0; i<ArraySize(azHelp); i++){ if( azHelp[i][0]=='.' ) j = i; if( sqlite3_strlike(zPat, azHelp[i], 0)==0 ){ utf8_printf(out, "%s\n", azHelp[j]); while( j<ArraySize(azHelp)-1 && azHelp[j+1][0]!='.' ){ j++; utf8_printf(out, "%s\n", azHelp[j]); } i = j; n++; } } |
︙ | ︙ | |||
5094 5095 5096 5097 5098 5099 5100 | ** is undefined in this case. */ static char *readFile(const char *zName, int *pnByte){ FILE *in = fopen(zName, "rb"); long nIn; size_t nRead; char *pBuf; | < | < < < < < | < < < < < | 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 | ** is undefined in this case. */ static char *readFile(const char *zName, int *pnByte){ FILE *in = fopen(zName, "rb"); long nIn; size_t nRead; char *pBuf; if( in==0 ) return 0; fseek(in, 0, SEEK_END); nIn = ftell(in); rewind(in); pBuf = sqlite3_malloc64( nIn+1 ); if( pBuf==0 ){ fclose(in); return 0; } nRead = fread(pBuf, nIn, 1, in); fclose(in); if( nRead!=1 ){ sqlite3_free(pBuf); return 0; } pBuf[nIn] = 0; if( pnByte ) *pnByte = nIn; return pBuf; } |
︙ | ︙ | |||
5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 | p->lineno = nLine; } sqlite3_free(a); utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine); return 0; } #endif /* SQLITE_OMIT_DESERIALIZE */ /* ** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X. */ static void shellUSleepFunc( sqlite3_context *context, int argcUnused, sqlite3_value **argv ){ int sleep = sqlite3_value_int(argv[0]); (void)argcUnused; sqlite3_sleep(sleep/1000); sqlite3_result_int(context, sleep); } /* Flags for open_db(). ** ** The default behavior of open_db() is to exit(1) if the database fails to ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error ** but still returns without calling exit. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 | p->lineno = nLine; } sqlite3_free(a); utf8_printf(stderr,"Error on line %d of --hexdb input\n", nLine); return 0; } #endif /* SQLITE_OMIT_DESERIALIZE */ /* ** Scalar function "shell_int32". The first argument to this function ** must be a blob. The second a non-negative integer. This function ** reads and returns a 32-bit big-endian integer from byte ** offset (4*<arg2>) of the blob. */ static void shellInt32( sqlite3_context *context, int argc, sqlite3_value **argv ){ const unsigned char *pBlob; int nBlob; int iInt; UNUSED_PARAMETER(argc); nBlob = sqlite3_value_bytes(argv[0]); pBlob = (const unsigned char*)sqlite3_value_blob(argv[0]); iInt = sqlite3_value_int(argv[1]); if( iInt>=0 && (iInt+1)*4<=nBlob ){ const unsigned char *a = &pBlob[iInt*4]; sqlite3_int64 iVal = ((sqlite3_int64)a[0]<<24) + ((sqlite3_int64)a[1]<<16) + ((sqlite3_int64)a[2]<< 8) + ((sqlite3_int64)a[3]<< 0); sqlite3_result_int64(context, iVal); } } /* ** Scalar function "shell_idquote(X)" returns string X quoted as an identifier, ** using "..." with internal double-quote characters doubled. */ static void shellIdQuote( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zName = (const char*)sqlite3_value_text(argv[0]); UNUSED_PARAMETER(argc); if( zName ){ char *z = sqlite3_mprintf("\"%w\"", zName); sqlite3_result_text(context, z, -1, sqlite3_free); } } /* ** Scalar function "usleep(X)" invokes sqlite3_sleep(X) and returns X. */ static void shellUSleepFunc( sqlite3_context *context, int argcUnused, sqlite3_value **argv ){ int sleep = sqlite3_value_int(argv[0]); (void)argcUnused; sqlite3_sleep(sleep/1000); sqlite3_result_int(context, sleep); } /* ** Scalar function "shell_escape_crnl" used by the .recover command. ** The argument passed to this function is the output of built-in ** function quote(). If the first character of the input is "'", ** indicating that the value passed to quote() was a text value, ** then this function searches the input for "\n" and "\r" characters ** and adds a wrapper similar to the following: ** ** replace(replace(<input>, '\n', char(10), '\r', char(13)); ** ** Or, if the first character of the input is not "'", then a copy ** of the input is returned. */ static void shellEscapeCrnl( sqlite3_context *context, int argc, sqlite3_value **argv ){ const char *zText = (const char*)sqlite3_value_text(argv[0]); UNUSED_PARAMETER(argc); if( zText && zText[0]=='\'' ){ i64 nText = sqlite3_value_bytes(argv[0]); i64 i; char zBuf1[20]; char zBuf2[20]; const char *zNL = 0; const char *zCR = 0; i64 nCR = 0; i64 nNL = 0; for(i=0; zText[i]; i++){ if( zNL==0 && zText[i]=='\n' ){ zNL = unused_string(zText, "\\n", "\\012", zBuf1); nNL = strlen(zNL); } if( zCR==0 && zText[i]=='\r' ){ zCR = unused_string(zText, "\\r", "\\015", zBuf2); nCR = strlen(zCR); } } if( zNL || zCR ){ i64 iOut = 0; i64 nMax = (nNL > nCR) ? nNL : nCR; i64 nAlloc = nMax * nText + (nMax+64)*2; char *zOut = (char*)sqlite3_malloc64(nAlloc); if( zOut==0 ){ sqlite3_result_error_nomem(context); return; } if( zNL && zCR ){ memcpy(&zOut[iOut], "replace(replace(", 16); iOut += 16; }else{ memcpy(&zOut[iOut], "replace(", 8); iOut += 8; } for(i=0; zText[i]; i++){ if( zText[i]=='\n' ){ memcpy(&zOut[iOut], zNL, nNL); iOut += nNL; }else if( zText[i]=='\r' ){ memcpy(&zOut[iOut], zCR, nCR); iOut += nCR; }else{ zOut[iOut] = zText[i]; iOut++; } } if( zNL ){ memcpy(&zOut[iOut], ",'", 2); iOut += 2; memcpy(&zOut[iOut], zNL, nNL); iOut += nNL; memcpy(&zOut[iOut], "', char(10))", 12); iOut += 12; } if( zCR ){ memcpy(&zOut[iOut], ",'", 2); iOut += 2; memcpy(&zOut[iOut], zCR, nCR); iOut += nCR; memcpy(&zOut[iOut], "', char(13))", 12); iOut += 12; } sqlite3_result_text(context, zOut, iOut, SQLITE_TRANSIENT); sqlite3_free(zOut); return; } } sqlite3_result_value(context, argv[0]); } /* Flags for open_db(). ** ** The default behavior of open_db() is to exit(1) if the database fails to ** open. The OPEN_DB_KEEPALIVE flag changes that so that it prints an error ** but still returns without calling exit. ** |
︙ | ︙ | |||
5382 5383 5384 5385 5386 5387 5388 | zDbFilename, sqlite3_errmsg(p->db)); if( openFlags & OPEN_DB_KEEPALIVE ){ sqlite3_open(":memory:", &p->db); return; } exit(1); } | < < < < < < < < < < < > > > | 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 | zDbFilename, sqlite3_errmsg(p->db)); if( openFlags & OPEN_DB_KEEPALIVE ){ sqlite3_open(":memory:", &p->db); return; } exit(1); } #ifndef SQLITE_OMIT_LOAD_EXTENSION sqlite3_enable_load_extension(p->db, 1); #endif sqlite3_shathree_init(p->db, 0, 0); sqlite3_uint_init(p->db, 0, 0); sqlite3_decimal_init(p->db, 0, 0); sqlite3_base64_init(p->db, 0, 0); sqlite3_base85_init(p->db, 0, 0); sqlite3_regexp_init(p->db, 0, 0); sqlite3_ieee_init(p->db, 0, 0); sqlite3_series_init(p->db, 0, 0); #ifndef SQLITE_SHELL_FIDDLE sqlite3_fileio_init(p->db, 0, 0); sqlite3_completion_init(p->db, 0, 0); #endif #if SQLITE_SHELL_HAVE_RECOVER sqlite3_dbdata_init(p->db, 0, 0); #endif #ifdef SQLITE_HAVE_ZLIB if( !p->bSafeModePersist ){ sqlite3_zipfile_init(p->db, 0, 0); sqlite3_sqlar_init(p->db, 0, 0); } #endif #ifdef SQLITE_SHELL_EXTFUNCS |
︙ | ︙ | |||
5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 | sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, shellModuleSchema, 0, 0); sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, shellPutsFunc, 0, 0); sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0, shellUSleepFunc, 0, 0); #ifndef SQLITE_NOHAVE_SYSTEM sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); | > > > > > > | 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 | sqlite3_create_function(p->db, "shell_add_schema", 3, SQLITE_UTF8, 0, shellAddSchemaName, 0, 0); sqlite3_create_function(p->db, "shell_module_schema", 1, SQLITE_UTF8, 0, shellModuleSchema, 0, 0); sqlite3_create_function(p->db, "shell_putsnl", 1, SQLITE_UTF8, p, shellPutsFunc, 0, 0); sqlite3_create_function(p->db, "shell_escape_crnl", 1, SQLITE_UTF8, 0, shellEscapeCrnl, 0, 0); sqlite3_create_function(p->db, "shell_int32", 2, SQLITE_UTF8, 0, shellInt32, 0, 0); sqlite3_create_function(p->db, "shell_idquote", 1, SQLITE_UTF8, 0, shellIdQuote, 0, 0); sqlite3_create_function(p->db, "usleep",1,SQLITE_UTF8,0, shellUSleepFunc, 0, 0); #ifndef SQLITE_NOHAVE_SYSTEM sqlite3_create_function(p->db, "edit", 1, SQLITE_UTF8, 0, editFunc, 0, 0); sqlite3_create_function(p->db, "edit", 2, SQLITE_UTF8, 0, editFunc, 0, 0); |
︙ | ︙ | |||
5475 5476 5477 5478 5479 5480 5481 | int rc; int nData = 0; unsigned char *aData; if( p->openMode==SHELL_OPEN_DESERIALIZE ){ aData = (unsigned char*)readFile(zDbFilename, &nData); }else{ aData = readHexDb(p, &nData); | < | | > < | | < < < < | 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 | int rc; int nData = 0; unsigned char *aData; if( p->openMode==SHELL_OPEN_DESERIALIZE ){ aData = (unsigned char*)readFile(zDbFilename, &nData); }else{ aData = readHexDb(p, &nData); if( aData==0 ){ return; } } rc = sqlite3_deserialize(p->db, "main", aData, nData, nData, SQLITE_DESERIALIZE_RESIZEABLE | SQLITE_DESERIALIZE_FREEONCLOSE); if( rc ){ utf8_printf(stderr, "Error: sqlite3_deserialize() returns %d\n", rc); } if( p->szMax>0 ){ sqlite3_file_control(p->db, "main", SQLITE_FCNTL_SIZE_LIMIT, &p->szMax); } } #endif } if( p->bSafeModePersist && p->db!=0 ){ sqlite3_set_authorizer(p->db, safeModeAuth, p); } } /* ** Attempt to close the databaes connection. Report errors. */ void close_db(sqlite3 *db){ |
︙ | ︙ | |||
5556 5557 5558 5559 5560 5561 5562 | static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ i64 nLine = strlen(zLine); i64 i, iStart; sqlite3_stmt *pStmt = 0; char *zSql; char zBuf[1000]; | | | | 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 | static void linenoise_completion(const char *zLine, linenoiseCompletions *lc){ i64 nLine = strlen(zLine); i64 i, iStart; sqlite3_stmt *pStmt = 0; char *zSql; char zBuf[1000]; if( nLine>sizeof(zBuf)-30 ) return; if( zLine[0]=='.' || zLine[0]=='#') return; for(i=nLine-1; i>=0 && (isalnum(zLine[i]) || zLine[i]=='_'); i--){} if( i==nLine-1 ) return; iStart = i+1; memcpy(zBuf, zLine, iStart); zSql = sqlite3_mprintf("SELECT DISTINCT candidate COLLATE nocase" " FROM completion(%Q,%Q) ORDER BY 1", &zLine[iStart], zLine); shell_check_oom(zSql); sqlite3_prepare_v2(globalDb, zSql, -1, &pStmt, 0); sqlite3_free(zSql); sqlite3_exec(globalDb, "PRAGMA page_count", 0, 0, 0); /* Load the schema */ while( sqlite3_step(pStmt)==SQLITE_ROW ){ const char *zCompletion = (const char*)sqlite3_column_text(pStmt, 0); int nCompletion = sqlite3_column_bytes(pStmt, 0); if( iStart+nCompletion < sizeof(zBuf)-1 && zCompletion ){ memcpy(zBuf+iStart, zCompletion, nCompletion+1); linenoiseAddCompletion(lc, zBuf); } } sqlite3_finalize(pStmt); } #endif |
︙ | ︙ | |||
5596 5597 5598 5599 5600 5601 5602 | ** \f -> form feed ** \r -> carriage return ** \s -> space ** \" -> " ** \' -> ' ** \\ -> backslash ** \NNN -> ascii character NNN in octal | < | 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 | ** \f -> form feed ** \r -> carriage return ** \s -> space ** \" -> " ** \' -> ' ** \\ -> backslash ** \NNN -> ascii character NNN in octal */ static void resolve_backslashes(char *z){ int i, j; char c; while( *z && *z!='\\' ) z++; for(i=j=0; (c = z[i])!=0; i++, j++){ if( c=='\\' && z[i+1]!=0 ){ |
︙ | ︙ | |||
5625 5626 5627 5628 5629 5630 5631 | c = '\r'; }else if( c=='"' ){ c = '"'; }else if( c=='\'' ){ c = '\''; }else if( c=='\\' ){ c = '\\'; | < < < < < < < < < | 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 | c = '\r'; }else if( c=='"' ){ c = '"'; }else if( c=='\'' ){ c = '\''; }else if( c=='\\' ){ c = '\\'; }else if( c>='0' && c<='7' ){ c -= '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; c = (c<<3) + z[i] - '0'; if( z[i+1]>='0' && z[i+1]<='7' ){ i++; |
︙ | ︙ | |||
5733 5734 5735 5736 5737 5738 5739 | const char *zSql; i64 nSql; if( p->traceOut==0 ) return 0; if( mType==SQLITE_TRACE_CLOSE ){ utf8_printf(p->traceOut, "-- closing database connection\n"); return 0; } | | | 5637 5638 5639 5640 5641 5642 5643 5644 5645 5646 5647 5648 5649 5650 5651 | const char *zSql; i64 nSql; if( p->traceOut==0 ) return 0; if( mType==SQLITE_TRACE_CLOSE ){ utf8_printf(p->traceOut, "-- closing database connection\n"); return 0; } if( mType!=SQLITE_TRACE_ROW && ((const char*)pX)[0]=='-' ){ zSql = (const char*)pX; }else{ pStmt = (sqlite3_stmt*)pP; switch( p->eTraceType ){ case SHELL_TRACE_EXPANDED: { zSql = sqlite3_expanded_sql(pStmt); break; |
︙ | ︙ | |||
5765 5766 5767 5768 5769 5770 5771 | switch( mType ){ case SQLITE_TRACE_ROW: case SQLITE_TRACE_STMT: { utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql); break; } case SQLITE_TRACE_PROFILE: { | | | 5669 5670 5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681 5682 5683 | switch( mType ){ case SQLITE_TRACE_ROW: case SQLITE_TRACE_STMT: { utf8_printf(p->traceOut, "%.*s;\n", (int)nSql, zSql); break; } case SQLITE_TRACE_PROFILE: { sqlite3_int64 nNanosec = *(sqlite3_int64*)pX; utf8_printf(p->traceOut, "%.*s; -- %lld ns\n", (int)nSql, zSql, nNanosec); break; } } return 0; } #endif |
︙ | ︙ | |||
5841 5842 5843 5844 5845 5846 5847 | ** + Keep track of the line number in p->nLine. ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ int c; | | | | 5745 5746 5747 5748 5749 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 | ** + Keep track of the line number in p->nLine. ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ static char *SQLITE_CDECL csv_read_one_field(ImportCtx *p){ int c; int cSep = p->cColSep; int rSep = p->cRowSep; p->n = 0; c = fgetc(p->in); if( c==EOF || seenInterrupt ){ p->cTerm = EOF; return 0; } if( c=='"' ){ |
︙ | ︙ | |||
5931 5932 5933 5934 5935 5936 5937 | ** + Keep track of the row number in p->nLine. ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ int c; | | | | 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 | ** + Keep track of the row number in p->nLine. ** + Store the character that terminates the field in p->cTerm. Store ** EOF on end-of-file. ** + Report syntax errors on stderr */ static char *SQLITE_CDECL ascii_read_one_field(ImportCtx *p){ int c; int cSep = p->cColSep; int rSep = p->cRowSep; p->n = 0; c = fgetc(p->in); if( c==EOF || seenInterrupt ){ p->cTerm = EOF; return 0; } while( c!=EOF && c!=cSep && c!=rSep ){ |
︙ | ︙ | |||
6230 6231 6232 6233 6234 6235 6236 | if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ res = sqlite3_column_int(pStmt,0); } sqlite3_finalize(pStmt); return res; } | | | 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 | if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){ res = sqlite3_column_int(pStmt,0); } sqlite3_finalize(pStmt); return res; } #if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB) /* ** Convert a 2-byte or 4-byte big-endian integer into a native integer */ static unsigned int get2byteInt(unsigned char *a){ return (a[0]<<8) + a[1]; } static unsigned int get4byteInt(unsigned char *a){ |
︙ | ︙ | |||
6293 6294 6295 6296 6297 6298 6299 | sqlite3_finalize(pStmt); return 1; } sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); if( sqlite3_step(pStmt)==SQLITE_ROW && sqlite3_column_bytes(pStmt,0)>100 ){ | | < < | 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 | sqlite3_finalize(pStmt); return 1; } sqlite3_bind_text(pStmt, 1, zDb, -1, SQLITE_STATIC); if( sqlite3_step(pStmt)==SQLITE_ROW && sqlite3_column_bytes(pStmt,0)>100 ){ memcpy(aHdr, sqlite3_column_blob(pStmt,0), 100); sqlite3_finalize(pStmt); }else{ raw_printf(stderr, "unable to read database header\n"); sqlite3_finalize(pStmt); return 1; } i = get2byteInt(aHdr+16); |
︙ | ︙ | |||
7112 7113 7114 7115 7116 7117 7118 | zArg = azArg[++iArg]; } if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR; } } } } | < < < | | 7014 7015 7016 7017 7018 7019 7020 7021 7022 7023 7024 7025 7026 7027 7028 | zArg = azArg[++iArg]; } if( arProcessSwitch(pAr, pMatch->eSwitch, zArg) ) return SQLITE_ERROR; } } } } return SQLITE_OK; } /* ** This function assumes that all arguments within the ArCommand.azArg[] ** array refer to archive members, as for the --extract, --list or --remove ** commands. It checks that each of them are "present". If any specified |
︙ | ︙ | |||
7881 7882 7883 7884 7885 7886 7887 | rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); rc_err_oom_die(rc); rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); rc_err_oom_die(rc); sqlite3_bind_int(pStmt, 1, nDigits); rc = sqlite3_step(pStmt); sqlite3_finalize(pStmt); | | | 7780 7781 7782 7783 7784 7785 7786 7787 7788 7789 7790 7791 7792 7793 7794 | rc = sqlite3_exec(*pDb, zSetReps, 0, 0, 0); rc_err_oom_die(rc); rc = sqlite3_prepare_v2(*pDb, zRenameRank, -1, &pStmt, 0); rc_err_oom_die(rc); sqlite3_bind_int(pStmt, 1, nDigits); rc = sqlite3_step(pStmt); sqlite3_finalize(pStmt); assert(rc==SQLITE_DONE); } assert(db_int(*pDb, zHasDupes)==0); /* Consider: remove this */ rc = sqlite3_prepare_v2(*pDb, zCollectVar, -1, &pStmt, 0); rc_err_oom_die(rc); rc = sqlite3_step(pStmt); if( rc==SQLITE_ROW ){ zColsSpec = sqlite3_mprintf("%s", sqlite3_column_text(pStmt, 0)); |
︙ | ︙ | |||
8131 8132 8133 8134 8135 8136 8137 8138 8139 8140 8141 8142 8143 8144 | if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ char *zRes = 0; output_reset(p); if( nArg!=2 ){ raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); rc = 2; }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ rc = 2; }else if( testcase_glob(azArg[1],zRes)==0 ){ utf8_printf(stderr, "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", p->zTestcase, azArg[1], zRes); rc = 1; }else{ | > | 8030 8031 8032 8033 8034 8035 8036 8037 8038 8039 8040 8041 8042 8043 8044 | if( c=='c' && n>=3 && cli_strncmp(azArg[0], "check", n)==0 ){ char *zRes = 0; output_reset(p); if( nArg!=2 ){ raw_printf(stderr, "Usage: .check GLOB-PATTERN\n"); rc = 2; }else if( (zRes = readFile("testcase-out.txt", 0))==0 ){ raw_printf(stderr, "Error: cannot read 'testcase-out.txt'\n"); rc = 2; }else if( testcase_glob(azArg[1],zRes)==0 ){ utf8_printf(stderr, "testcase-%s FAILED\n Expected: [%s]\n Got: [%s]\n", p->zTestcase, azArg[1], zRes); rc = 1; }else{ |
︙ | ︙ | |||
8260 8261 8262 8263 8264 8265 8266 | { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, | < < | 8160 8161 8162 8163 8164 8165 8166 8167 8168 8169 8170 8171 8172 8173 | { "enable_view", SQLITE_DBCONFIG_ENABLE_VIEW }, { "fts3_tokenizer", SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER }, { "legacy_alter_table", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "legacy_file_format", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, { "load_extension", SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION }, { "no_ckpt_on_close", SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE }, { "reset_database", SQLITE_DBCONFIG_RESET_DATABASE }, { "trigger_eqp", SQLITE_DBCONFIG_TRIGGER_EQP }, { "trusted_schema", SQLITE_DBCONFIG_TRUSTED_SCHEMA }, { "writable_schema", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, }; int ii, v; open_db(p, 0); for(ii=0; ii<ArraySize(aDbConfig); ii++){ |
︙ | ︙ | |||
8813 8814 8815 8816 8817 8818 8819 | nSep = strlen30(p->rowSeparator); } if( nSep>1 ){ raw_printf(stderr, "Error: multi-character row separators not allowed" " for import\n"); goto meta_command_exit; } | | | | 8711 8712 8713 8714 8715 8716 8717 8718 8719 8720 8721 8722 8723 8724 8725 8726 | nSep = strlen30(p->rowSeparator); } if( nSep>1 ){ raw_printf(stderr, "Error: multi-character row separators not allowed" " for import\n"); goto meta_command_exit; } sCtx.cColSep = p->colSeparator[0]; sCtx.cRowSep = p->rowSeparator[0]; } sCtx.zFile = zFile; sCtx.nLine = 1; if( sCtx.zFile[0]=='|' ){ #ifdef SQLITE_OMIT_POPEN raw_printf(stderr, "Error: pipes are not supported in this OS\n"); goto meta_command_exit; |
︙ | ︙ | |||
9010 9011 9012 9013 9014 9015 9016 | char *zSql; char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ int i; | < < < < < < | 8908 8909 8910 8911 8912 8913 8914 8915 8916 8917 8918 8919 8920 8921 | char *zSql; char *zCollist = 0; sqlite3_stmt *pStmt; int tnum = 0; int isWO = 0; /* True if making an imposter of a WITHOUT ROWID table */ int lenPK = 0; /* Length of the PRIMARY KEY string for isWO tables */ int i; if( !(nArg==3 || (nArg==2 && sqlite3_stricmp(azArg[1],"off")==0)) ){ utf8_printf(stderr, "Usage: .imposter INDEX IMPOSTER\n" " .imposter off\n"); /* Also allowed, but not documented: ** ** .imposter TABLE IMPOSTER ** |
︙ | ︙ | |||
9200 9201 9202 9203 9204 9205 9206 | }else #if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE) if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){ const char *zFile, *zProc; char *zErrMsg = 0; failIfSafeMode(p, "cannot run .load in safe mode"); | | < > > < < < < < < < < < > | 9092 9093 9094 9095 9096 9097 9098 9099 9100 9101 9102 9103 9104 9105 9106 9107 9108 9109 9110 9111 9112 9113 9114 9115 9116 9117 9118 9119 9120 9121 9122 9123 9124 9125 9126 9127 9128 9129 9130 9131 9132 9133 9134 9135 | }else #if !defined(SQLITE_OMIT_LOAD_EXTENSION) && !defined(SQLITE_SHELL_FIDDLE) if( c=='l' && cli_strncmp(azArg[0], "load", n)==0 ){ const char *zFile, *zProc; char *zErrMsg = 0; failIfSafeMode(p, "cannot run .load in safe mode"); if( nArg<2 ){ raw_printf(stderr, "Usage: .load FILE ?ENTRYPOINT?\n"); rc = 1; goto meta_command_exit; } zFile = azArg[1]; zProc = nArg>=3 ? azArg[2] : 0; open_db(p, 0); rc = sqlite3_load_extension(p->db, zFile, zProc, &zErrMsg); if( rc!=SQLITE_OK ){ utf8_printf(stderr, "Error: %s\n", zErrMsg); sqlite3_free(zErrMsg); rc = 1; } }else #endif #ifndef SQLITE_SHELL_FIDDLE if( c=='l' && cli_strncmp(azArg[0], "log", n)==0 ){ failIfSafeMode(p, "cannot run .log in safe mode"); if( nArg!=2 ){ raw_printf(stderr, "Usage: .log FILENAME\n"); rc = 1; }else{ const char *zFile = azArg[1]; output_file_close(p->pLog); p->pLog = output_file_open(zFile, 0); } }else #endif if( c=='m' && cli_strncmp(azArg[0], "mode", n)==0 ){ const char *zMode = 0; const char *zTabname = 0; int i, n2; ColModeOpts cmOpts = ColModeOpts_default; for(i=1; i<nArg; i++){ |
︙ | ︙ | |||
9872 9873 9874 9875 9876 9877 9878 | if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){ if( nArg==2 ){ if( cli_strcmp(azArg[1], "est")==0 ){ p->scanstatsOn = 2; }else{ p->scanstatsOn = (u8)booleanValue(azArg[1]); } | < < < < | 9757 9758 9759 9760 9761 9762 9763 9764 9765 9766 9767 9768 9769 9770 | if( c=='s' && cli_strncmp(azArg[0], "scanstats", n)==0 ){ if( nArg==2 ){ if( cli_strcmp(azArg[1], "est")==0 ){ p->scanstatsOn = 2; }else{ p->scanstatsOn = (u8)booleanValue(azArg[1]); } #ifndef SQLITE_ENABLE_STMT_SCANSTATUS raw_printf(stderr, "Warning: .scanstats not available in this build.\n"); #endif }else{ raw_printf(stderr, "Usage: .scanstats on|off|est\n"); rc = 1; } |
︙ | ︙ | |||
10525 10526 10527 10528 10529 10530 10531 | "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n" "|| ' AND typeof('||cname||')=''text'' ',\n" "' OR ') as query, tname from tabcols group by tname)" , zRevText); shell_check_oom(zRevText); if( bDebug ) utf8_printf(p->out, "%s\n", zRevText); lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0); | < | < < < | | | | | | | | < < | | | | | | | | | | | | | < < | 10406 10407 10408 10409 10410 10411 10412 10413 10414 10415 10416 10417 10418 10419 10420 10421 10422 10423 10424 10425 10426 10427 10428 10429 10430 10431 10432 10433 10434 10435 10436 10437 10438 10439 10440 10441 | "||group_concat('CAST(CAST('||cname||' AS BLOB) AS TEXT)<>'||cname\n" "|| ' AND typeof('||cname||')=''text'' ',\n" "' OR ') as query, tname from tabcols group by tname)" , zRevText); shell_check_oom(zRevText); if( bDebug ) utf8_printf(p->out, "%s\n", zRevText); lrc = sqlite3_prepare_v2(p->db, zRevText, -1, &pStmt, 0); assert(lrc==SQLITE_OK); if( zLike ) sqlite3_bind_text(pStmt,1,zLike,-1,SQLITE_STATIC); lrc = SQLITE_ROW==sqlite3_step(pStmt); if( lrc ){ const char *zGenQuery = (char*)sqlite3_column_text(pStmt,0); sqlite3_stmt *pCheckStmt; lrc = sqlite3_prepare_v2(p->db, zGenQuery, -1, &pCheckStmt, 0); if( bDebug ) utf8_printf(p->out, "%s\n", zGenQuery); if( SQLITE_OK==lrc ){ if( SQLITE_ROW==sqlite3_step(pCheckStmt) ){ double countIrreversible = sqlite3_column_double(pCheckStmt, 0); if( countIrreversible>0 ){ int sz = (int)(countIrreversible + 0.5); utf8_printf(stderr, "Digest includes %d invalidly encoded text field%s.\n", sz, (sz>1)? "s": ""); } } sqlite3_finalize(pCheckStmt); } sqlite3_finalize(pStmt); } sqlite3_free(zRevText); } #endif /* !defined(*_OMIT_SCHEMA_PRAGMAS) && !defined(*_OMIT_VIRTUALTABLE) */ sqlite3_free(zSql); }else #if !defined(SQLITE_NOHAVE_SYSTEM) && !defined(SQLITE_SHELL_FIDDLE) |
︙ | ︙ | |||
10817 10818 10819 10820 10821 10822 10823 | int testctrl = -1; int iCtrl = -1; int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ int isOk = 0; int i, n2; const char *zCmd = 0; | < < < < < < | 10690 10691 10692 10693 10694 10695 10696 10697 10698 10699 10700 10701 10702 10703 | int testctrl = -1; int iCtrl = -1; int rc2 = 0; /* 0: usage. 1: %d 2: %x 3: no-output */ int isOk = 0; int i, n2; const char *zCmd = 0; open_db(p, 0); zCmd = nArg>=2 ? azArg[1] : "help"; /* The argument can optionally begin with "-" or "--" */ if( zCmd[0]=='-' && zCmd[1] ){ zCmd++; if( zCmd[0]=='-' && zCmd[1] ) zCmd++; |
︙ | ︙ | |||
11631 11632 11633 11634 11635 11636 11637 | free(home_dir); home_dir = 0; return 0; } if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ | | | 11498 11499 11500 11501 11502 11503 11504 11505 11506 11507 11508 11509 11510 11511 11512 | free(home_dir); home_dir = 0; return 0; } if( home_dir ) return home_dir; #if !defined(_WIN32) && !defined(WIN32) && !defined(_WIN32_WCE) \ && !defined(__RTP__) && !defined(_WRS_KERNEL) { struct passwd *pwent; uid_t uid = getuid(); if( (pwent=getpwuid(uid)) != NULL) { home_dir = pwent->pw_dir; } } |
︙ | ︙ | |||
11770 11771 11772 11773 11774 11775 11776 | sqlite3_free(zBuf); } /* ** Show available command line options */ static const char zOptions[] = | < | 11637 11638 11639 11640 11641 11642 11643 11644 11645 11646 11647 11648 11649 11650 | sqlite3_free(zBuf); } /* ** Show available command line options */ static const char zOptions[] = #if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE) " -A ARGS... run \".archive ARGS\" and exit\n" #endif " -append append the database to the end of the file\n" " -ascii set output mode to 'ascii'\n" " -bail stop after hitting an error\n" " -batch force batch I/O\n" |
︙ | ︙ | |||
11822 11823 11824 11825 11826 11827 11828 | " -separator SEP set output column separator. Default: '|'\n" #ifdef SQLITE_ENABLE_SORTER_REFERENCES " -sorterref SIZE sorter references threshold size\n" #endif " -stats print memory stats before each finalize\n" " -table set output mode to 'table'\n" " -tabs set output mode to 'tabs'\n" | < < < < | | | 11688 11689 11690 11691 11692 11693 11694 11695 11696 11697 11698 11699 11700 11701 11702 11703 11704 11705 11706 11707 11708 11709 11710 11711 11712 11713 11714 11715 | " -separator SEP set output column separator. Default: '|'\n" #ifdef SQLITE_ENABLE_SORTER_REFERENCES " -sorterref SIZE sorter references threshold size\n" #endif " -stats print memory stats before each finalize\n" " -table set output mode to 'table'\n" " -tabs set output mode to 'tabs'\n" " -version show SQLite version\n" " -vfs NAME use NAME as the default VFS\n" #ifdef SQLITE_ENABLE_VFSTRACE " -vfstrace enable tracing of all VFS calls\n" #endif #ifdef SQLITE_HAVE_ZLIB " -zip open the file as a ZIP Archive\n" #endif ; static void usage(int showDetail){ utf8_printf(stderr, "Usage: %s [OPTIONS] FILENAME [SQL]\n" "FILENAME is the name of an SQLite database. A new database is created\n" "if the file does not previously exist.\n", Argv0); if( showDetail ){ utf8_printf(stderr, "OPTIONS include:\n%s", zOptions); }else{ raw_printf(stderr, "Use the -help option for additional information\n"); } exit(1); } |
︙ | ︙ | |||
11871 11872 11873 11874 11875 11876 11877 | data->normalMode = data->cMode = data->mode = MODE_List; data->autoExplain = 1; data->pAuxDb = &data->aAuxDb[0]; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; | < < < > | 11733 11734 11735 11736 11737 11738 11739 11740 11741 11742 11743 11744 11745 11746 11747 11748 11749 | data->normalMode = data->cMode = data->mode = MODE_List; data->autoExplain = 1; data->pAuxDb = &data->aAuxDb[0]; memcpy(data->colSeparator,SEP_Column, 2); memcpy(data->rowSeparator,SEP_Row, 2); data->showHeader = 0; data->shellFlgs = SHFLG_Lookaside; verify_uninitialized(); sqlite3_config(SQLITE_CONFIG_URI, 1); sqlite3_config(SQLITE_CONFIG_LOG, shellLog, data); sqlite3_config(SQLITE_CONFIG_MULTITHREAD); sqlite3_snprintf(sizeof(mainPrompt), mainPrompt,"sqlite> "); sqlite3_snprintf(sizeof(continuePrompt), continuePrompt," ...> "); } /* ** Output text to the console in a font that attracts extra attention. |
︙ | ︙ | |||
11918 11919 11920 11921 11922 11923 11924 | utf8_printf(stderr, "%s: Error: missing argument to %s\n", argv[0], argv[argc-1]); exit(1); } return argv[i]; } | < < < < | < < > > | < < < < < < < < < < < < < < | 11778 11779 11780 11781 11782 11783 11784 11785 11786 11787 11788 11789 11790 11791 11792 11793 11794 11795 11796 11797 11798 11799 11800 11801 11802 11803 11804 11805 11806 11807 11808 11809 11810 11811 11812 11813 11814 11815 11816 11817 11818 11819 11820 11821 11822 11823 11824 11825 11826 11827 11828 11829 11830 11831 11832 11833 11834 11835 11836 11837 11838 11839 11840 11841 11842 11843 11844 11845 11846 11847 11848 11849 11850 11851 11852 11853 11854 11855 11856 11857 11858 11859 11860 11861 11862 | utf8_printf(stderr, "%s: Error: missing argument to %s\n", argv[0], argv[argc-1]); exit(1); } return argv[i]; } #ifndef SQLITE_SHELL_IS_UTF8 # if (defined(_WIN32) || defined(WIN32)) \ && (defined(_MSC_VER) || (defined(UNICODE) && defined(__GNUC__))) # define SQLITE_SHELL_IS_UTF8 (0) # else # define SQLITE_SHELL_IS_UTF8 (1) # endif #endif #ifdef SQLITE_SHELL_FIDDLE # define main fiddle_main #endif #if SQLITE_SHELL_IS_UTF8 int SQLITE_CDECL main(int argc, char **argv){ #else int SQLITE_CDECL wmain(int argc, wchar_t **wargv){ char **argv; #endif #ifdef SQLITE_DEBUG sqlite3_int64 mem_main_enter = sqlite3_memory_used(); #endif char *zErrMsg = 0; #ifdef SQLITE_SHELL_FIDDLE # define data shellState #else ShellState data; #endif const char *zInitFile = 0; int i; int rc = 0; int warnInmemoryDb = 0; int readStdin = 1; int nCmd = 0; char **azCmd = 0; const char *zVfs = 0; /* Value of -vfs command-line option */ #if !SQLITE_SHELL_IS_UTF8 char **argvToFree = 0; int argcToFree = 0; #endif setBinaryMode(stdin, 0); setvbuf(stderr, 0, _IONBF, 0); /* Make sure stderr is unbuffered */ #ifdef SQLITE_SHELL_FIDDLE stdin_is_interactive = 0; stdout_is_console = 1; data.wasm.zDefaultDbName = "/fiddle.sqlite3"; #else stdin_is_interactive = isatty(0); stdout_is_console = isatty(1); #endif #if !defined(_WIN32_WCE) if( getenv("SQLITE_DEBUG_BREAK") ){ if( isatty(0) && isatty(2) ){ fprintf(stderr, "attach debugger to process %d and press any key to continue.\n", GETPID()); fgetc(stdin); }else{ #if defined(_WIN32) || defined(WIN32) #if SQLITE_OS_WINRT __debugbreak(); #else DebugBreak(); #endif #elif defined(SIGTRAP) raise(SIGTRAP); #endif } } #endif #if USE_SYSTEM_SQLITE+0!=1 if( cli_strncmp(sqlite3_sourceid(),SQLITE_SOURCE_ID,60)!=0 ){ utf8_printf(stderr, "SQLite header and source version mismatch\n%s\n%s\n", sqlite3_sourceid(), SQLITE_SOURCE_ID); exit(1); |
︙ | ︙ | |||
12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 12061 12062 12063 12064 12065 12066 12067 12068 12069 12070 | sqlite3_free(z); } sqlite3_shutdown(); #endif assert( argc>=1 && argv && argv[0] ); Argv0 = argv[0]; #ifdef SQLITE_SHELL_DBNAME_PROC { /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name ** of a C-function that will provide the name of the database file. Use ** this compile-time option to embed this shell program in larger ** applications. */ extern void SQLITE_SHELL_DBNAME_PROC(const char**); SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); warnInmemoryDb = 0; } #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ | > > > > > > > > > < < | < < < < | | 11888 11889 11890 11891 11892 11893 11894 11895 11896 11897 11898 11899 11900 11901 11902 11903 11904 11905 11906 11907 11908 11909 11910 11911 11912 11913 11914 11915 11916 11917 11918 11919 11920 11921 11922 11923 11924 11925 11926 11927 11928 11929 11930 11931 11932 11933 11934 11935 11936 11937 11938 11939 11940 11941 11942 11943 11944 11945 11946 11947 | sqlite3_free(z); } sqlite3_shutdown(); #endif assert( argc>=1 && argv && argv[0] ); Argv0 = argv[0]; /* Make sure we have a valid signal handler early, before anything ** else is done. */ #ifdef SIGINT signal(SIGINT, interrupt_handler); #elif (defined(_WIN32) || defined(WIN32)) && !defined(_WIN32_WCE) SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); #endif #ifdef SQLITE_SHELL_DBNAME_PROC { /* If the SQLITE_SHELL_DBNAME_PROC macro is defined, then it is the name ** of a C-function that will provide the name of the database file. Use ** this compile-time option to embed this shell program in larger ** applications. */ extern void SQLITE_SHELL_DBNAME_PROC(const char**); SQLITE_SHELL_DBNAME_PROC(&data.pAuxDb->zDbFilename); warnInmemoryDb = 0; } #endif /* Do an initial pass through the command-line argument to locate ** the name of the database file, the name of the initialization file, ** the size of the alternative malloc heap, ** and the first command to execute. */ verify_uninitialized(); for(i=1; i<argc; i++){ char *z; z = argv[i]; if( z[0]!='-' ){ if( data.aAuxDb->zDbFilename==0 ){ data.aAuxDb->zDbFilename = z; }else{ /* Excesss arguments are interpreted as SQL (or dot-commands) and ** mean that nothing is read from stdin */ readStdin = 0; nCmd++; azCmd = realloc(azCmd, sizeof(azCmd[0])*nCmd); shell_check_oom(azCmd); azCmd[nCmd-1] = z; } } if( z[1]=='-' ) z++; if( cli_strcmp(z,"-separator")==0 || cli_strcmp(z,"-nullvalue")==0 || cli_strcmp(z,"-newline")==0 || cli_strcmp(z,"-cmd")==0 ){ (void)cmdline_option_value(argc, argv, ++i); }else if( cli_strcmp(z,"-init")==0 ){ zInitFile = cmdline_option_value(argc, argv, ++i); |
︙ | ︙ | |||
12110 12111 12112 12113 12114 12115 12116 | #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) const char *zSize; sqlite3_int64 szHeap; zSize = cmdline_option_value(argc, argv, ++i); szHeap = integerValue(zSize); if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; | < < < < | 11955 11956 11957 11958 11959 11960 11961 11962 11963 11964 11965 11966 11967 11968 11969 11970 11971 11972 11973 11974 11975 11976 11977 11978 11979 11980 11981 11982 11983 11984 11985 11986 11987 11988 11989 11990 11991 11992 11993 11994 11995 | #if defined(SQLITE_ENABLE_MEMSYS3) || defined(SQLITE_ENABLE_MEMSYS5) const char *zSize; sqlite3_int64 szHeap; zSize = cmdline_option_value(argc, argv, ++i); szHeap = integerValue(zSize); if( szHeap>0x7fff0000 ) szHeap = 0x7fff0000; sqlite3_config(SQLITE_CONFIG_HEAP, malloc((int)szHeap), (int)szHeap, 64); #else (void)cmdline_option_value(argc, argv, ++i); #endif }else if( cli_strcmp(z,"-pagecache")==0 ){ sqlite3_int64 n, sz; sz = integerValue(cmdline_option_value(argc,argv,++i)); if( sz>70000 ) sz = 70000; if( sz<0 ) sz = 0; n = integerValue(cmdline_option_value(argc,argv,++i)); if( sz>0 && n>0 && 0xffffffffffffLL/sz<n ){ n = 0xffffffffffffLL/sz; } sqlite3_config(SQLITE_CONFIG_PAGECACHE, (n>0 && sz>0) ? malloc(n*sz) : 0, sz, n); data.shellFlgs |= SHFLG_Pagecache; }else if( cli_strcmp(z,"-lookaside")==0 ){ int n, sz; sz = (int)integerValue(cmdline_option_value(argc,argv,++i)); if( sz<0 ) sz = 0; n = (int)integerValue(cmdline_option_value(argc,argv,++i)); if( n<0 ) n = 0; sqlite3_config(SQLITE_CONFIG_LOOKASIDE, sz, n); if( sz*n==0 ) data.shellFlgs &= ~SHFLG_Lookaside; }else if( cli_strcmp(z,"-threadsafe")==0 ){ int n; n = (int)integerValue(cmdline_option_value(argc,argv,++i)); switch( n ){ case 0: sqlite3_config(SQLITE_CONFIG_SINGLETHREAD); break; case 2: sqlite3_config(SQLITE_CONFIG_MULTITHREAD); break; default: sqlite3_config(SQLITE_CONFIG_SERIALIZED); break; } #ifdef SQLITE_ENABLE_VFSTRACE }else if( cli_strcmp(z,"-vfstrace")==0 ){ |
︙ | ︙ | |||
12164 12165 12166 12167 12168 12169 12170 | #ifdef SQLITE_ENABLE_MULTIPLEX }else if( cli_strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiple_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }else if( cli_strcmp(z,"-mmap")==0 ){ sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); | < | < | 12005 12006 12007 12008 12009 12010 12011 12012 12013 12014 12015 12016 12017 12018 12019 12020 12021 12022 | #ifdef SQLITE_ENABLE_MULTIPLEX }else if( cli_strcmp(z,"-multiplex")==0 ){ extern int sqlite3_multiple_initialize(const char*,int); sqlite3_multiplex_initialize(0, 1); #endif }else if( cli_strcmp(z,"-mmap")==0 ){ sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); sqlite3_config(SQLITE_CONFIG_MMAP_SIZE, sz, sz); #ifdef SQLITE_ENABLE_SORTER_REFERENCES }else if( cli_strcmp(z,"-sorterref")==0 ){ sqlite3_int64 sz = integerValue(cmdline_option_value(argc,argv,++i)); sqlite3_config(SQLITE_CONFIG_SORTERREF_SIZE, (int)sz); #endif }else if( cli_strcmp(z,"-vfs")==0 ){ zVfs = cmdline_option_value(argc, argv, ++i); #ifdef SQLITE_HAVE_ZLIB }else if( cli_strcmp(z,"-zip")==0 ){ data.openMode = SHELL_OPEN_ZIPFILE; |
︙ | ︙ | |||
12203 12204 12205 12206 12207 12208 12209 | }else if( cli_strcmp(z, "-memtrace")==0 ){ sqlite3MemTraceActivate(stderr); }else if( cli_strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( cli_strcmp(z,"-nonce")==0 ){ free(data.zNonce); data.zNonce = strdup(argv[++i]); | < < < < | 12042 12043 12044 12045 12046 12047 12048 12049 12050 12051 12052 12053 12054 12055 12056 12057 12058 12059 12060 | }else if( cli_strcmp(z, "-memtrace")==0 ){ sqlite3MemTraceActivate(stderr); }else if( cli_strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( cli_strcmp(z,"-nonce")==0 ){ free(data.zNonce); data.zNonce = strdup(argv[++i]); }else if( cli_strcmp(z,"-safe")==0 ){ /* no-op - catch this on the second pass */ } } verify_uninitialized(); #ifdef SQLITE_SHELL_INIT_PROC { /* If the SQLITE_SHELL_INIT_PROC macro is defined, then it is the name ** of a C-function that will perform initialization actions on SQLite that ** occur just before or after sqlite3_initialize(). Use this compile-time |
︙ | ︙ | |||
12275 12276 12277 12278 12279 12280 12281 | /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization ** file is processed so that the command-line arguments will override ** settings in the initialization file. */ for(i=1; i<argc; i++){ char *z = argv[i]; | | | 12110 12111 12112 12113 12114 12115 12116 12117 12118 12119 12120 12121 12122 12123 12124 | /* Make a second pass through the command-line argument and set ** options. This second pass is delayed until after the initialization ** file is processed so that the command-line arguments will override ** settings in the initialization file. */ for(i=1; i<argc; i++){ char *z = argv[i]; if( z[0]!='-' ) continue; if( z[1]=='-' ){ z++; } if( cli_strcmp(z,"-init")==0 ){ i++; }else if( cli_strcmp(z,"-html")==0 ){ data.mode = MODE_Html; }else if( cli_strcmp(z,"-list")==0 ){ data.mode = MODE_List; |
︙ | ︙ | |||
12367 12368 12369 12370 12371 12372 12373 | }else if( cli_strcmp(z,"-version")==0 ){ printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); return 0; }else if( cli_strcmp(z,"-interactive")==0 ){ stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ stdin_is_interactive = 0; | < < < < | 12202 12203 12204 12205 12206 12207 12208 12209 12210 12211 12212 12213 12214 12215 | }else if( cli_strcmp(z,"-version")==0 ){ printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); return 0; }else if( cli_strcmp(z,"-interactive")==0 ){ stdin_is_interactive = 1; }else if( cli_strcmp(z,"-batch")==0 ){ stdin_is_interactive = 0; }else if( cli_strcmp(z,"-heap")==0 ){ i++; }else if( cli_strcmp(z,"-pagecache")==0 ){ i+=2; }else if( cli_strcmp(z,"-lookaside")==0 ){ i+=2; }else if( cli_strcmp(z,"-threadsafe")==0 ){ |
︙ | ︙ | |||
12441 12442 12443 12444 12445 12446 12447 | arDotCommand(&data, 1, argv+i, argc-i); } readStdin = 0; break; #endif }else if( cli_strcmp(z,"-safe")==0 ){ data.bSafeMode = data.bSafeModePersist = 1; | < < < < < < < < < < < | 12272 12273 12274 12275 12276 12277 12278 12279 12280 12281 12282 12283 12284 12285 12286 12287 12288 12289 12290 12291 12292 12293 12294 12295 12296 12297 12298 12299 12300 12301 12302 12303 12304 12305 12306 12307 | arDotCommand(&data, 1, argv+i, argc-i); } readStdin = 0; break; #endif }else if( cli_strcmp(z,"-safe")==0 ){ data.bSafeMode = data.bSafeModePersist = 1; }else{ utf8_printf(stderr,"%s: Error: unknown option: %s\n", Argv0, z); raw_printf(stderr,"Use -help for a list of options.\n"); return 1; } data.cMode = data.mode; } if( !readStdin ){ /* Run all arguments that do not begin with '-' as if they were separate ** command-line inputs, except for the argToSkip argument which contains ** the database filename. */ for(i=0; i<nCmd; i++){ if( azCmd[i][0]=='.' ){ rc = do_meta_command(azCmd[i], &data); if( rc ){ free(azCmd); return rc==2 ? 0 : rc; } }else{ open_db(&data, 0); rc = shell_exec(&data, azCmd[i], &zErrMsg); if( zErrMsg || rc ){ if( zErrMsg!=0 ){ utf8_printf(stderr,"Error: %s\n", zErrMsg); }else{ utf8_printf(stderr,"Error: unable to process SQL: %s\n", azCmd[i]); } |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 | ** file to the database file. ** ** <li>[[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode ** transaction open on the database or not. It is only available on unix.The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that ** currently has an SQL transaction open on the database. It is set to 0 if ** the database is not a wal-mode db, or if there is no such connection in any ** other process. This opcode cannot be used to detect transactions opened ** by clients within the current process, only within other processes. ** ** <li>[[SQLITE_FCNTL_CKSM_FILE]] | > > < | | | | | 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 | ** file to the database file. ** ** <li>[[SQLITE_FCNTL_CKPT_DONE]] ** The [SQLITE_FCNTL_CKPT_DONE] opcode is invoked from within a checkpoint ** in wal mode after the client has finished copying pages from the wal ** file to the database file, but before the *-shm file is updated to ** record the fact that the pages have been checkpointed. ** </ul> ** ** <li>[[SQLITE_FCNTL_EXTERNAL_READER]] ** The EXPERIMENTAL [SQLITE_FCNTL_EXTERNAL_READER] opcode is used to detect ** whether or not there is a database client in another process with a wal-mode ** transaction open on the database or not. It is only available on unix.The ** (void*) argument passed with this file-control should be a pointer to a ** value of type (int). The integer value is set to 1 if the database is a wal ** mode database and there exists at least one client in another process that ** currently has an SQL transaction open on the database. It is set to 0 if ** the database is not a wal-mode db, or if there is no such connection in any ** other process. This opcode cannot be used to detect transactions opened ** by clients within the current process, only within other processes. ** </ul> ** ** <li>[[SQLITE_FCNTL_CKSM_FILE]] ** Used by the cksmvfs VFS module only. ** ** <li>[[SQLITE_FCNTL_RESET_CACHE]] ** If there is currently no transaction open on the database, and the ** database is not a temp db, then this file-control purges the contents ** of the in-memory page cache. If there is an open transaction, or if ** the db is a temp-db, it is a no-op, not an error. ** </ul> */ #define SQLITE_FCNTL_LOCKSTATE 1 #define SQLITE_FCNTL_GET_LOCKPROXYFILE 2 #define SQLITE_FCNTL_SET_LOCKPROXYFILE 3 #define SQLITE_FCNTL_LAST_ERRNO 4 #define SQLITE_FCNTL_SIZE_HINT 5 |
︙ | ︙ | |||
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 | ** applications and so this routine is usually not necessary. It is ** provided to support rare applications with unusual needs. ** ** <b>The sqlite3_config() interface is not threadsafe. The application ** must ensure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running.</b> ** ** The first argument to sqlite3_config() is an integer ** [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** | > > > > > > > > < < < < < < < < < < < | 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 | ** applications and so this routine is usually not necessary. It is ** provided to support rare applications with unusual needs. ** ** <b>The sqlite3_config() interface is not threadsafe. The application ** must ensure that no other SQLite interfaces are invoked by other ** threads while sqlite3_config() is running.</b> ** ** The sqlite3_config() interface ** may only be invoked prior to library initialization using ** [sqlite3_initialize()] or after shutdown by [sqlite3_shutdown()]. ** ^If sqlite3_config() is called after [sqlite3_initialize()] and before ** [sqlite3_shutdown()] then it will return SQLITE_MISUSE. ** Note, however, that ^sqlite3_config() can be called as part of the ** implementation of an application-defined [sqlite3_os_init()]. ** ** The first argument to sqlite3_config() is an integer ** [configuration option] that determines ** what property of SQLite is to be configured. Subsequent arguments ** vary depending on the [configuration option] ** in the first argument. ** ** ^When a configuration option is set, sqlite3_config() returns [SQLITE_OK]. ** ^If the option is unknown or SQLite is unable to set the option ** then this routine returns a non-zero [error code]. */ int sqlite3_config(int, ...); /* |
︙ | ︙ | |||
1775 1776 1777 1778 1779 1780 1781 | /* ** CAPI3REF: Configuration Options ** KEYWORDS: {configuration option} ** ** These constants are the available integer configuration options that ** can be passed as the first argument to the [sqlite3_config()] interface. ** | < < < < < < < < < < < < < < < < < | 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 | /* ** CAPI3REF: Configuration Options ** KEYWORDS: {configuration option} ** ** These constants are the available integer configuration options that ** can be passed as the first argument to the [sqlite3_config()] interface. ** ** New configuration options may be added in future releases of SQLite. ** Existing configuration options might be discontinued. Applications ** should check the return code from [sqlite3_config()] to make sure that ** the call worked. The [sqlite3_config()] interface will return a ** non-zero [error code] if a discontinued or unsupported configuration option ** is invoked. ** |
︙ | ︙ | |||
2394 2395 2396 2397 2398 2399 2400 | ** behaves as it did prior to [version 3.24.0] (2018-06-04). See the ** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for ** additional information. This feature can also be turned on and off ** using the [PRAGMA legacy_alter_table] statement. ** </dd> ** ** [[SQLITE_DBCONFIG_DQS_DML]] | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 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 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 | ** behaves as it did prior to [version 3.24.0] (2018-06-04). See the ** "Compatibility Notice" on the [ALTER TABLE RENAME documentation] for ** additional information. This feature can also be turned on and off ** using the [PRAGMA legacy_alter_table] statement. ** </dd> ** ** [[SQLITE_DBCONFIG_DQS_DML]] ** <dt>SQLITE_DBCONFIG_DQS_DML</td> ** <dd>The SQLITE_DBCONFIG_DQS_DML option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DML statements ** only, that is DELETE, INSERT, SELECT, and UPDATE statements. The ** default value of this setting is determined by the [-DSQLITE_DQS] ** compile-time option. ** </dd> ** ** [[SQLITE_DBCONFIG_DQS_DDL]] ** <dt>SQLITE_DBCONFIG_DQS_DDL</td> ** <dd>The SQLITE_DBCONFIG_DQS option activates or deactivates ** the legacy [double-quoted string literal] misfeature for DDL statements, ** such as CREATE TABLE and CREATE INDEX. The ** default value of this setting is determined by the [-DSQLITE_DQS] ** compile-time option. ** </dd> ** ** [[SQLITE_DBCONFIG_TRUSTED_SCHEMA]] ** <dt>SQLITE_DBCONFIG_TRUSTED_SCHEMA</td> ** <dd>The SQLITE_DBCONFIG_TRUSTED_SCHEMA option tells SQLite to ** assume that database schemas are untainted by malicious content. ** When the SQLITE_DBCONFIG_TRUSTED_SCHEMA option is disabled, SQLite ** takes additional defensive steps to protect the application from harm ** including: ** <ul> ** <li> Prohibit the use of SQL functions inside triggers, views, ** CHECK constraints, DEFAULT clauses, expression indexes, ** partial indexes, or generated columns ** unless those functions are tagged with [SQLITE_INNOCUOUS]. ** <li> Prohibit the use of virtual tables inside of triggers or views ** unless those virtual tables are tagged with [SQLITE_VTAB_INNOCUOUS]. ** </ul> ** This setting defaults to "on" for legacy compatibility, however ** all applications are advised to turn it off if possible. This setting ** can also be controlled using the [PRAGMA trusted_schema] statement. ** </dd> ** ** [[SQLITE_DBCONFIG_LEGACY_FILE_FORMAT]] ** <dt>SQLITE_DBCONFIG_LEGACY_FILE_FORMAT</td> ** <dd>The SQLITE_DBCONFIG_LEGACY_FILE_FORMAT option activates or deactivates ** the legacy file format flag. When activated, this flag causes all newly ** created database file to have a schema format version number (the 4-byte ** integer found at offset 44 into the database header) of 1. This in turn ** means that the resulting database file will be readable and writable by ** any SQLite version back to 3.0.0 ([dateof:3.0.0]). Without this setting, ** newly created databases are generally not understandable by SQLite versions ** prior to 3.3.0 ([dateof:3.3.0]). As these words are written, there ** is now scarcely any need to generated database files that are compatible ** all the way back to version 3.0.0, and so this setting is of little ** practical use, but is provided so that SQLite can continue to claim the ** ability to generate new database files that are compatible with version ** 3.0.0. ** <p>Note that when the SQLITE_DBCONFIG_LEGACY_FILE_FORMAT setting is on, ** the [VACUUM] command will fail with an obscure error when attempting to ** process a table with generated columns and a descending index. This is ** not considered a bug since SQLite versions 3.3.0 and earlier do not support ** either generated columns or decending indexes. ** </dd> ** </dl> */ #define SQLITE_DBCONFIG_MAINDBNAME 1000 /* const char* */ #define SQLITE_DBCONFIG_LOOKASIDE 1001 /* void* int int */ #define SQLITE_DBCONFIG_ENABLE_FKEY 1002 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_TRIGGER 1003 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER 1004 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION 1005 /* int int* */ #define SQLITE_DBCONFIG_NO_CKPT_ON_CLOSE 1006 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_QPSG 1007 /* int int* */ #define SQLITE_DBCONFIG_TRIGGER_EQP 1008 /* int int* */ #define SQLITE_DBCONFIG_RESET_DATABASE 1009 /* int int* */ #define SQLITE_DBCONFIG_DEFENSIVE 1010 /* int int* */ #define SQLITE_DBCONFIG_WRITABLE_SCHEMA 1011 /* int int* */ #define SQLITE_DBCONFIG_LEGACY_ALTER_TABLE 1012 /* int int* */ #define SQLITE_DBCONFIG_DQS_DML 1013 /* int int* */ #define SQLITE_DBCONFIG_DQS_DDL 1014 /* int int* */ #define SQLITE_DBCONFIG_ENABLE_VIEW 1015 /* int int* */ #define SQLITE_DBCONFIG_LEGACY_FILE_FORMAT 1016 /* int int* */ #define SQLITE_DBCONFIG_TRUSTED_SCHEMA 1017 /* int int* */ #define SQLITE_DBCONFIG_MAX 1017 /* Largest DBCONFIG */ /* ** CAPI3REF: Enable Or Disable Extended Result Codes ** METHOD: sqlite3 ** ** ^The sqlite3_extended_result_codes() routine enables or disables the ** [extended result codes] feature of SQLite. ^The extended result |
︙ | ︙ | |||
6251 6252 6253 6254 6255 6256 6257 | ** requested from the operating system is returned. ** ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. | < < < < < < < | 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 | ** requested from the operating system is returned. ** ** ^SQLite implements this interface by calling the xSleep() ** method of the default [sqlite3_vfs] object. If the xSleep() method ** of the default VFS is not implemented correctly, or not implemented at ** all, then the behavior of sqlite3_sleep() may deviate from the description ** in the previous paragraphs. */ int sqlite3_sleep(int); /* ** CAPI3REF: Name Of The Folder Holding Temporary Files ** ** ^(If this global variable is made to point to a string which is |
︙ | ︙ | |||
9621 9622 9623 9624 9625 9626 9627 | ** prohibits that virtual table from being used from within triggers and ** views. ** </dd> ** ** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt> ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the | | < < < < < < < < < < | 9561 9562 9563 9564 9565 9566 9567 9568 9569 9570 9571 9572 9573 9574 9575 9576 9577 9578 9579 9580 9581 9582 9583 9584 9585 9586 | ** prohibits that virtual table from being used from within triggers and ** views. ** </dd> ** ** [[SQLITE_VTAB_INNOCUOUS]]<dt>SQLITE_VTAB_INNOCUOUS</dt> ** <dd>Calls of the form ** [sqlite3_vtab_config](db,SQLITE_VTAB_INNOCUOUS) from within the ** the [xConnect] or [xCreate] methods of a [virtual table] implmentation ** identify that virtual table as being safe to use from within triggers ** and views. Conceptually, the SQLITE_VTAB_INNOCUOUS tag means that the ** virtual table can do no serious harm even if it is controlled by a ** malicious hacker. Developers should avoid setting the SQLITE_VTAB_INNOCUOUS ** flag unless absolutely necessary. ** </dd> ** </dl> */ #define SQLITE_VTAB_CONSTRAINT_SUPPORT 1 #define SQLITE_VTAB_INNOCUOUS 2 #define SQLITE_VTAB_DIRECTONLY 3 /* ** CAPI3REF: Determine The Virtual Table Conflict Policy ** ** This function may only be called from within a call to the [xUpdate] method ** of a [virtual table] implementation for an INSERT or UPDATE operation. ^The ** value returned is one of [SQLITE_ROLLBACK], [SQLITE_IGNORE], [SQLITE_FAIL], |
︙ | ︙ | |||
9885 9886 9887 9888 9889 9890 9891 | ** processing, then these routines return [SQLITE_ERROR].)^ ** ** ^(Use these routines to access all values on the right-hand side ** of the IN constraint using code like the following: ** ** <blockquote><pre> ** for(rc=sqlite3_vtab_in_first(pList, &pVal); | | | 9815 9816 9817 9818 9819 9820 9821 9822 9823 9824 9825 9826 9827 9828 9829 | ** processing, then these routines return [SQLITE_ERROR].)^ ** ** ^(Use these routines to access all values on the right-hand side ** of the IN constraint using code like the following: ** ** <blockquote><pre> ** for(rc=sqlite3_vtab_in_first(pList, &pVal); ** rc==SQLITE_OK && pVal ** rc=sqlite3_vtab_in_next(pList, &pVal) ** ){ ** // do something with pVal ** } ** if( rc!=SQLITE_OK ){ ** // an error has occurred ** } |
︙ | ︙ | |||
10019 10020 10021 10022 10023 10024 10025 10026 10027 10028 10029 10030 10031 10032 10033 10034 10035 10036 10037 10038 | ** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECTID</dt> ** <dd>^The "int" variable pointed to by the V parameter will be set to the ** id for the X-th query plan element. The id value is unique within the ** statement. The select-id is the same value as is output in the first ** column of an [EXPLAIN QUERY PLAN] query. ** ** [[SQLITE_SCANSTAT_PARENTID]] <dt>SQLITE_SCANSTAT_PARENTID</dt> ** <dd>The "int" variable pointed to by the V parameter will be set to the ** the id of the parent of the current query element, if applicable, or ** to zero if the query element has no parent. This is the same value as ** returned in the second column of an [EXPLAIN QUERY PLAN] query. ** ** [[SQLITE_SCANSTAT_NCYCLE]] <dt>SQLITE_SCANSTAT_NCYCLE</dt> ** <dd>The sqlite3_int64 output value is set to the number of cycles, ** according to the processor time-stamp counter, that elapsed while the ** query element was being processed. This value is not available for ** all query elements - if it is unavailable the output variable is ** set to -1. | > < | 9949 9950 9951 9952 9953 9954 9955 9956 9957 9958 9959 9960 9961 9962 9963 9964 9965 9966 9967 9968 9969 9970 9971 9972 9973 9974 9975 9976 | ** description for the X-th loop. ** ** [[SQLITE_SCANSTAT_SELECTID]] <dt>SQLITE_SCANSTAT_SELECTID</dt> ** <dd>^The "int" variable pointed to by the V parameter will be set to the ** id for the X-th query plan element. The id value is unique within the ** statement. The select-id is the same value as is output in the first ** column of an [EXPLAIN QUERY PLAN] query. ** </dl> ** ** [[SQLITE_SCANSTAT_PARENTID]] <dt>SQLITE_SCANSTAT_PARENTID</dt> ** <dd>The "int" variable pointed to by the V parameter will be set to the ** the id of the parent of the current query element, if applicable, or ** to zero if the query element has no parent. This is the same value as ** returned in the second column of an [EXPLAIN QUERY PLAN] query. ** ** [[SQLITE_SCANSTAT_NCYCLE]] <dt>SQLITE_SCANSTAT_NCYCLE</dt> ** <dd>The sqlite3_int64 output value is set to the number of cycles, ** according to the processor time-stamp counter, that elapsed while the ** query element was being processed. This value is not available for ** all query elements - if it is unavailable the output variable is ** set to -1. */ #define SQLITE_SCANSTAT_NLOOP 0 #define SQLITE_SCANSTAT_NVISIT 1 #define SQLITE_SCANSTAT_EST 2 #define SQLITE_SCANSTAT_NAME 3 #define SQLITE_SCANSTAT_EXPLAIN 4 #define SQLITE_SCANSTAT_SELECTID 5 |
︙ | ︙ | |||
10189 10190 10191 10192 10193 10194 10195 | ** or any operation on a WITHOUT ROWID table, the value of the sixth ** parameter is undefined. For an INSERT or UPDATE on a rowid table the ** seventh parameter is the final rowid value of the row being inserted ** or updated. The value of the seventh parameter passed to the callback ** function is not defined for operations on WITHOUT ROWID tables, or for ** DELETE operations on rowid tables. ** | | | 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 10133 | ** or any operation on a WITHOUT ROWID table, the value of the sixth ** parameter is undefined. For an INSERT or UPDATE on a rowid table the ** seventh parameter is the final rowid value of the row being inserted ** or updated. The value of the seventh parameter passed to the callback ** function is not defined for operations on WITHOUT ROWID tables, or for ** DELETE operations on rowid tables. ** ** ^The sqlite3_update_hook(D,C,P) function returns the P argument from ** the previous call on the same [database connection] D, or NULL for ** the first call on D. ** ** The [sqlite3_preupdate_old()], [sqlite3_preupdate_new()], ** [sqlite3_preupdate_count()], and [sqlite3_preupdate_depth()] interfaces ** provide additional information about a preupdate event. These routines ** may only be called from within a preupdate callback. Invoking any of |
︙ | ︙ | |||
10598 10599 10600 10601 10602 10603 10604 | ** 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 #endif | < < < < < < < < < < < < < | 10528 10529 10530 10531 10532 10533 10534 10535 10536 10537 10538 | ** 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 #endif #ifdef __cplusplus } /* End of the 'extern "C"' block */ #endif #endif /* SQLITE3_H */ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
220 221 222 223 224 225 226 | #pragma warn -ccc /* Condition is always true or false */ #pragma warn -aus /* Assigned value is never used */ #pragma warn -csu /* Comparing signed and unsigned */ #pragma warn -spa /* Suspicious pointer arithmetic */ #endif /* | | | | 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 | #pragma warn -ccc /* Condition is always true or false */ #pragma warn -aus /* Assigned value is never used */ #pragma warn -csu /* Comparing signed and unsigned */ #pragma warn -spa /* Suspicious pointer arithmetic */ #endif /* ** WAL mode depends on atomic aligned 32-bit loads and stores in a few ** places. The following macros try to make this explicit. */ #ifndef __has_extension # define __has_extension(x) 0 /* compatibility with non-clang compilers */ #endif #if GCC_VERSION>=4007000 || __has_extension(c_atomic) # define SQLITE_ATOMIC_INTRINSICS 1 # define AtomicLoad(PTR) __atomic_load_n((PTR),__ATOMIC_RELAXED) |
︙ | ︙ | |||
277 278 279 280 281 282 283 | # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif /* | | < < < < < < < | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 | # define SQLITE_PTR_TO_INT(X) ((int)(((char*)X)-(char*)0)) #else /* Generates a warning - but it always works */ # define SQLITE_INT_TO_PTR(X) ((void*)(X)) # define SQLITE_PTR_TO_INT(X) ((int)(X)) #endif /* ** A macro to hint to the compiler that a function should not be ** inlined. */ #if defined(__GNUC__) # define SQLITE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) && _MSC_VER>=1310 # define SQLITE_NOINLINE __declspec(noinline) #else # define SQLITE_NOINLINE #endif /* ** Make sure that the compiler intrinsics we desire are enabled when ** compiling with an appropriate version of MSVC unless prevented by ** the SQLITE_DISABLE_INTRINSIC define. */ |
︙ | ︙ | |||
822 823 824 825 826 827 828 | ** is 0x00000000ffffffff. But because of quirks of some compilers, we ** have to specify the value in the less intuitive manner shown: */ #define SQLITE_MAX_U32 ((((u64)1)<<32)-1) /* ** The datatype used to store estimates of the number of rows in a | | > > > | > > > | 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 | ** is 0x00000000ffffffff. But because of quirks of some compilers, we ** have to specify the value in the less intuitive manner shown: */ #define SQLITE_MAX_U32 ((((u64)1)<<32)-1) /* ** The datatype used to store estimates of the number of rows in a ** table or index. This is an unsigned integer type. For 99.9% of ** the world, a 32-bit integer is sufficient. But a 64-bit integer ** can be used at compile-time if desired. */ #ifdef SQLITE_64BIT_STATS typedef u64 tRowcnt; /* 64-bit only if requested at compile-time */ #else typedef u32 tRowcnt; /* 32-bit is the default */ #endif /* ** Estimated quantities used for query planning are stored as 16-bit ** logarithms. For quantity X, the value stored is 10*log2(X). This ** gives a possible range of values of approximately 1.0e986 to 1e-986. ** But the allowed values are "grainy". Not every value is representable. ** For example, quantities 16 and 17 are both represented by a LogEst |
︙ | ︙ | |||
1760 1761 1762 1763 1764 1765 1766 | #define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */ #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ #define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and ** vtabs in the schema definition */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */ | | | 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 | #define SQLITE_CacheSpill 0x00000020 /* OK to spill pager cache */ #define SQLITE_ShortColNames 0x00000040 /* Show short columns names */ #define SQLITE_TrustedSchema 0x00000080 /* Allow unsafe functions and ** vtabs in the schema definition */ #define SQLITE_NullCallback 0x00000100 /* Invoke the callback once if the */ /* result set is empty */ #define SQLITE_IgnoreChecks 0x00000200 /* Do not enforce check constraints */ #define SQLITE_ReadUncommit 0x00000400 /* READ UNCOMMITTED in shared-cache */ #define SQLITE_NoCkptOnClose 0x00000800 /* No checkpoint on close()/DETACH */ #define SQLITE_ReverseOrder 0x00001000 /* Reverse unordered SELECTs */ #define SQLITE_RecTriggers 0x00002000 /* Enable recursive triggers */ #define SQLITE_ForeignKeys 0x00004000 /* Enforce foreign key constraints */ #define SQLITE_AutoIndex 0x00008000 /* Enable automatic indexes */ #define SQLITE_LoadExtension 0x00010000 /* Enable load_extension */ #define SQLITE_LoadExtFunc 0x00020000 /* Enable load_extension() SQL func */ |
︙ | ︙ | |||
1786 1787 1788 1789 1790 1791 1792 | #define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ #define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ #define SQLITE_EnableView 0x80000000 /* Enable the use of views */ #define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */ | < | 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | #define SQLITE_DqsDDL 0x20000000 /* dbl-quoted strings allowed in DDL*/ #define SQLITE_DqsDML 0x40000000 /* dbl-quoted strings allowed in DML*/ #define SQLITE_EnableView 0x80000000 /* Enable the use of views */ #define SQLITE_CountRows HI(0x00001) /* Count rows changed by INSERT, */ /* DELETE, or UPDATE and return */ /* the count using a callback. */ #define SQLITE_CorruptRdOnly HI(0x00002) /* Prohibit writes due to error */ /* Flags used only if debugging */ #ifdef SQLITE_DEBUG #define SQLITE_SqlTrace HI(0x0100000) /* Debug print SQL as it executes */ #define SQLITE_VdbeListing HI(0x0200000) /* Debug listings of VDBE progs */ #define SQLITE_VdbeTrace HI(0x0400000) /* True to trace VDBE execution */ #define SQLITE_VdbeAddopTrace HI(0x0800000) /* Trace sqlite3VdbeAddOp() calls */ |
︙ | ︙ | |||
1843 1844 1845 1846 1847 1848 1849 | #define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ #define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ #define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */ #define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */ #define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ #define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ | < | 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 | #define SQLITE_BloomPulldown 0x00100000 /* Run Bloom filters early */ #define SQLITE_BalancedMerge 0x00200000 /* Balance multi-way merges */ #define SQLITE_ReleaseReg 0x00400000 /* Use OP_ReleaseReg for testing */ #define SQLITE_FlttnUnionAll 0x00800000 /* Disable the UNION ALL flattener */ /* TH3 expects this value ^^^^^^^^^^ See flatten04.test */ #define SQLITE_IndexedExpr 0x01000000 /* Pull exprs from index when able */ #define SQLITE_Coroutines 0x02000000 /* Co-routines for subqueries */ #define SQLITE_AllOpts 0xffffffff /* All optimizations */ /* ** Macros for testing whether or not optimizations are enabled or disabled. */ #define OptimizationDisabled(db, mask) (((db)->dbOptFlags&(mask))!=0) #define OptimizationEnabled(db, mask) (((db)->dbOptFlags&(mask))==0) |
︙ | ︙ | |||
2315 2316 2317 2318 2319 2320 2321 | */ struct VTable { sqlite3 *db; /* Database connection associated with this table */ Module *pMod; /* Pointer to module implementation */ sqlite3_vtab *pVtab; /* Pointer to vtab instance */ int nRef; /* Number of pointers to this structure */ u8 bConstraint; /* True if constraints are supported */ | < | 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 | */ struct VTable { sqlite3 *db; /* Database connection associated with this table */ Module *pMod; /* Pointer to module implementation */ sqlite3_vtab *pVtab; /* Pointer to vtab instance */ int nRef; /* Number of pointers to this structure */ u8 bConstraint; /* True if constraints are supported */ u8 eVtabRisk; /* Riskiness of allowing hacker access */ int iSavepoint; /* Depth of the SAVEPOINT stack */ VTable *pNext; /* Next in linked list (see above) */ }; /* Allowed values for VTable.eVtabRisk */ |
︙ | ︙ | |||
2696 2697 2698 2699 2700 2701 2702 | unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ unsigned bHasExpr:1; /* Index contains an expression, either a literal ** expression, or a reference to a VIRTUAL column */ #ifdef SQLITE_ENABLE_STAT4 int nSample; /* Number of elements in aSample[] */ | < | 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 | unsigned bNoQuery:1; /* Do not use this index to optimize queries */ unsigned bAscKeyBug:1; /* True if the bba7b69f9849b5bf bug applies */ unsigned bHasVCol:1; /* Index references one or more VIRTUAL columns */ unsigned bHasExpr:1; /* Index contains an expression, either a literal ** expression, or a reference to a VIRTUAL column */ #ifdef SQLITE_ENABLE_STAT4 int nSample; /* Number of elements in aSample[] */ int nSampleCol; /* Size of IndexSample.anEq[] and so on */ tRowcnt *aAvgEq; /* Average nEq values for keys not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ tRowcnt *aiRowEst; /* Non-logarithmic stat1 data for this index */ tRowcnt nRowEst0; /* Non-logarithmic number of rows in the index */ #endif Bitmask colNotIdxed; /* Unindexed columns in pTab */ |
︙ | ︙ | |||
3348 3349 3350 3351 3352 3353 3354 | #define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */ #define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */ #define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */ #define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */ #define NC_HasAgg 0x000010 /* One or more aggregate functions seen */ #define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */ #define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */ | | | 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 | #define NC_AllowAgg 0x000001 /* Aggregate functions are allowed here */ #define NC_PartIdx 0x000002 /* True if resolving a partial index WHERE */ #define NC_IsCheck 0x000004 /* True if resolving a CHECK constraint */ #define NC_GenCol 0x000008 /* True for a GENERATED ALWAYS AS clause */ #define NC_HasAgg 0x000010 /* One or more aggregate functions seen */ #define NC_IdxExpr 0x000020 /* True if resolving columns of CREATE INDEX */ #define NC_SelfRef 0x00002e /* Combo: PartIdx, isCheck, GenCol, and IdxExpr */ #define NC_VarSelect 0x000040 /* A correlated subquery has been seen */ #define NC_UEList 0x000080 /* True if uNC.pEList is used */ #define NC_UAggInfo 0x000100 /* True if uNC.pAggInfo is used */ #define NC_UUpsert 0x000200 /* True if uNC.pUpsert is used */ #define NC_UBaseReg 0x000400 /* True if uNC.iBaseReg is used */ #define NC_MinMaxAgg 0x001000 /* min/max aggregates seen. See note above */ #define NC_Complex 0x002000 /* True if a function or subquery seen */ #define NC_AllowWin 0x004000 /* Window functions are allowed here */ |
︙ | ︙ | |||
3667 3668 3669 3670 3671 3672 3673 | */ struct IndexedExpr { Expr *pExpr; /* The expression contained in the index */ int iDataCur; /* The data cursor associated with the index */ int iIdxCur; /* The index cursor */ int iIdxCol; /* The index column that contains value of pExpr */ u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ | < | 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 | */ struct IndexedExpr { Expr *pExpr; /* The expression contained in the index */ int iDataCur; /* The data cursor associated with the index */ int iIdxCur; /* The index cursor */ int iIdxCol; /* The index column that contains value of pExpr */ u8 bMaybeNullRow; /* True if we need an OP_IfNullRow check */ IndexedExpr *pIENext; /* Next in a list of all indexed expressions */ #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS const char *zIdxName; /* Name of index, used only for bytecode comments */ #endif }; /* |
︙ | ︙ | |||
3720 3721 3722 3723 3724 3725 3726 | u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif | < < < | 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 | u8 okConstFactor; /* OK to factor out constants */ u8 disableLookaside; /* Number of times lookaside has been disabled */ u8 prepFlags; /* SQLITE_PREPARE_* flags */ u8 withinRJSubrtn; /* Nesting level for RIGHT JOIN body subroutines */ #if defined(SQLITE_DEBUG) || defined(SQLITE_COVERAGE_TEST) u8 earlyCleanup; /* OOM inside sqlite3ParserAddCleanup() */ #endif int nRangeReg; /* Size of the temporary register block */ int iRangeReg; /* First register in temporary register block */ int nErr; /* Number of errors seen */ int nTab; /* Number of previously allocated VDBE cursors */ int nMem; /* Number of memory cells used so far */ int szOpAlloc; /* Bytes of memory space allocated for Vdbe.aOp[] */ int iSelfTab; /* Table associated with an index on expr, or negative |
︙ | ︙ | |||
4183 4184 4185 4186 4187 4188 4189 | struct WindowRewrite *pRewrite; /* Window rewrite context */ struct WhereConst *pConst; /* WHERE clause constants */ struct RenameCtx *pRename; /* RENAME COLUMN context */ struct Table *pTab; /* Table of generated column */ struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */ SrcItem *pSrcItem; /* A single FROM clause item */ DbFixer *pFix; /* See sqlite3FixSelect() */ | < | 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 | struct WindowRewrite *pRewrite; /* Window rewrite context */ struct WhereConst *pConst; /* WHERE clause constants */ struct RenameCtx *pRename; /* RENAME COLUMN context */ struct Table *pTab; /* Table of generated column */ struct CoveringIndexCheck *pCovIdxCk; /* Check for covering index */ SrcItem *pSrcItem; /* A single FROM clause item */ DbFixer *pFix; /* See sqlite3FixSelect() */ } u; }; /* ** The following structure contains information used by the sqliteFix... ** routines as they walk the parse tree to make database references ** explicit. |
︙ | ︙ | |||
4453 4454 4455 4456 4457 4458 4459 | # define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01) # define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06) # define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02) # define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) # define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) # define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) # define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) | < < < < | 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 | # define sqlite3Isspace(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x01) # define sqlite3Isalnum(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x06) # define sqlite3Isalpha(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x02) # define sqlite3Isdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x04) # define sqlite3Isxdigit(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x08) # define sqlite3Tolower(x) (sqlite3UpperToLower[(unsigned char)(x)]) # define sqlite3Isquote(x) (sqlite3CtypeMap[(unsigned char)(x)]&0x80) #else # define sqlite3Toupper(x) toupper((unsigned char)(x)) # define sqlite3Isspace(x) isspace((unsigned char)(x)) # define sqlite3Isalnum(x) isalnum((unsigned char)(x)) # define sqlite3Isalpha(x) isalpha((unsigned char)(x)) # define sqlite3Isdigit(x) isdigit((unsigned char)(x)) # define sqlite3Isxdigit(x) isxdigit((unsigned char)(x)) # define sqlite3Tolower(x) tolower((unsigned char)(x)) # define sqlite3Isquote(x) ((x)=='"'||(x)=='\''||(x)=='['||(x)=='`') #endif int sqlite3IsIdChar(u8); /* ** Internal function prototypes */ int sqlite3StrICmp(const char*,const char*); |
︙ | ︙ | |||
4659 4660 4661 4662 4663 4664 4665 | int sqlite3RunParser(Parse*, const char*); void sqlite3FinishCoding(Parse*); int sqlite3GetTempReg(Parse*); void sqlite3ReleaseTempReg(Parse*,int); int sqlite3GetTempRange(Parse*,int); void sqlite3ReleaseTempRange(Parse*,int,int); void sqlite3ClearTempRegCache(Parse*); | < < < < | 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 | int sqlite3RunParser(Parse*, const char*); void sqlite3FinishCoding(Parse*); int sqlite3GetTempReg(Parse*); void sqlite3ReleaseTempReg(Parse*,int); int sqlite3GetTempRange(Parse*,int); void sqlite3ReleaseTempRange(Parse*,int,int); void sqlite3ClearTempRegCache(Parse*); #ifdef SQLITE_DEBUG int sqlite3NoTempsInRange(Parse*,int,int); #endif Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int); Expr *sqlite3Expr(sqlite3*,int,const char*); void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*); Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*); |
︙ | ︙ | |||
4813 4814 4815 4816 4817 4818 4819 | Expr*, int, int, u8); void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,u32,Expr*); void sqlite3SelectDelete(sqlite3*, Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); | | | 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 | Expr*, int, int, u8); void sqlite3DropIndex(Parse*, SrcList*, int); int sqlite3Select(Parse*, Select*, SelectDest*); Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*, Expr*,ExprList*,u32,Expr*); void sqlite3SelectDelete(sqlite3*, Select*); Table *sqlite3SrcListLookup(Parse*, SrcList*); int sqlite3IsReadOnly(Parse*, Table*, int); void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) Expr *sqlite3LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,char*); #endif void sqlite3CodeChangeCount(Vdbe*,int,const char*); void sqlite3DeleteFrom(Parse*, SrcList*, Expr*, ExprList*, Expr*); void sqlite3Update(Parse*, SrcList*, ExprList*,Expr*,int,ExprList*,Expr*, |
︙ | ︙ | |||
5350 5351 5352 5353 5354 5355 5356 | void sqlite3VtabArgExtend(Parse*, Token*); int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); int sqlite3VtabCallConnect(Parse*, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); | > > | > | 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 | void sqlite3VtabArgExtend(Parse*, Token*); int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); int sqlite3VtabCallConnect(Parse*, Table*); int sqlite3VtabCallDestroy(sqlite3*, int, const char *); int sqlite3VtabBegin(sqlite3 *, VTable *); FuncDef *sqlite3VtabOverloadFunction(sqlite3 *,FuncDef*, int nArg, Expr*); #if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) void sqlite3VtabUsesAllSchemas(sqlite3_index_info*); #endif sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*); int sqlite3VdbeParameterIndex(Vdbe*, const char*, int); int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *); void sqlite3ParseObjectInit(Parse*,sqlite3*); void sqlite3ParseObjectReset(Parse*); void *sqlite3ParserAddCleanup(Parse*,void(*)(sqlite3*,void*),void*); #ifdef SQLITE_ENABLE_NORMALIZE |
︙ | ︙ | |||
5597 5598 5599 5600 5601 5602 5603 | #if defined(VDBE_PROFILE) \ || defined(SQLITE_PERFORMANCE_TRACE) \ || defined(SQLITE_ENABLE_STMT_SCANSTATUS) sqlite3_uint64 sqlite3Hwtime(void); #endif | < < < < < < | 5582 5583 5584 5585 5586 5587 5588 5589 | #if defined(VDBE_PROFILE) \ || defined(SQLITE_PERFORMANCE_TRACE) \ || defined(SQLITE_ENABLE_STMT_SCANSTATUS) sqlite3_uint64 sqlite3Hwtime(void); #endif #endif /* SQLITEINT_H */ |
Changes to src/test1.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. */ #include "sqliteInt.h" #if SQLITE_OS_WIN # include "os_win.h" | < < < < < < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** Code for testing all sorts of SQLite interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. */ #include "sqliteInt.h" #if SQLITE_OS_WIN # include "os_win.h" #endif #include "vdbeInt.h" #if defined(INCLUDE_SQLITE_TCL_H) # include "sqlite_tcl.h" #else # include "tcl.h" |
︙ | ︙ | |||
2387 2388 2389 2390 2391 2392 2393 | return TCL_ERROR; } pVfs->xCurrentTimeInt64(pVfs, &t); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < | 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 | return TCL_ERROR; } pVfs->xCurrentTimeInt64(pVfs, &t); Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t)); return TCL_OK; } #ifdef SQLITE_ENABLE_SNAPSHOT /* ** Usage: sqlite3_snapshot_get DB DBNAME */ static int SQLITE_TCLAPI test_snapshot_get( void * clientData, Tcl_Interp *interp, |
︙ | ︙ | |||
8311 8312 8313 8314 8315 8316 8317 | { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, { "WRITABLE_SCHEMA", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "DQS_DML", SQLITE_DBCONFIG_DQS_DML }, { "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL }, { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, | < | 8279 8280 8281 8282 8283 8284 8285 8286 8287 8288 8289 8290 8291 8292 | { "RESET_DB", SQLITE_DBCONFIG_RESET_DATABASE }, { "DEFENSIVE", SQLITE_DBCONFIG_DEFENSIVE }, { "WRITABLE_SCHEMA", SQLITE_DBCONFIG_WRITABLE_SCHEMA }, { "LEGACY_ALTER_TABLE", SQLITE_DBCONFIG_LEGACY_ALTER_TABLE }, { "DQS_DML", SQLITE_DBCONFIG_DQS_DML }, { "DQS_DDL", SQLITE_DBCONFIG_DQS_DDL }, { "LEGACY_FILE_FORMAT", SQLITE_DBCONFIG_LEGACY_FILE_FORMAT }, }; int i; int v = 0; const char *zSetting; sqlite3 *db; if( objc!=4 && objc!=3 ){ |
︙ | ︙ | |||
8668 8669 8670 8671 8672 8673 8674 | "sqlite3_autovacuum_pages() returns %d", rc); Tcl_AppendResult(interp, zBuf, (void*)0); return TCL_ERROR; } return TCL_OK; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 8635 8636 8637 8638 8639 8640 8641 8642 8643 8644 8645 8646 8647 8648 | "sqlite3_autovacuum_pages() returns %d", rc); Tcl_AppendResult(interp, zBuf, (void*)0); return TCL_ERROR; } return TCL_OK; } /* ** Register commands with the TCL interpreter. */ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_search_count; extern int sqlite3_found_count; |
︙ | ︙ | |||
9002 9003 9004 9005 9006 9007 9008 | { "sqlite3_mmap_warm", test_mmap_warm, 0 }, { "sqlite3_config_sorterref", test_config_sorterref, 0 }, { "sqlite3_autovacuum_pages", test_autovacuum_pages, 0 }, { "decode_hexdb", test_decode_hexdb, 0 }, { "test_write_db", test_write_db, 0 }, { "sqlite3_register_cksumvfs", test_register_cksumvfs, 0 }, { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs, 0 }, | < < < < | 8935 8936 8937 8938 8939 8940 8941 8942 8943 8944 8945 8946 8947 8948 | { "sqlite3_mmap_warm", test_mmap_warm, 0 }, { "sqlite3_config_sorterref", test_config_sorterref, 0 }, { "sqlite3_autovacuum_pages", test_autovacuum_pages, 0 }, { "decode_hexdb", test_decode_hexdb, 0 }, { "test_write_db", test_write_db, 0 }, { "sqlite3_register_cksumvfs", test_register_cksumvfs, 0 }, { "sqlite3_unregister_cksumvfs", test_unregister_cksumvfs, 0 }, }; static int bitmask_size = sizeof(Bitmask)*8; static int longdouble_size = sizeof(LONGDOUBLE_TYPE); int i; extern int sqlite3_sync_count, sqlite3_fullsync_count; extern int sqlite3_opentemp_count; extern int sqlite3_like_count; |
︙ | ︙ |
Changes to src/test_syscall.c.
︙ | ︙ | |||
106 107 108 109 110 111 112 | static int ts_close(int fd); static int ts_access(const char *zPath, int mode); static char *ts_getcwd(char *zPath, size_t nPath); static int ts_stat(const char *zPath, struct stat *p); static int ts_fstat(int fd, struct stat *p); static int ts_ftruncate(int fd, off_t n); static int ts_fcntl(int fd, int cmd, ... ); | | | | | | | | 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 | static int ts_close(int fd); static int ts_access(const char *zPath, int mode); static char *ts_getcwd(char *zPath, size_t nPath); static int ts_stat(const char *zPath, struct stat *p); static int ts_fstat(int fd, struct stat *p); static int ts_ftruncate(int fd, off_t n); static int ts_fcntl(int fd, int cmd, ... ); static int ts_read(int fd, void *aBuf, size_t nBuf); static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off); /* Note: pread64() and pwrite64() actually use off64_t as the type on their ** last parameter. But that datatype is not defined on many systems ** (ex: Mac, OpenBSD). So substitute a likely equivalent: sqlite3_uint64 */ static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off); static int ts_write(int fd, const void *aBuf, size_t nBuf); static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off); static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off); static int ts_fchmod(int fd, mode_t mode); static int ts_fallocate(int fd, off_t off, off_t len); static void *ts_mmap(void *, size_t, int, int, int, off_t); static void *ts_mremap(void*, size_t, size_t, int, ...); struct TestSyscallArray { const char *zName; |
︙ | ︙ | |||
207 208 209 210 211 212 213 | assert(0); return 0; } /* ** A wrapper around tsIsFail(). If tsIsFail() returns non-zero, set the ** value of errno before returning. | | | 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 | assert(0); return 0; } /* ** A wrapper around tsIsFail(). If tsIsFail() returns non-zero, set the ** value of errno before returning. */ static int tsIsFailErrno(const char *zFunc){ if( tsIsFail() ){ errno = tsErrno(zFunc); return 1; } return 0; } |
︙ | ︙ | |||
309 310 311 312 313 314 315 | pArg = va_arg(ap, void *); return orig_fcntl(fd, cmd, pArg); } /* ** A wrapper around read(). */ | | | | | | | | 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | pArg = va_arg(ap, void *); return orig_fcntl(fd, cmd, pArg); } /* ** A wrapper around read(). */ static int ts_read(int fd, void *aBuf, size_t nBuf){ if( tsIsFailErrno("read") ){ return -1; } return orig_read(fd, aBuf, nBuf); } /* ** A wrapper around pread(). */ static int ts_pread(int fd, void *aBuf, size_t nBuf, off_t off){ if( tsIsFailErrno("pread") ){ return -1; } return orig_pread(fd, aBuf, nBuf, off); } /* ** A wrapper around pread64(). */ static int ts_pread64(int fd, void *aBuf, size_t nBuf, sqlite3_uint64 off){ if( tsIsFailErrno("pread64") ){ return -1; } return orig_pread64(fd, aBuf, nBuf, off); } /* ** A wrapper around write(). */ static int ts_write(int fd, const void *aBuf, size_t nBuf){ if( tsIsFailErrno("write") ){ if( tsErrno("write")==EINTR ) orig_write(fd, aBuf, nBuf/2); return -1; } return orig_write(fd, aBuf, nBuf); } /* ** A wrapper around pwrite(). */ static int ts_pwrite(int fd, const void *aBuf, size_t nBuf, off_t off){ if( tsIsFailErrno("pwrite") ){ return -1; } return orig_pwrite(fd, aBuf, nBuf, off); } /* ** A wrapper around pwrite64(). */ static int ts_pwrite64(int fd, const void *aBuf, size_t nBuf, sqlite3_uint64 off){ if( tsIsFailErrno("pwrite64") ){ return -1; } return orig_pwrite64(fd, aBuf, nBuf, off); } /* |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
198 199 200 201 202 203 204 | if( !IN_RENAME_OBJECT ){ if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); }else{ assert( !db->init.busy ); sqlite3CodeVerifySchema(pParse, iDb); | < | 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | if( !IN_RENAME_OBJECT ){ if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash),zName) ){ if( !noErr ){ sqlite3ErrorMsg(pParse, "trigger %T already exists", pName); }else{ assert( !db->init.busy ); sqlite3CodeVerifySchema(pParse, iDb); } goto trigger_cleanup; } } /* Do not create a trigger on a system table */ if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){ |
︙ | ︙ | |||
980 981 982 983 984 985 986 | sqlite3SelectPrep(pParse, &sSelect, 0); if( pParse->nErr==0 ){ assert( db->mallocFailed==0 ); sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); | | | 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 | sqlite3SelectPrep(pParse, &sSelect, 0); if( pParse->nErr==0 ){ assert( db->mallocFailed==0 ); sqlite3GenerateColumnNames(pParse, &sSelect); } sqlite3ExprListDelete(db, sSelect.pEList); pNew = sqlite3ExpandReturning(pParse, pReturning->pReturnEL, pTab); if( !db->mallocFailed ){ NameContext sNC; memset(&sNC, 0, sizeof(sNC)); if( pReturning->nRetCol==0 ){ pReturning->nRetCol = pNew->nExpr; pReturning->iRetCur = pParse->nTab++; } sNC.pParse = pParse; |
︙ | ︙ | |||
1449 1450 1451 1452 1453 1454 1455 | int orconf /* Default ON CONFLICT policy for trigger steps */ ){ const int op = pChanges ? TK_UPDATE : TK_DELETE; u32 mask = 0; Trigger *p; assert( isNew==1 || isNew==0 ); | < < < | 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 | int orconf /* Default ON CONFLICT policy for trigger steps */ ){ const int op = pChanges ? TK_UPDATE : TK_DELETE; u32 mask = 0; Trigger *p; assert( isNew==1 || isNew==0 ); for(p=pTrigger; p; p=p->pNext){ if( p->op==op && (tr_tm&p->tr_tm) && checkColumnOverlap(p->pColumns,pChanges) ){ if( p->bReturning ){ mask = 0xffffffff; |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
404 405 406 407 408 409 410 | pLimit = 0; } #endif if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto update_cleanup; } | | | 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 | pLimit = 0; } #endif if( sqlite3ViewGetColumnNames(pParse, pTab) ){ goto update_cleanup; } if( sqlite3IsReadOnly(pParse, pTab, tmask) ){ goto update_cleanup; } /* Allocate a cursors for the main database table and for all indices. ** The index cursors might not be used, but if they are used they ** need to occur right after the database cursor. So go ahead and ** allocate enough space, just in case. |
︙ | ︙ | |||
723 724 725 726 727 728 729 | eOnePass = ONEPASS_SINGLE; sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); bFinishSeek = 0; }else{ /* Begin the database scan. ** ** Do not consider a single-pass strategy for a multi-row update if | < < < | < | < < > > | < < < < < < | 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 | eOnePass = ONEPASS_SINGLE; sqlite3ExprIfFalse(pParse, pWhere, labelBreak, SQLITE_JUMPIFNULL); bFinishSeek = 0; }else{ /* Begin the database scan. ** ** Do not consider a single-pass strategy for a multi-row update if ** there are any triggers or foreign keys to process, or rows may ** be deleted as a result of REPLACE conflict handling. Any of these ** things might disturb a cursor being used to scan through the table ** or index, causing a single-pass approach to malfunction. */ flags = WHERE_ONEPASS_DESIRED; if( !pParse->nested && !pTrigger && !hasFK && !chngKey && !bReplace ){ flags |= WHERE_ONEPASS_MULTIROW; } pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere,0,0,0,flags,iIdxCur); if( pWInfo==0 ) goto update_cleanup; /* A one-pass strategy that might update more than one row may not ** be used if any column of the index used for the scan is being |
︙ | ︙ |
Changes to src/util.c.
︙ | ︙ | |||
666 667 668 669 670 671 672 | if( v<0 ){ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v; }else{ x = v; } i = sizeof(zTemp)-2; zTemp[sizeof(zTemp)-1] = 0; | < > | | < < | | | | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 | if( v<0 ){ x = (v==SMALLEST_INT64) ? ((u64)1)<<63 : (u64)-v; }else{ x = v; } i = sizeof(zTemp)-2; zTemp[sizeof(zTemp)-1] = 0; do{ zTemp[i--] = (x%10) + '0'; x = x/10; }while( x ); if( v<0 ) zTemp[i--] = '-'; memcpy(zOut, &zTemp[i+1], sizeof(zTemp)-1-i); return sizeof(zTemp)-2-i; } /* ** Compare the 19-character string zNum against the text representation ** value 2^63: 9223372036854775808. Return negative, zero, or positive ** if zNum is less than, equal to, or greater than the string. ** Note that zNum must contain exactly 19 characters. |
︙ | ︙ | |||
839 840 841 842 843 844 845 | u64 u = 0; int i, k; for(i=2; z[i]=='0'; i++){} for(k=i; sqlite3Isxdigit(z[k]); k++){ u = u*16 + sqlite3HexToInt(z[k]); } memcpy(pOut, &u, 8); | < < | | 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 | u64 u = 0; int i, k; for(i=2; z[i]=='0'; i++){} for(k=i; sqlite3Isxdigit(z[k]); k++){ u = u*16 + sqlite3HexToInt(z[k]); } memcpy(pOut, &u, 8); return (z[k]==0 && k-i<=16) ? 0 : 2; }else #endif /* SQLITE_OMIT_HEX_INTEGER */ { return sqlite3Atoi64(z, pOut, sqlite3Strlen30(z), SQLITE_UTF8); } } |
︙ | ︙ | |||
877 878 879 880 881 882 883 | else if( zNum[0]=='0' && (zNum[1]=='x' || zNum[1]=='X') && sqlite3Isxdigit(zNum[2]) ){ u32 u = 0; zNum += 2; while( zNum[0]=='0' ) zNum++; | | | 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 | else if( zNum[0]=='0' && (zNum[1]=='x' || zNum[1]=='X') && sqlite3Isxdigit(zNum[2]) ){ u32 u = 0; zNum += 2; while( zNum[0]=='0' ) zNum++; for(i=0; sqlite3Isxdigit(zNum[i]) && i<8; i++){ u = u*16 + sqlite3HexToInt(zNum[i]); } if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){ memcpy(pValue, &u, 4); return 1; }else{ return 0; |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
679 680 681 682 683 684 685 | for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){ const Mem *p = &aMem[i]; if( p->flags & (MEM_Int|MEM_IntReal) ){ h += p->u.i; }else if( p->flags & MEM_Real ){ h += sqlite3VdbeIntValue(p); }else if( p->flags & (MEM_Str|MEM_Blob) ){ | | < < | | 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 | for(i=pOp->p3, mx=i+pOp->p4.i; i<mx; i++){ const Mem *p = &aMem[i]; if( p->flags & (MEM_Int|MEM_IntReal) ){ h += p->u.i; }else if( p->flags & MEM_Real ){ h += sqlite3VdbeIntValue(p); }else if( p->flags & (MEM_Str|MEM_Blob) ){ h += p->n; if( p->flags & MEM_Zero ) h += p->u.nZero; } } return h; } /* ** Return the symbolic name for the data type of a pMem |
︙ | ︙ | |||
732 733 734 735 736 737 738 | Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) u64 *pnCycle = 0; | < | 730 731 732 733 734 735 736 737 738 739 740 741 742 743 | Mem *aMem = p->aMem; /* Copy of p->aMem */ Mem *pIn1 = 0; /* 1st input operand */ Mem *pIn2 = 0; /* 2nd input operand */ Mem *pIn3 = 0; /* 3rd input operand */ Mem *pOut = 0; /* Output operand */ #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) u64 *pnCycle = 0; #endif /*** INSERT STACK UNION HERE ***/ assert( p->eVdbeState==VDBE_RUN_STATE ); /* sqlite3_step() verifies this */ if( DbMaskNonZero(p->lockMask) ){ sqlite3VdbeEnter(p); } |
︙ | ︙ | |||
797 798 799 800 801 802 803 | for(pOp=&aOp[p->pc]; 1; pOp++){ /* Errors are detected by individual opcodes, with an immediate ** jumps to abort_due_to_error. */ assert( rc==SQLITE_OK ); assert( pOp>=aOp && pOp<&aOp[p->nOp]); nVmStep++; | | < > | < | < < < | 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 | for(pOp=&aOp[p->pc]; 1; pOp++){ /* Errors are detected by individual opcodes, with an immediate ** jumps to abort_due_to_error. */ assert( rc==SQLITE_OK ); assert( pOp>=aOp && pOp<&aOp[p->nOp]); nVmStep++; #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) || defined(VDBE_PROFILE) pOp->nExec++; pnCycle = &pOp->nCycle; # ifdef VDBE_PROFILE if( sqlite3NProfileCnt==0 ) # endif *pnCycle -= sqlite3Hwtime(); #endif /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeTrace ){ sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp); |
︙ | ︙ | |||
1155 1156 1157 1158 1159 1160 1161 | int pcx; #ifdef SQLITE_DEBUG if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } #endif /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates | | | 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 | int pcx; #ifdef SQLITE_DEBUG if( pOp->p2==OE_Abort ){ sqlite3VdbeAssertAbortable(p); } #endif /* A deliberately coded "OP_Halt SQLITE_INTERNAL * * * *" opcode indicates ** something is wrong with the code generator. Raise and assertion in order ** to bring this to the attention of fuzzers and other testing tools. */ assert( pOp->p1!=SQLITE_INTERNAL ); if( p->pFrame && pOp->p1==SQLITE_OK ){ /* Halt the sub-program. Return control to the parent frame. */ pFrame = p->pFrame; p->pFrame = pFrame->pParent; |
︙ | ︙ | |||
2622 2623 2624 2625 2626 2627 2628 | ** If P1 is -1, then P3 is a register number and the datatype is taken ** from the value in that register. ** ** P5 is a bitmask of data types. SQLITE_INTEGER is the least significant ** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04. ** SQLITE_BLOB is 0x08. SQLITE_NULL is 0x10. ** | < < < < < < | 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 | ** If P1 is -1, then P3 is a register number and the datatype is taken ** from the value in that register. ** ** P5 is a bitmask of data types. SQLITE_INTEGER is the least significant ** (0x01) bit. SQLITE_FLOAT is the 0x02 bit. SQLITE_TEXT is 0x04. ** SQLITE_BLOB is 0x08. SQLITE_NULL is 0x10. ** ** Take the jump to address P2 if and only if the datatype of the ** value determined by P1 and P3 corresponds to one of the bits in the ** P5 bitmask. ** */ case OP_IsType: { /* jump */ VdbeCursor *pC; |
︙ | ︙ | |||
2741 2742 2743 2744 2745 2746 2747 | ** ** If P1 is not an open cursor, then this opcode is a no-op. */ case OP_IfNullRow: { /* jump */ VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; | | | 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 | ** ** If P1 is not an open cursor, then this opcode is a no-op. */ case OP_IfNullRow: { /* jump */ VdbeCursor *pC; assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; if( ALWAYS(pC) && pC->nullRow ){ sqlite3VdbeMemSetNull(aMem + pOp->p3); goto jump_to_p2; } break; } #ifdef SQLITE_ENABLE_OFFSET_SQL_FUNC |
︙ | ︙ | |||
3236 3237 3238 3239 3240 3241 3242 | testcase( pIn1->u.i==-140737488355329LL ); if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){ pIn1->flags |= MEM_IntReal; pIn1->flags &= ~MEM_Int; }else{ pIn1->u.r = (double)pIn1->u.i; pIn1->flags |= MEM_Real; | | | 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 | testcase( pIn1->u.i==-140737488355329LL ); if( pIn1->u.i<=140737488355327LL && pIn1->u.i>=-140737488355328LL ){ pIn1->flags |= MEM_IntReal; pIn1->flags &= ~MEM_Int; }else{ pIn1->u.r = (double)pIn1->u.i; pIn1->flags |= MEM_Real; pIn1->flags &= ~MEM_Int; } } REGISTER_TRACE((int)(pIn1-aMem), pIn1); zAffinity++; if( zAffinity[0]==0 ) break; pIn1++; } |
︙ | ︙ | |||
4975 4976 4977 4978 4979 4980 4981 | printf("... fall through after %d steps\n", pOp->p1); } #endif VdbeBranchTaken(0,3); break; } nStep--; | < | 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 | printf("... fall through after %d steps\n", pOp->p1); } #endif VdbeBranchTaken(0,3); break; } nStep--; rc = sqlite3BtreeNext(pC->uc.pCursor, 0); if( rc ){ if( rc==SQLITE_DONE ){ rc = SQLITE_OK; goto seekscan_search_fail; }else{ goto abort_due_to_error; |
︙ | ︙ | |||
7628 7629 7630 7631 7632 7633 7634 | if( rc ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); goto abort_due_to_error; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); | < | 7614 7615 7616 7617 7618 7619 7620 7621 7622 7623 7624 7625 7626 7627 | if( rc ){ sqlite3VdbeError(p, "%s", sqlite3_value_text(pMem)); goto abort_due_to_error; } sqlite3VdbeChangeEncoding(pMem, encoding); UPDATE_MAX_BLOBSIZE(pMem); break; } #ifndef SQLITE_OMIT_WAL /* Opcode: Checkpoint P1 P2 P3 * * ** ** Checkpoint database P1. This is a no-op if P1 is not currently in |
︙ | ︙ | |||
8779 8780 8781 8782 8783 8784 8785 | *****************************************************************************/ } #if defined(VDBE_PROFILE) *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); pnCycle = 0; #elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) | < | | < | 8764 8765 8766 8767 8768 8769 8770 8771 8772 8773 8774 8775 8776 8777 8778 8779 | *****************************************************************************/ } #if defined(VDBE_PROFILE) *pnCycle += sqlite3NProfileCnt ? sqlite3NProfileCnt : sqlite3Hwtime(); pnCycle = 0; #elif defined(SQLITE_ENABLE_STMT_SCANSTATUS) *pnCycle += sqlite3Hwtime(); pnCycle = 0; #endif /* The following code adds nothing to the actual functionality ** of the program. It is only here for testing and debugging. ** On the other hand, it does burn CPU cycles every time through ** the evaluator loop. So we can leave it out when NDEBUG is defined. */ |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
399 400 401 402 403 404 405 | # define sqlite3VdbeScanStatusCounters(a,b,c,d) #endif #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) void sqlite3VdbePrintOp(FILE*, int, VdbeOp*); #endif | < < < < | 399 400 401 402 403 404 405 406 | # define sqlite3VdbeScanStatusCounters(a,b,c,d) #endif #if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE) void sqlite3VdbePrintOp(FILE*, int, VdbeOp*); #endif #endif /* SQLITE_VDBE_H */ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
267 268 269 270 271 272 273 | SQLITE_NULL, /* 0x1b (not possible) */ SQLITE_INTEGER, /* 0x1c (not possible) */ SQLITE_NULL, /* 0x1d (not possible) */ SQLITE_INTEGER, /* 0x1e (not possible) */ SQLITE_NULL, /* 0x1f (not possible) */ SQLITE_FLOAT, /* 0x20 INTREAL */ SQLITE_NULL, /* 0x21 (not possible) */ | | | 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | SQLITE_NULL, /* 0x1b (not possible) */ SQLITE_INTEGER, /* 0x1c (not possible) */ SQLITE_NULL, /* 0x1d (not possible) */ SQLITE_INTEGER, /* 0x1e (not possible) */ SQLITE_NULL, /* 0x1f (not possible) */ SQLITE_FLOAT, /* 0x20 INTREAL */ SQLITE_NULL, /* 0x21 (not possible) */ SQLITE_TEXT, /* 0x22 INTREAL + TEXT */ SQLITE_NULL, /* 0x23 (not possible) */ SQLITE_FLOAT, /* 0x24 (not possible) */ SQLITE_NULL, /* 0x25 (not possible) */ SQLITE_FLOAT, /* 0x26 (not possible) */ SQLITE_NULL, /* 0x27 (not possible) */ SQLITE_FLOAT, /* 0x28 (not possible) */ SQLITE_NULL, /* 0x29 (not possible) */ |
︙ | ︙ | |||
1333 1334 1335 1336 1337 1338 1339 | #endif ret = 0; p = (Vdbe *)pStmt; db = p->db; assert( db!=0 ); n = sqlite3_column_count(pStmt); if( N<n && N>=0 ){ | < > < | | 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 | #endif ret = 0; p = (Vdbe *)pStmt; db = p->db; assert( db!=0 ); n = sqlite3_column_count(pStmt); if( N<n && N>=0 ){ N += useType*n; sqlite3_mutex_enter(db->mutex); assert( db->mallocFailed==0 ); #ifndef SQLITE_OMIT_UTF16 if( useUtf16 ){ ret = sqlite3_value_text16((sqlite3_value*)&p->aColName[N]); }else #endif { ret = sqlite3_value_text((sqlite3_value*)&p->aColName[N]); } /* A malloc may have failed inside of the _text() call. If this ** is the case, clear the mallocFailed flag and return NULL. */ if( db->mallocFailed ){ sqlite3OomClear(db); ret = 0; } sqlite3_mutex_leave(db->mutex); } return ret; } |
︙ | ︙ | |||
2135 2136 2137 2138 2139 2140 2141 | sqlite3_stmt *pStmt, /* Prepared statement being queried */ int iScan, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ int flags, void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; | < < | < < < < < < < | | | 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 | sqlite3_stmt *pStmt, /* Prepared statement being queried */ int iScan, /* Index of loop to report on */ int iScanStatusOp, /* Which metric to return */ int flags, void *pOut /* OUT: Write the answer here */ ){ Vdbe *p = (Vdbe*)pStmt; ScanStatus *pScan; int idx; if( iScan<0 ){ int ii; if( iScanStatusOp==SQLITE_SCANSTAT_NCYCLE ){ i64 res = 0; for(ii=0; ii<p->nOp; ii++){ res += p->aOp[ii].nCycle; } *(i64*)pOut = res; return 0; } return 1; } if( flags & SQLITE_SCANSTAT_COMPLEX ){ |
︙ | ︙ | |||
2178 2179 2180 2181 2182 2183 2184 | } } if( idx>=p->nScan ) return 1; switch( iScanStatusOp ){ case SQLITE_SCANSTAT_NLOOP: { if( pScan->addrLoop>0 ){ | | | | 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 | } } if( idx>=p->nScan ) return 1; switch( iScanStatusOp ){ case SQLITE_SCANSTAT_NLOOP: { if( pScan->addrLoop>0 ){ *(sqlite3_int64*)pOut = p->aOp[pScan->addrLoop].nExec; }else{ *(sqlite3_int64*)pOut = -1; } break; } case SQLITE_SCANSTAT_NVISIT: { if( pScan->addrVisit>0 ){ *(sqlite3_int64*)pOut = p->aOp[pScan->addrVisit].nExec; }else{ *(sqlite3_int64*)pOut = -1; } break; } case SQLITE_SCANSTAT_EST: { double r = 1.0; |
︙ | ︙ | |||
2208 2209 2210 2211 2212 2213 2214 | } case SQLITE_SCANSTAT_NAME: { *(const char**)pOut = pScan->zName; break; } case SQLITE_SCANSTAT_EXPLAIN: { if( pScan->addrExplain ){ | | | | | | | | | 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 | } case SQLITE_SCANSTAT_NAME: { *(const char**)pOut = pScan->zName; break; } case SQLITE_SCANSTAT_EXPLAIN: { if( pScan->addrExplain ){ *(const char**)pOut = p->aOp[ pScan->addrExplain ].p4.z; }else{ *(const char**)pOut = 0; } break; } case SQLITE_SCANSTAT_SELECTID: { if( pScan->addrExplain ){ *(int*)pOut = p->aOp[ pScan->addrExplain ].p1; }else{ *(int*)pOut = -1; } break; } case SQLITE_SCANSTAT_PARENTID: { if( pScan->addrExplain ){ *(int*)pOut = p->aOp[ pScan->addrExplain ].p2; }else{ *(int*)pOut = -1; } break; } case SQLITE_SCANSTAT_NCYCLE: { i64 res = 0; if( pScan->aAddrRange[0]==0 ){ res = -1; }else{ int ii; for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){ int iIns = pScan->aAddrRange[ii]; int iEnd = pScan->aAddrRange[ii+1]; if( iIns==0 ) break; if( iIns>0 ){ while( iIns<=iEnd ){ res += p->aOp[iIns].nCycle; iIns++; } }else{ int iOp; for(iOp=0; iOp<p->nOp; iOp++){ Op *pOp = &p->aOp[iOp]; if( pOp->p1!=iEnd ) continue; if( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_NCYCLE)==0 ){ continue; } res += p->aOp[iOp].nCycle; } } } } *(i64*)pOut = res; break; } |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
439 440 441 442 443 444 445 | ** Add a new OP_Explain opcode. ** ** If the bPush flag is true, then make this opcode the parent for ** subsequent Explains until sqlite3VdbeExplainPop() is called. */ int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ int addr = 0; | | | | 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 | ** Add a new OP_Explain opcode. ** ** If the bPush flag is true, then make this opcode the parent for ** subsequent Explains until sqlite3VdbeExplainPop() is called. */ int sqlite3VdbeExplain(Parse *pParse, u8 bPush, const char *zFmt, ...){ int addr = 0; #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) /* Always include the OP_Explain opcodes if SQLITE_DEBUG is defined. ** But omit them (for performance) during production builds */ if( pParse->explain==2 ) #endif { char *zMsg; Vdbe *v; va_list ap; int iThis; va_start(ap, zFmt); |
︙ | ︙ | |||
816 817 818 819 820 821 822 | ** coordinated with changes to mkopcodeh.tcl. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int nMaxArgs = *pMaxFuncArgs; Op *pOp; Parse *pParse = p->pParse; int *aLabel = pParse->aLabel; | < < | 816 817 818 819 820 821 822 823 824 825 826 827 828 829 | ** coordinated with changes to mkopcodeh.tcl. */ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){ int nMaxArgs = *pMaxFuncArgs; Op *pOp; Parse *pParse = p->pParse; int *aLabel = pParse->aLabel; p->readOnly = 1; p->bIsReader = 0; pOp = &p->aOp[p->nOp-1]; assert( p->aOp[0].opcode==OP_Init ); while( 1 /* Loop termates when it reaches the OP_Init opcode */ ){ /* Only JUMP opcodes and the short list of special opcodes in the switch ** below need to be considered. The mkopcodeh.tcl generator script groups |
︙ | ︙ | |||
877 878 879 880 881 882 883 | default: { if( pOp->p2<0 ){ /* The mkopcodeh.tcl script has so arranged things that the only ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to ** have non-negative values for P2. */ assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ); assert( ADDR(pOp->p2)<-pParse->nLabel ); | < | 875 876 877 878 879 880 881 882 883 884 885 886 887 888 | default: { if( pOp->p2<0 ){ /* The mkopcodeh.tcl script has so arranged things that the only ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to ** have non-negative values for P2. */ assert( (sqlite3OpcodeProperty[pOp->opcode] & OPFLG_JUMP)!=0 ); assert( ADDR(pOp->p2)<-pParse->nLabel ); pOp->p2 = aLabel[ADDR(pOp->p2)]; } break; } } /* The mkopcodeh.tcl script has so arranged things that the only ** non-jump opcodes less than SQLITE_MX_JUMP_CODE are guaranteed to |
︙ | ︙ | |||
1121 1122 1123 1124 1125 1126 1127 | Vdbe *p, /* VM to add scanstatus() to */ int addrExplain, /* Address of OP_Explain (or 0) */ int addrLoop, /* Address of loop counter */ int addrVisit, /* Address of rows visited counter */ LogEst nEst, /* Estimated number of output rows */ const char *zName /* Name of table or index being scanned */ ){ | < | | | | | | | | | | | | < < | | | | | | | | | | | | | | < < | | | | | | | | | | | | < | | 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 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 | Vdbe *p, /* VM to add scanstatus() to */ int addrExplain, /* Address of OP_Explain (or 0) */ int addrLoop, /* Address of loop counter */ int addrVisit, /* Address of rows visited counter */ LogEst nEst, /* Estimated number of output rows */ const char *zName /* Name of table or index being scanned */ ){ sqlite3_int64 nByte = (p->nScan+1) * sizeof(ScanStatus); ScanStatus *aNew; aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); if( aNew ){ ScanStatus *pNew = &aNew[p->nScan++]; memset(pNew, 0, sizeof(ScanStatus)); pNew->addrExplain = addrExplain; pNew->addrLoop = addrLoop; pNew->addrVisit = addrVisit; pNew->nEst = nEst; pNew->zName = sqlite3DbStrDup(p->db, zName); p->aScan = aNew; } } /* ** Add the range of instructions from addrStart to addrEnd (inclusive) to ** the set of those corresponding to the sqlite3_stmt_scanstatus() counters ** associated with the OP_Explain instruction at addrExplain. The ** sum of the sqlite3Hwtime() values for each of these instructions ** will be returned for SQLITE_SCANSTAT_NCYCLE requests. */ void sqlite3VdbeScanStatusRange( Vdbe *p, int addrExplain, int addrStart, int addrEnd ){ ScanStatus *pScan = 0; int ii; for(ii=p->nScan-1; ii>=0; ii--){ pScan = &p->aScan[ii]; if( pScan->addrExplain==addrExplain ) break; pScan = 0; } if( pScan ){ if( addrEnd<0 ) addrEnd = sqlite3VdbeCurrentAddr(p)-1; for(ii=0; ii<ArraySize(pScan->aAddrRange); ii+=2){ if( pScan->aAddrRange[ii]==0 ){ pScan->aAddrRange[ii] = addrStart; pScan->aAddrRange[ii+1] = addrEnd; break; } } } } /* ** Set the addresses for the SQLITE_SCANSTAT_NLOOP and SQLITE_SCANSTAT_NROW ** counters for the query element associated with the OP_Explain at ** addrExplain. */ void sqlite3VdbeScanStatusCounters( Vdbe *p, int addrExplain, int addrLoop, int addrVisit ){ ScanStatus *pScan = 0; int ii; for(ii=p->nScan-1; ii>=0; ii--){ pScan = &p->aScan[ii]; if( pScan->addrExplain==addrExplain ) break; pScan = 0; } if( pScan ){ pScan->addrLoop = addrLoop; pScan->addrVisit = addrVisit; } } #endif /* ** Change the value of the opcode, or P1, P2, P3, or P5 operands ** for a specific instruction. */ void sqlite3VdbeChangeOpcode(Vdbe *p, int addr, u8 iNewOpcode){ |
︙ | ︙ | |||
1621 1622 1623 1624 1625 1626 1627 | }else{ return &p->aOp[addr]; } } /* Return the most recently added opcode */ | | | 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 | }else{ return &p->aOp[addr]; } } /* Return the most recently added opcode */ VdbeOp * sqlite3VdbeGetLastOp(Vdbe *p){ return sqlite3VdbeGetOp(p, p->nOp - 1); } #if defined(SQLITE_ENABLE_EXPLAIN_COMMENTS) /* ** Return an integer value for one of the parameters to the opcode pOp ** determined by character c. |
︙ | ︙ | |||
3325 3326 3327 3328 3329 3330 3331 | p->nChange = 0; }else{ db->nDeferredCons = 0; db->nDeferredImmCons = 0; db->flags &= ~(u64)SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } | < < | 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 | p->nChange = 0; }else{ db->nDeferredCons = 0; db->nDeferredImmCons = 0; db->flags &= ~(u64)SQLITE_DeferFKs; sqlite3CommitInternalChanges(db); } }else{ sqlite3RollbackAll(db, SQLITE_OK); p->nChange = 0; } db->nStatement = 0; }else if( eStatementOp==0 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ |
︙ | ︙ | |||
3645 3646 3647 3648 3649 3650 3651 | if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree); } vdbeFreeOpArray(db, p->aOp, p->nOp); if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql); #ifdef SQLITE_ENABLE_NORMALIZE sqlite3DbFree(db, p->zNormSql); { | | | | | 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 | if( p->pFree ) sqlite3DbNNFreeNN(db, p->pFree); } vdbeFreeOpArray(db, p->aOp, p->nOp); if( p->zSql ) sqlite3DbNNFreeNN(db, p->zSql); #ifdef SQLITE_ENABLE_NORMALIZE sqlite3DbFree(db, p->zNormSql); { DblquoteStr *pThis, *pNext; for(pThis=p->pDblStr; pThis; pThis=pNext){ pNext = pThis->pNextStr; sqlite3DbFree(db, pThis); } } #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS { int i; |
︙ | ︙ | |||
5274 5275 5276 5277 5278 5279 5280 | sqlite3_result_error(pCtx, zMsg, -1); sqlite3_free(zMsg); return 0; } return 1; } | < < < < < < < < < < < < < < | 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 | sqlite3_result_error(pCtx, zMsg, -1); sqlite3_free(zMsg); return 0; } return 1; } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored ** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored ** in memory obtained from sqlite3DbMalloc). */ void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){ |
︙ | ︙ | |||
5350 5351 5352 5353 5354 5355 5356 | int iBlobWrite ){ sqlite3 *db = v->db; i64 iKey2; PreUpdate preupdate; const char *zTbl = pTab->zName; static const u8 fakeSortOrder = 0; | < < < < < < < < < < | | | 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 | int iBlobWrite ){ sqlite3 *db = v->db; i64 iKey2; PreUpdate preupdate; const char *zTbl = pTab->zName; static const u8 fakeSortOrder = 0; assert( db->pPreUpdate==0 ); memset(&preupdate, 0, sizeof(PreUpdate)); if( HasRowid(pTab)==0 ){ iKey1 = iKey2 = 0; preupdate.pPk = sqlite3PrimaryKeyIndex(pTab); }else{ if( op==SQLITE_UPDATE ){ iKey2 = v->aMem[iReg].u.i; }else{ iKey2 = iKey1; } } assert( pCsr!=0 ); assert( pCsr->eCurType==CURTYPE_BTREE ); assert( pCsr->nField==pTab->nCol || (pCsr->nField==pTab->nCol+1 && op==SQLITE_DELETE && iReg==-1) ); preupdate.v = v; preupdate.pCsr = pCsr; preupdate.op = op; preupdate.iNewReg = iReg; preupdate.keyinfo.db = db; |
︙ | ︙ |
Changes to src/vdbemem.c.
︙ | ︙ | |||
153 154 155 156 157 158 159 | */ int sqlite3VdbeMemValidStrRep(Mem *p){ Mem tmp; char zBuf[100]; char *z; int i, j, incr; if( (p->flags & MEM_Str)==0 ) return 1; | < | 153 154 155 156 157 158 159 160 161 162 163 164 165 166 | */ int sqlite3VdbeMemValidStrRep(Mem *p){ Mem tmp; char zBuf[100]; char *z; int i, j, incr; if( (p->flags & MEM_Str)==0 ) return 1; if( p->flags & MEM_Term ){ /* Insure that the string is properly zero-terminated. Pay particular ** attention to the case where p->n is odd */ if( p->szMalloc>0 && p->z==p->zMalloc ){ assert( p->enc==SQLITE_UTF8 || p->szMalloc >= ((p->n+1)&~1)+2 ); assert( p->enc!=SQLITE_UTF8 || p->szMalloc >= p->n+1 ); } |
︙ | ︙ | |||
436 437 438 439 440 441 442 | if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ pMem->enc = 0; return SQLITE_NOMEM_BKPT; } vdbeMemRenderNum(nByte, pMem->z, pMem); assert( pMem->z!=0 ); | | | 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 | if( sqlite3VdbeMemClearAndResize(pMem, nByte) ){ pMem->enc = 0; return SQLITE_NOMEM_BKPT; } vdbeMemRenderNum(nByte, pMem->z, pMem); assert( pMem->z!=0 ); assert( pMem->n==sqlite3Strlen30NN(pMem->z) ); pMem->enc = SQLITE_UTF8; pMem->flags |= MEM_Str|MEM_Term; if( bForce ) pMem->flags &= ~(MEM_Int|MEM_Real|MEM_IntReal); sqlite3VdbeChangeEncoding(pMem, enc); return SQLITE_OK; } |
︙ | ︙ | |||
1480 1481 1482 1483 1484 1485 1486 | assert( pCtx!=0 ); assert( (p->flags & EP_TokenOnly)==0 ); assert( ExprUseXList(p) ); pList = p->x.pList; if( pList ) nVal = pList->nExpr; assert( !ExprHasProperty(p, EP_IntValue) ); pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0); | < < < | | 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 | assert( pCtx!=0 ); assert( (p->flags & EP_TokenOnly)==0 ); assert( ExprUseXList(p) ); pList = p->x.pList; if( pList ) nVal = pList->nExpr; assert( !ExprHasProperty(p, EP_IntValue) ); pFunc = sqlite3FindFunction(db, p->u.zToken, nVal, enc, 0); assert( pFunc ); if( (pFunc->funcFlags & (SQLITE_FUNC_CONSTANT|SQLITE_FUNC_SLOCHNG))==0 || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL) ){ return SQLITE_OK; } if( pList ){ apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal); |
︙ | ︙ | |||
1519 1520 1521 1522 1523 1524 1525 1526 | pFunc->xSFunc(&ctx, nVal, apVal); if( ctx.isError ){ rc = ctx.isError; sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); }else{ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); assert( rc==SQLITE_OK ); rc = sqlite3VdbeChangeEncoding(pVal, enc); | > > | > > < | 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 | pFunc->xSFunc(&ctx, nVal, apVal); if( ctx.isError ){ rc = ctx.isError; sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal)); }else{ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8); assert( rc==SQLITE_OK ); assert( enc==pVal->enc || db->mallocFailed ); #if 0 /* Not reachable except after a prior failure */ rc = sqlite3VdbeChangeEncoding(pVal, enc); if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){ rc = SQLITE_TOOBIG; pCtx->pParse->nErr++; } #endif } pCtx->pParse->rc = rc; value_from_function_out: if( rc!=SQLITE_OK ){ pVal = 0; } if( apVal ){ for(i=0; i<nVal; i++){ sqlite3ValueFree(apVal[i]); } sqlite3DbFreeNN(db, apVal); } |
︙ | ︙ | |||
1587 1588 1589 1590 1591 1592 1593 | if( op==TK_CAST ){ u8 aff; assert( !ExprHasProperty(pExpr, EP_IntValue) ); aff = sqlite3AffinityType(pExpr->u.zToken,0); rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); testcase( rc!=SQLITE_OK ); if( *ppVal ){ | < < < < < < < | 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 | if( op==TK_CAST ){ u8 aff; assert( !ExprHasProperty(pExpr, EP_IntValue) ); aff = sqlite3AffinityType(pExpr->u.zToken,0); rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx); testcase( rc!=SQLITE_OK ); if( *ppVal ){ sqlite3VdbeMemCast(*ppVal, aff, enc); sqlite3ValueApplyAffinity(*ppVal, affinity, enc); } return rc; } /* Handle negative integers in a single step. This is needed in the |
︙ | ︙ |
Changes to src/vtab.c.
︙ | ︙ | |||
606 607 608 609 610 611 612 | assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; sCtx.pPrior = db->pVtabCtx; sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; | < < | 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 | assert( &db->pVtabCtx ); assert( xConstruct ); sCtx.pTab = pTab; sCtx.pVTable = pVTable; sCtx.pPrior = db->pVtabCtx; sCtx.bDeclared = 0; db->pVtabCtx = &sCtx; rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); db->pVtabCtx = sCtx.pPrior; if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); assert( sCtx.pTab==pTab ); if( SQLITE_OK!=rc ){ if( zErr==0 ){ *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); |
︙ | ︙ | |||
1327 1328 1329 1330 1331 1332 1333 | p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low; break; } case SQLITE_VTAB_DIRECTONLY: { p->pVTable->eVtabRisk = SQLITE_VTABRISK_High; break; } | < < < < | 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 | p->pVTable->eVtabRisk = SQLITE_VTABRISK_Low; break; } case SQLITE_VTAB_DIRECTONLY: { p->pVTable->eVtabRisk = SQLITE_VTABRISK_High; break; } default: { rc = SQLITE_MISUSE_BKPT; break; } } va_end(ap); } |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
1004 1005 1006 1007 1008 1009 1010 | }else{ s1 = s2 = 0; } assert( nByte>=8 ); assert( (nByte&0x00000007)==0 ); assert( nByte<=65536 ); | < | > > > > > < < < < < < < < < < < < < < < < < < < < < < < < < | 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 | }else{ s1 = s2 = 0; } assert( nByte>=8 ); assert( (nByte&0x00000007)==0 ); assert( nByte<=65536 ); if( nativeCksum ){ do { s1 += *aData++ + s2; s2 += *aData++ + s1; }while( aData<aEnd ); }else{ do { s1 += BYTESWAP32(aData[0]) + s2; s2 += BYTESWAP32(aData[1]) + s1; aData += 2; }while( aData<aEnd ); } aOut[0] = s1; aOut[1] = s2; } /* ** If there is the possibility of concurrent access to the SHM file |
︙ | ︙ | |||
4522 4523 4524 4525 4526 4527 4528 | ** https://sqlite.org/src/info/ff5be73dee */ if( pWal->syncHeader ){ rc = sqlite3OsSync(pWal->apWalFd[iApp], CKPT_SYNC_FLAGS(sync_flags)); if( rc ) return rc; } } | | < < | 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 | ** https://sqlite.org/src/info/ff5be73dee */ if( pWal->syncHeader ){ rc = sqlite3OsSync(pWal->apWalFd[iApp], CKPT_SYNC_FLAGS(sync_flags)); if( rc ) return rc; } } assert( (int)pWal->szPage==szPage ); /* Setup information needed to write frames into the WAL */ w.pWal = pWal; w.pFd = pWal->apWalFd[iApp]; w.iSyncPoint = 0; w.syncFlags = sync_flags; w.szPage = szPage; |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
827 828 829 830 831 832 833 | */ static void explainAutomaticIndex( Parse *pParse, Index *pIdx, /* Automatic index to explain */ int bPartial, /* True if pIdx is a partial index */ int *pAddrExplain /* OUT: Address of OP_Explain */ ){ | | | 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 | */ static void explainAutomaticIndex( Parse *pParse, Index *pIdx, /* Automatic index to explain */ int bPartial, /* True if pIdx is a partial index */ int *pAddrExplain /* OUT: Address of OP_Explain */ ){ if( pParse->explain!=2 ){ Table *pTab = pIdx->pTable; const char *zSep = ""; char *zText = 0; int ii = 0; sqlite3_str *pStr = sqlite3_str_new(pParse->db); sqlite3_str_appendf(pStr,"CREATE AUTOMATIC INDEX ON %s(", pTab->zName); assert( pIdx->nColumn>1 ); |
︙ | ︙ | |||
888 889 890 891 892 893 894 | int i; /* Loop counter */ int mxBitCol; /* Maximum column in pSrc->colUsed */ CollSeq *pColl; /* Collating sequence to on a column */ WhereLoop *pLoop; /* The Loop object */ char *zNotUsed; /* Extra space on the end of pIdx */ Bitmask idxCols; /* Bitmap of columns used for indexing */ Bitmask extraCols; /* Bitmap of additional columns */ | | < | 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 | int i; /* Loop counter */ int mxBitCol; /* Maximum column in pSrc->colUsed */ CollSeq *pColl; /* Collating sequence to on a column */ WhereLoop *pLoop; /* The Loop object */ char *zNotUsed; /* Extra space on the end of pIdx */ Bitmask idxCols; /* Bitmap of columns used for indexing */ Bitmask extraCols; /* Bitmap of additional columns */ u8 sentWarning = 0; /* True if a warnning has been issued */ Expr *pPartial = 0; /* Partial Index Expression */ int iContinue = 0; /* Jump here to skip excluded rows */ SrcItem *pTabItem; /* FROM clause term being indexed */ int addrCounter = 0; /* Address where integer counter is initialized */ int regBase; /* Array of registers where record is assembled */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS int addrExp = 0; /* Address of OP_Explain */ |
︙ | ︙ | |||
959 960 961 962 963 964 965 | ** covering index. A "covering index" is an index that contains all ** columns that are needed by the query. With a covering index, the ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used ** if they go out of sync. */ | < < < | < | 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 | ** covering index. A "covering index" is an index that contains all ** columns that are needed by the query. With a covering index, the ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used ** if they go out of sync. */ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); mxBitCol = MIN(BMS-1,pTable->nCol); testcase( pTable->nCol==BMS-1 ); testcase( pTable->nCol==BMS-2 ); for(i=0; i<mxBitCol; i++){ if( extraCols & MASKBIT(i) ) nKeyCol++; } if( pSrc->colUsed & MASKBIT(BMS-1) ){ |
︙ | ︙ | |||
999 1000 1001 1002 1003 1004 1005 | Expr *pX = pTerm->pExpr; idxCols |= cMask; pIdx->aiColumn[n] = pTerm->u.x.leftColumn; pColl = sqlite3ExprCompareCollSeq(pParse, pX); assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */ pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; n++; | < < < < < < < < < < | 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 | Expr *pX = pTerm->pExpr; idxCols |= cMask; pIdx->aiColumn[n] = pTerm->u.x.leftColumn; pColl = sqlite3ExprCompareCollSeq(pParse, pX); assert( pColl!=0 || pParse->nErr>0 ); /* TH3 collate01.800 */ pIdx->azColl[n] = pColl ? pColl->zName : sqlite3StrBINARY; n++; } } } assert( (u32)n==pLoop->u.btree.nEq ); /* Add additional columns needed to make the automatic index into ** a covering index */ |
︙ | ︙ | |||
1041 1042 1043 1044 1045 1046 1047 | /* Create the automatic index */ explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp); assert( pLevel->iIdxCur>=0 ); pLevel->iIdxCur = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); | | < | 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 | /* Create the automatic index */ explainAutomaticIndex(pParse, pIdx, pPartial!=0, &addrExp); assert( pLevel->iIdxCur>=0 ); pLevel->iIdxCur = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_OpenAutoindex, pLevel->iIdxCur, nKeyCol+1); sqlite3VdbeSetP4KeyInfo(pParse, pIdx); VdbeComment((v, "for %s", pTable->zName)); if( OptimizationEnabled(pParse->db, SQLITE_BloomFilter) ){ pLevel->regFilter = ++pParse->nMem; sqlite3VdbeAddOp2(v, OP_Blob, 10000, pLevel->regFilter); } /* Fill the automatic index with content */ pTabItem = &pWC->pWInfo->pTabList->a[pLevel->iFrom]; if( pTabItem->fg.viaCoroutine ){ |
︙ | ︙ | |||
1135 1136 1137 1138 1139 1140 1141 | int addrCont; /* Jump here to skip a row */ const WhereTerm *pTerm; /* For looping over WHERE clause terms */ const WhereTerm *pWCEnd; /* Last WHERE clause term */ Parse *pParse = pWInfo->pParse; /* Parsing context */ Vdbe *v = pParse->pVdbe; /* VDBE under construction */ WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */ int iCur; /* Cursor for table getting the filter */ | < < < < | 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 | int addrCont; /* Jump here to skip a row */ const WhereTerm *pTerm; /* For looping over WHERE clause terms */ const WhereTerm *pWCEnd; /* Last WHERE clause term */ Parse *pParse = pWInfo->pParse; /* Parsing context */ Vdbe *v = pParse->pVdbe; /* VDBE under construction */ WhereLoop *pLoop = pLevel->pWLoop; /* The loop being coded */ int iCur; /* Cursor for table getting the filter */ assert( pLoop!=0 ); assert( v!=0 ); assert( pLoop->wsFlags & WHERE_BLOOMFILTER ); addrOnce = sqlite3VdbeAddOp0(v, OP_Once); VdbeCoverage(v); do{ |
︙ | ︙ | |||
1195 1196 1197 1198 1199 1200 1201 1202 | sqlite3ReleaseTempReg(pParse, r1); }else{ Index *pIdx = pLoop->u.btree.pIndex; int n = pLoop->u.btree.nEq; int r1 = sqlite3GetTempRange(pParse, n); int jj; for(jj=0; jj<n; jj++){ assert( pIdx->pTable==pItem->pTab ); | > | | 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 | sqlite3ReleaseTempReg(pParse, r1); }else{ Index *pIdx = pLoop->u.btree.pIndex; int n = pLoop->u.btree.nEq; int r1 = sqlite3GetTempRange(pParse, n); int jj; for(jj=0; jj<n; jj++){ int iCol = pIdx->aiColumn[jj]; assert( pIdx->pTable==pItem->pTab ); sqlite3ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iCol,r1+jj); } sqlite3VdbeAddOp4Int(v, OP_FilterAdd, pLevel->regFilter, 0, r1, n); sqlite3ReleaseTempRange(pParse, r1, n); } sqlite3VdbeResolveLabel(v, addrCont); sqlite3VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); VdbeCoverage(v); |
︙ | ︙ | |||
1227 1228 1229 1230 1231 1232 1233 | ** not able to do early evaluation of bloom filters that make use of ** the IN operator */ break; } } }while( iLevel < pWInfo->nLevel ); sqlite3VdbeJumpHere(v, addrOnce); | < | 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | ** not able to do early evaluation of bloom filters that make use of ** the IN operator */ break; } } }while( iLevel < pWInfo->nLevel ); sqlite3VdbeJumpHere(v, addrOnce); } #ifndef SQLITE_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite3_index_info structure. It is the ** responsibility of the caller to eventually release the structure |
︙ | ︙ | |||
1483 1484 1485 1486 1487 1488 1489 | sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); } } | < < < | 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | sqlite3OomFault(pParse->db); }else if( !pVtab->zErrMsg ){ sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc)); }else{ sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg); } } sqlite3_free(pVtab->zErrMsg); pVtab->zErrMsg = 0; return rc; } #endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) */ #ifdef SQLITE_ENABLE_STAT4 |
︙ | ︙ | |||
1529 1530 1531 1532 1533 1534 1535 | #ifndef SQLITE_DEBUG UNUSED_PARAMETER( pParse ); #endif assert( pRec!=0 ); assert( pIdx->nSample>0 ); assert( pRec->nField>0 ); | < | 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | #ifndef SQLITE_DEBUG UNUSED_PARAMETER( pParse ); #endif assert( pRec!=0 ); assert( pIdx->nSample>0 ); assert( pRec->nField>0 ); /* Do a binary search to find the first sample greater than or equal ** to pRec. If pRec contains a single field, the set of samples to search ** is simply the aSample[] array. If the samples in aSample[] contain more ** than one fields, all fields following the first are ignored. ** ** If pRec contains N fields, where N is more than one, then as well as the |
︙ | ︙ | |||
1575 1576 1577 1578 1579 1580 1581 | ** equal to the previous sample in the array. For example, in the above, ** sample 2 is the first sample of a block of N samples, so at first it ** appears that it should be 1 field in size. However, that would make it ** smaller than sample 1, so the binary search would not work. As a result, ** it is extended to two fields. The duplicates that this creates do not ** cause any problems. */ | < < < < < | | 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 | ** equal to the previous sample in the array. For example, in the above, ** sample 2 is the first sample of a block of N samples, so at first it ** appears that it should be 1 field in size. However, that would make it ** smaller than sample 1, so the binary search would not work. As a result, ** it is extended to two fields. The duplicates that this creates do not ** cause any problems. */ nField = MIN(pRec->nField, pIdx->nSample); iCol = 0; iSample = pIdx->nSample * nField; do{ int iSamp; /* Index in aSample[] of test sample */ int n; /* Number of fields in test sample */ iTest = (iMin+iSample)/2; |
︙ | ︙ | |||
1646 1647 1648 1649 1650 1651 1652 | /* if i==0 and iCol==0, then record pRec is smaller than all samples ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must ** be greater than or equal to the (iCol) field prefix of sample i. ** If (i>0), then pRec must also be greater than sample (i-1). */ if( iCol>0 ){ pRec->nField = iCol; assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 | | | | 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 | /* if i==0 and iCol==0, then record pRec is smaller than all samples ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must ** be greater than or equal to the (iCol) field prefix of sample i. ** If (i>0), then pRec must also be greater than sample (i-1). */ if( iCol>0 ){ pRec->nField = iCol; assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0 || pParse->db->mallocFailed ); } if( i>0 ){ pRec->nField = nField; assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0 || pParse->db->mallocFailed ); } } } #endif /* ifdef SQLITE_DEBUG */ if( res==0 ){ /* Record pRec is equal to sample i */ |
︙ | ︙ | |||
2016 2017 2018 2019 2020 2021 2022 | } } #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(pBuilder); assert( pLower || pUpper ); #endif | | | 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 | } } #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(pBuilder); assert( pLower || pUpper ); #endif assert( pUpper==0 || (pUpper->wtFlags & TERM_VNULL)==0 ); nNew = whereRangeAdjust(pLower, nOut); nNew = whereRangeAdjust(pUpper, nNew); /* TUNING: If there is both an upper and lower limit and neither limit ** has an application-defined likelihood(), assume the range is ** reduced by an additional 75%. This means that, by default, an open-ended ** range query (e.g. col > ?) is assumed to match 1/4 of the rows in the |
︙ | ︙ | |||
2148 2149 2150 2151 2152 2153 2154 | nEst = nRow0; rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); nRowEst += nEst; pBuilder->nRecValid = nRecValid; } if( rc==SQLITE_OK ){ | | | 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 | nEst = nRow0; rc = whereEqualScanEst(pParse, pBuilder, pList->a[i].pExpr, &nEst); nRowEst += nEst; pBuilder->nRecValid = nRecValid; } if( rc==SQLITE_OK ){ if( nRowEst > nRow0 ) nRowEst = nRow0; *pnRow = nRowEst; WHERETRACE(0x20,("IN row estimate: est=%d\n", nRowEst)); } assert( pBuilder->nRecValid==nRecValid ); return rc; } #endif /* SQLITE_ENABLE_STAT4 */ |
︙ | ︙ | |||
4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 | */ int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 ); return pHidden->eDistinct; } /* ** Cause the prepared statement that is associated with a call to ** xBestIndex to potentially use all schemas. If the statement being ** prepared is read-only, then just start read transactions on all ** schemas. But if this is a write operation, start writes on all ** schemas. ** ** This is used by the (built-in) sqlite_dbpage virtual table. */ | > > | > > > | 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 | */ int sqlite3_vtab_distinct(sqlite3_index_info *pIdxInfo){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; assert( pHidden->eDistinct>=0 && pHidden->eDistinct<=3 ); return pHidden->eDistinct; } #if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) /* ** Cause the prepared statement that is associated with a call to ** xBestIndex to potentially use all schemas. If the statement being ** prepared is read-only, then just start read transactions on all ** schemas. But if this is a write operation, start writes on all ** schemas. ** ** This is used by the (built-in) sqlite_dbpage virtual table. */ void sqlite3VtabUsesAllSchemas(sqlite3_index_info *pIdxInfo){ HiddenIndexInfo *pHidden = (HiddenIndexInfo*)&pIdxInfo[1]; Parse *pParse = pHidden->pParse; int nDb = pParse->db->nDb; int i; for(i=0; i<nDb; i++){ sqlite3CodeVerifySchema(pParse, i); } if( DbMaskNonZero(pParse->writeMask) ){ for(i=0; i<nDb; i++){ sqlite3BeginWriteOperation(pParse, 0, i); } } } #endif /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. ** ** If there are no LEFT or CROSS JOIN joins in the query, both mPrereq and ** mUnusable are set to 0. Otherwise, mPrereq is a mask of all FROM clause |
︙ | ︙ | |||
5303 5304 5305 5306 5307 5308 5309 | pWInfo->bOrderedInnerLoop = 0; if( pWInfo->pOrderBy ){ pWInfo->nOBSat = pFrom->isOrdered; if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } | < < < < | 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 | pWInfo->bOrderedInnerLoop = 0; if( pWInfo->pOrderBy ){ pWInfo->nOBSat = pFrom->isOrdered; if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ if( pFrom->isOrdered==pWInfo->pOrderBy->nExpr ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } }else{ pWInfo->revMask = pFrom->revLoop; if( pWInfo->nOBSat<=0 ){ pWInfo->nOBSat = 0; if( nLoop>0 ){ u32 wsFlags = pFrom->aLoop[nLoop-1]->wsFlags; if( (wsFlags & WHERE_ONEROW)==0 |
︙ | ︙ | |||
5718 5719 5720 5721 5722 5723 5724 | } #endif p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; p->bMaybeNullRow = bMaybeNullRow; | < < < | 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 | } #endif p->pExpr = sqlite3ExprDup(pParse->db, pExpr, 0); p->iDataCur = pTabItem->iCursor; p->iIdxCur = iIdxCur; p->iIdxCol = i; p->bMaybeNullRow = bMaybeNullRow; #ifdef SQLITE_ENABLE_EXPLAIN_COMMENTS p->zIdxName = pIdx->zName; #endif pParse->pIdxEpr = p; if( p->pIENext==0 ){ sqlite3ParserAddCleanup(pParse, whereIndexedExprCleanup, pParse); } |
︙ | ︙ | |||
5978 5979 5980 5981 5982 5983 5984 | /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( pSelect && pSelect->pLimit ){ sqlite3WhereAddLimit(&pWInfo->sWC, pSelect); } if( pParse->nErr ) goto whereBeginError; | < < | > | < < < < < < < | | < | | | < < < < < < | < < < < < | < < < | | 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 | /* Analyze all of the subexpressions. */ sqlite3WhereExprAnalyze(pTabList, &pWInfo->sWC); if( pSelect && pSelect->pLimit ){ sqlite3WhereAddLimit(&pWInfo->sWC, pSelect); } if( pParse->nErr ) goto whereBeginError; /* Special case: WHERE terms that do not refer to any tables in the join ** (constant expressions). Evaluate each such term, and jump over all the ** generated code if the result is not true. ** ** Do not do this if the expression contains non-deterministic functions ** that are not within a sub-select. This is not strictly required, but ** preserves SQLite's legacy behaviour in the following two cases: ** ** FROM ... WHERE random()>0; -- eval random() once per row ** FROM ... WHERE (SELECT random())>0; -- eval random() once overall */ for(ii=0; ii<sWLB.pWC->nBase; ii++){ WhereTerm *pT = &sWLB.pWC->a[ii]; if( pT->wtFlags & TERM_VIRTUAL ) continue; if( pT->prereqAll==0 && (nTabList==0 || exprIsDeterministic(pT->pExpr)) ){ sqlite3ExprIfFalse(pParse, pT->pExpr, pWInfo->iBreak, SQLITE_JUMPIFNULL); pT->wtFlags |= TERM_CODED; } } if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( OptimizationDisabled(db, SQLITE_DistinctOpt) ){ /* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via |
︙ | ︙ | |||
6259 6260 6261 6262 6263 6264 6265 | Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} sqlite3VdbeChangeP4(v, -1, SQLITE_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } #ifdef SQLITE_ENABLE_CURSOR_HINTS | | | 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 | Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} sqlite3VdbeChangeP4(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 |
︙ | ︙ | |||
6717 6718 6719 6720 6721 6722 6723 | } p = p->pIENext; } } k = pLevel->addrBody + 1; #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeAddopTrace ){ | | < | 6663 6664 6665 6666 6667 6668 6669 6670 6671 6672 6673 6674 6675 6676 6677 | } p = p->pIENext; } } k = pLevel->addrBody + 1; #ifdef SQLITE_DEBUG if( db->flags & SQLITE_VdbeAddopTrace ){ printf("TRANSLATE opcodes in range %d..%d\n", k, last-1); } /* Proof that the "+1" on the k value above is safe */ pOp = sqlite3VdbeGetOp(v, k - 1); assert( pOp->opcode!=OP_Column || pOp->p1!=pLevel->iTabCur ); assert( pOp->opcode!=OP_Rowid || pOp->p1!=pLevel->iTabCur ); assert( pOp->opcode!=OP_IfNullRow || pOp->p1!=pLevel->iTabCur ); #endif |
︙ | ︙ |
Changes to src/wherecode.c.
︙ | ︙ | |||
107 108 109 110 111 112 113 | explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } sqlite3_str_append(pStr, ")", 1); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN | | | | | | | 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 | explainAppendTerm(pStr, pIndex, pLoop->u.btree.nTop, j, i, "<"); } sqlite3_str_append(pStr, ")", 1); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN ** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was ** defined at compile-time. If it is not a no-op, a single OP_Explain opcode ** is added to the output to describe the table scan strategy in pLevel. ** ** If an OP_Explain opcode is added to the VM, its address is returned. ** Otherwise, if no OP_Explain is coded, zero is returned. */ int sqlite3WhereExplainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ u16 wctrlFlags /* Flags passed to sqlite3WhereBegin() */ ){ int ret = 0; #if !defined(SQLITE_DEBUG) && !defined(SQLITE_ENABLE_STMT_SCANSTATUS) if( sqlite3ParseToplevel(pParse)->explain==2 ) #endif { SrcItem *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite3 *db = pParse->db; /* Database handle */ int isSearch; /* True for a SEARCH. False for SCAN. */ WhereLoop *pLoop; /* The controlling WhereLoop object */ |
︙ | ︙ | |||
288 289 290 291 292 293 294 | */ void sqlite3WhereAddScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ ){ | < | | | | | | | | | | | | | | | | | | | < | 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 | */ void sqlite3WhereAddScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ ){ const char *zObj = 0; WhereLoop *pLoop = pLvl->pWLoop; int wsFlags = pLoop->wsFlags; int viaCoroutine = 0; if( (wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 ){ zObj = pLoop->u.btree.pIndex->zName; }else{ zObj = pSrclist->a[pLvl->iFrom].zName; viaCoroutine = pSrclist->a[pLvl->iFrom].fg.viaCoroutine; } sqlite3VdbeScanStatus( v, addrExplain, pLvl->addrBody, pLvl->addrVisit, pLoop->nOut, zObj ); if( viaCoroutine==0 ){ if( (wsFlags & (WHERE_MULTI_OR|WHERE_AUTO_INDEX))==0 ){ sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iTabCur); } if( wsFlags & WHERE_INDEXED ){ sqlite3VdbeScanStatusRange(v, addrExplain, -1, pLvl->iIdxCur); } } } #endif /* |
︙ | ︙ | |||
487 488 489 490 491 492 493 | static Expr *removeUnindexableInClauseTerms( Parse *pParse, /* The parsing context */ int iEq, /* Look at loop terms starting here */ WhereLoop *pLoop, /* The current loop */ Expr *pX /* The IN expression to be reduced */ ){ sqlite3 *db = pParse->db; | < < | | | | | > | | | | < | < | | | | | | | | < | | | | | < | < | | < | | | | | | | | | | > | | | | | | | | | | | | | | | | | < | 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 | static Expr *removeUnindexableInClauseTerms( Parse *pParse, /* The parsing context */ int iEq, /* Look at loop terms starting here */ WhereLoop *pLoop, /* The current loop */ Expr *pX /* The IN expression to be reduced */ ){ sqlite3 *db = pParse->db; Expr *pNew; pNew = sqlite3ExprDup(db, pX, 0); if( db->mallocFailed==0 ){ ExprList *pOrigRhs; /* Original unmodified RHS */ ExprList *pOrigLhs; /* Original unmodified LHS */ ExprList *pRhs = 0; /* New RHS after modifications */ ExprList *pLhs = 0; /* New LHS after mods */ int i; /* Loop counter */ Select *pSelect; /* Pointer to the SELECT on the RHS */ assert( ExprUseXSelect(pNew) ); pOrigRhs = pNew->x.pSelect->pEList; assert( pNew->pLeft!=0 ); assert( ExprUseXList(pNew->pLeft) ); pOrigLhs = pNew->pLeft->x.pList; for(i=iEq; i<pLoop->nLTerm; i++){ if( pLoop->aLTerm[i]->pExpr==pX ){ int iField; assert( (pLoop->aLTerm[i]->eOperator & (WO_OR|WO_AND))==0 ); iField = pLoop->aLTerm[i]->u.x.iField - 1; if( pOrigRhs->a[iField].pExpr==0 ) continue; /* Duplicate PK column */ pRhs = sqlite3ExprListAppend(pParse, pRhs, pOrigRhs->a[iField].pExpr); pOrigRhs->a[iField].pExpr = 0; assert( pOrigLhs->a[iField].pExpr!=0 ); pLhs = sqlite3ExprListAppend(pParse, pLhs, pOrigLhs->a[iField].pExpr); pOrigLhs->a[iField].pExpr = 0; } } sqlite3ExprListDelete(db, pOrigRhs); sqlite3ExprListDelete(db, pOrigLhs); pNew->pLeft->x.pList = pLhs; pNew->x.pSelect->pEList = pRhs; if( pLhs && pLhs->nExpr==1 ){ /* Take care here not to generate a TK_VECTOR containing only a ** single value. Since the parser never creates such a vector, some ** of the subroutines do not handle this case. */ Expr *p = pLhs->a[0].pExpr; pLhs->a[0].pExpr = 0; sqlite3ExprDelete(db, pNew->pLeft); pNew->pLeft = p; } pSelect = pNew->x.pSelect; if( pSelect->pOrderBy ){ /* If the SELECT statement has an ORDER BY clause, zero the ** iOrderByCol variables. These are set to non-zero when an ** ORDER BY term exactly matches one of the terms of the ** result-set. Since the result-set of the SELECT statement may ** have been modified or reordered, these variables are no longer ** set correctly. Since setting them is just an optimization, ** it's easiest just to zero them here. */ ExprList *pOrderBy = pSelect->pOrderBy; for(i=0; i<pOrderBy->nExpr; i++){ pOrderBy->a[i].u.x.iOrderByCol = 0; } } #if 0 printf("For indexing, change the IN expr:\n"); sqlite3TreeViewExpr(0, pX, 0); printf("Into:\n"); sqlite3TreeViewExpr(0, pNew, 0); #endif } return pNew; } /* ** Generate code for a single equality term of the WHERE clause. An equality |
︙ | ︙ | |||
1007 1008 1009 1010 1011 1012 1013 | ** 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; | < | | | | | | > | < < | > | | 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 | ** 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 ){ int reg = ++pWalker->pParse->nMem; /* Register for column value */ sqlite3ExprCode(pWalker->pParse, pExpr, reg); pExpr->op = TK_REGISTER; pExpr->iTable = reg; }else if( pHint->pIdx!=0 ){ pExpr->iTable = pHint->iIdxCur; pExpr->iColumn = sqlite3TableColumnToIndex(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. */ |
︙ | ︙ | |||
1130 1131 1132 1133 1134 1135 1136 | } /* If we survive all prior tests, that means this term is worth hinting */ pExpr = sqlite3ExprAnd(pParse, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0)); } if( pExpr!=0 ){ sWalker.xExprCallback = codeCursorHintFixExpr; | | | 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 | } /* If we survive all prior tests, that means this term is worth hinting */ pExpr = sqlite3ExprAnd(pParse, 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,D) /* No-op */ |
︙ | ︙ | |||
1924 1925 1926 1927 1928 1929 1930 | ** should we try before giving up and going with a seek. The cost ** of a seek is proportional to the logarithm of the of the number ** of entries in the tree, so basing the number of steps to try ** on the estimated number of rows in the btree seems like a good ** guess. */ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10); | | | 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 | ** should we try before giving up and going with a seek. The cost ** of a seek is proportional to the logarithm of the of the number ** of entries in the tree, so basing the number of steps to try ** on the estimated number of rows in the btree seems like a good ** guess. */ addrSeekScan = sqlite3VdbeAddOp1(v, OP_SeekScan, (pIdx->aiRowLogEst[0]+9)/10); if( pRangeStart ){ sqlite3VdbeChangeP5(v, 1); sqlite3VdbeChangeP2(v, addrSeekScan, sqlite3VdbeCurrentAddr(v)+1); addrSeekScan = 0; } VdbeCoverage(v); } sqlite3VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); |
︙ | ︙ | |||
1965 1966 1967 1968 1969 1970 1971 | /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; assert( pLevel->p2==0 ); if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; | | > > > > > > > > > | 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 | /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; assert( pLevel->p2==0 ); if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; if( addrSeekScan ){ /* For a seek-scan that has a range on the lowest term of the index, ** we have to make the top of the loop be code that sets the end ** condition of the range. Otherwise, the OP_SeekScan might jump ** over that initialization, leaving the range-end value set to the ** range-start value, resulting in a wrong answer. ** See ticket 5981a8c041a3c2f3 (2021-11-02). */ pLevel->p2 = sqlite3VdbeCurrentAddr(v); } codeExprOrVector(pParse, pRight, regBase+nEq, nTop); whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 && sqlite3ExprCanBeNull(pRight) ){ sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt); VdbeCoverage(v); |
︙ | ︙ | |||
1999 2000 2001 2002 2003 2004 2005 | } nConstraint++; } if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff); if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff); /* Top of the loop body */ | | | 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 | } nConstraint++; } if( zStartAff ) sqlite3DbNNFreeNN(db, zStartAff); if( zEndAff ) sqlite3DbNNFreeNN(db, zEndAff); /* Top of the loop body */ if( pLevel->p2==0 ) pLevel->p2 = sqlite3VdbeCurrentAddr(v); /* Check if the index cursor is past the end of the range. */ if( nConstraint ){ if( regBignull ){ /* Except, skip the end-of-range check while doing the NULL-scan */ sqlite3VdbeAddOp2(v, OP_IfNot, regBignull, sqlite3VdbeCurrentAddr(v)+3); VdbeComment((v, "If NULL-scan 2nd pass")); |
︙ | ︙ |
Changes to src/whereexpr.c.
︙ | ︙ | |||
970 971 972 973 974 975 976 977 | ** ** If pExpr is a TK_COLUMN column reference, then this routine always returns ** true even if that particular column is not indexed, because the column ** might be added to an automatic index later. */ static SQLITE_NOINLINE int exprMightBeIndexed2( SrcList *pFrom, /* The FROM clause */ int *aiCurCol, /* Write the referenced table cursor and column here */ | > | < | | | | | | | | < < | | | | | | < > < < > | | < < < | < < < < | 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 | ** ** If pExpr is a TK_COLUMN column reference, then this routine always returns ** true even if that particular column is not indexed, because the column ** might be added to an automatic index later. */ static SQLITE_NOINLINE int exprMightBeIndexed2( SrcList *pFrom, /* The FROM clause */ Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ int *aiCurCol, /* Write the referenced table cursor and column here */ Expr *pExpr /* An operand of a comparison operator */ ){ Index *pIdx; int i; int iCur; for(i=0; mPrereq>1; i++, mPrereq>>=1){} iCur = pFrom->a[i].iCursor; for(pIdx=pFrom->a[i].pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->aColExpr==0 ) continue; for(i=0; i<pIdx->nKeyCol; i++){ if( pIdx->aiColumn[i]!=XN_EXPR ) continue; assert( pIdx->bHasExpr ); if( sqlite3ExprCompareSkip(pExpr, pIdx->aColExpr->a[i].pExpr, iCur)==0 ){ aiCurCol[0] = iCur; aiCurCol[1] = XN_EXPR; return 1; } } } return 0; } static int exprMightBeIndexed( SrcList *pFrom, /* The FROM clause */ Bitmask mPrereq, /* Bitmask of FROM clause terms referenced by pExpr */ int *aiCurCol, /* Write the referenced table cursor & column here */ Expr *pExpr, /* An operand of a comparison operator */ int op /* The specific comparison operator */ ){ /* If this expression is a vector to the left or right of a ** inequality constraint (>, <, >= or <=), perform the processing ** on the first element of the vector. */ assert( TK_GT+1==TK_LE && TK_GT+2==TK_LT && TK_GT+3==TK_GE ); assert( TK_IS<TK_GE && TK_ISNULL<TK_GE && TK_IN<TK_GE ); assert( op<=TK_GE ); if( pExpr->op==TK_VECTOR && (op>=TK_GT && ALWAYS(op<=TK_GE)) ){ assert( ExprUseXList(pExpr) ); pExpr = pExpr->x.pList->a[0].pExpr; } if( pExpr->op==TK_COLUMN ){ aiCurCol[0] = pExpr->iTable; aiCurCol[1] = pExpr->iColumn; return 1; } if( mPrereq==0 ) return 0; /* No table references */ if( (mPrereq&(mPrereq-1))!=0 ) return 0; /* Refs more than one table */ return exprMightBeIndexed2(pFrom,mPrereq,aiCurCol,pExpr); } /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm |
︙ | ︙ | |||
1155 1156 1157 1158 1159 1160 1161 | if( pTerm->u.x.iField>0 ){ assert( op==TK_IN ); assert( pLeft->op==TK_VECTOR ); assert( ExprUseXList(pLeft) ); pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr; } | | | | 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 | if( pTerm->u.x.iField>0 ){ assert( op==TK_IN ); assert( pLeft->op==TK_VECTOR ); assert( ExprUseXList(pLeft) ); pLeft = pLeft->x.pList->a[pTerm->u.x.iField-1].pExpr; } if( exprMightBeIndexed(pSrc, prereqLeft, aiCurCol, pLeft, op) ){ pTerm->leftCursor = aiCurCol[0]; assert( (pTerm->eOperator & (WO_OR|WO_AND))==0 ); pTerm->u.x.leftColumn = aiCurCol[1]; pTerm->eOperator = operatorMask(op) & opMask; } if( op==TK_IS ) pTerm->wtFlags |= TERM_IS; if( pRight && exprMightBeIndexed(pSrc, pTerm->prereqRight, aiCurCol, pRight, op) && !ExprHasProperty(pRight, EP_FixedCol) ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ assert( pTerm->u.x.iField==0 ); if( pTerm->leftCursor>=0 ){ |
︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 | pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; }else if( op==TK_ISNULL && !ExprHasProperty(pExpr,EP_OuterON) && 0==sqlite3ExprCanBeNull(pLeft) ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); | | | 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 | pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; }else if( op==TK_ISNULL && !ExprHasProperty(pExpr,EP_OuterON) && 0==sqlite3ExprCanBeNull(pLeft) ){ assert( !ExprHasProperty(pExpr, EP_IntValue) ); pExpr->op = TK_TRUEFALSE; pExpr->u.zToken = "false"; ExprSetProperty(pExpr, EP_IsFalse); pTerm->prereqAll = 0; pTerm->eOperator = 0; } } |
︙ | ︙ | |||
1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 | pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), pStr1); transferJoinMarkings(pNewExpr1, pExpr); idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), pStr2); transferJoinMarkings(pNewExpr2, pExpr); idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); | > < | 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 | pNewExpr1 = sqlite3ExprDup(db, pLeft, 0); pNewExpr1 = sqlite3PExpr(pParse, TK_GE, sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName), pStr1); transferJoinMarkings(pNewExpr1, pExpr); idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite3ExprDup(db, pLeft, 0); pNewExpr2 = sqlite3PExpr(pParse, TK_LT, sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName), pStr2); transferJoinMarkings(pNewExpr2, pExpr); idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; if( isComplete ){ markTermAsChild(pWC, idxNew1, idxTerm); markTermAsChild(pWC, idxNew2, idxTerm); } } |
︙ | ︙ | |||
1438 1439 1440 1441 1442 1443 1444 | ** This only works if the RHS is a simple SELECT (not a compound) that does ** not use window functions. */ else if( pExpr->op==TK_IN && pTerm->u.x.iField==0 && pExpr->pLeft->op==TK_VECTOR && ALWAYS( ExprUseXSelect(pExpr) ) | | | 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 | ** This only works if the RHS is a simple SELECT (not a compound) that does ** not use window functions. */ else if( pExpr->op==TK_IN && pTerm->u.x.iField==0 && pExpr->pLeft->op==TK_VECTOR && ALWAYS( ExprUseXSelect(pExpr) ) && pExpr->x.pSelect->pPrior==0 #ifndef SQLITE_OMIT_WINDOWFUNC && pExpr->x.pSelect->pWin==0 #endif && pWC->op==TK_AND ){ int i; for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){ |
︙ | ︙ | |||
1852 1853 1854 1855 1856 1857 1858 | pColRef->iColumn = k++; assert( ExprUseYTab(pColRef) ); pColRef->y.pTab = pTab; pItem->colUsed |= sqlite3ExprColUsed(pColRef); pRhs = sqlite3PExpr(pParse, TK_UPLUS, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); | | < < < | 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 | pColRef->iColumn = k++; assert( ExprUseYTab(pColRef) ); pColRef->y.pTab = pTab; pItem->colUsed |= sqlite3ExprColUsed(pColRef); pRhs = sqlite3PExpr(pParse, TK_UPLUS, sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){ joinType = EP_OuterON; }else{ joinType = EP_InnerON; } sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } |
Changes to src/window.c.
︙ | ︙ | |||
781 782 783 784 785 786 787 | assert( pWin->pOwner==pExpr ); return WRC_Prune; } } } /* no break */ deliberate_fall_through | < | 781 782 783 784 785 786 787 788 789 790 791 792 793 794 | assert( pWin->pOwner==pExpr ); return WRC_Prune; } } } /* no break */ deliberate_fall_through case TK_AGG_FUNCTION: case TK_COLUMN: { int iCol = -1; if( pParse->db->mallocFailed ) return WRC_Abort; if( p->pSub ){ int i; for(i=0; i<p->pSub->nExpr; i++){ |
︙ | ︙ |
Deleted test/aggfault.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/altertab.test.
︙ | ︙ | |||
977 978 979 980 981 982 983 | CREATE TABLE t1(x); CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN UPDATE t1 SET x=x FROM (SELECT*); END; ALTER TABLE t1 RENAME TO x; } {1 {error in trigger r1: no tables specified}} | < < < < < < < < < < < < < < < < < < | 977 978 979 980 981 982 983 984 | CREATE TABLE t1(x); CREATE TRIGGER r1 BEFORE INSERT ON t1 BEGIN UPDATE t1 SET x=x FROM (SELECT*); END; ALTER TABLE t1 RENAME TO x; } {1 {error in trigger r1: no tables specified}} finish_test |
Changes to test/analyze3.test.
︙ | ︙ | |||
732 733 734 735 736 737 738 | ANALYZE; SELECT * FROM sqlite_stat1; INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); ANALYZE sqlite_master; } | < < < < < < < < < < < < < < < < < < < < < < < < < < < | 732 733 734 735 736 737 738 739 | ANALYZE; SELECT * FROM sqlite_stat1; INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); INSERT INTO sqlite_stat1(tbl,idx,stat) VALUES('t1','t1a','12000'); ANALYZE sqlite_master; } finish_test |
Changes to test/analyzeE.test.
︙ | ︙ | |||
235 236 237 238 239 240 241 | SELECT * FROM t1 WHERE a<1100 AND c=123 } {/SEARCH t1 USING INDEX t1ca/} do_execsql_test analyzeE-4.11 { EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a<1900 AND c=123 } {/SCAN t1/} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 235 236 237 238 239 240 241 242 | SELECT * FROM t1 WHERE a<1100 AND c=123 } {/SEARCH t1 USING INDEX t1ca/} do_execsql_test analyzeE-4.11 { EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a<1900 AND c=123 } {/SCAN t1/} finish_test |
Changes to test/autoindex1.test.
︙ | ︙ | |||
190 191 192 193 194 195 196 | do_eqp_test autoindex1-501 { SELECT b FROM t501 WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b); } { QUERY PLAN |--SCAN t501 `--CORRELATED LIST SUBQUERY xxxxxx | < | 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | do_eqp_test autoindex1-501 { SELECT b FROM t501 WHERE t501.a IN (SELECT x FROM t502 WHERE y=t501.b); } { QUERY PLAN |--SCAN t501 `--CORRELATED LIST SUBQUERY xxxxxx `--SEARCH t502 USING AUTOMATIC COVERING INDEX (y=?) } do_eqp_test autoindex1-502 { SELECT b FROM t501 WHERE t501.a=123 AND t501.a IN (SELECT x FROM t502 WHERE y=t501.b); } { |
︙ | ︙ |
Changes to test/autoindex3.test.
︙ | ︙ | |||
82 83 84 85 86 87 88 | # automatic index scan. # do_eqp_test 220 { select count(*) from u, v where u.b = v.b and v.e > 34; } { QUERY PLAN |--SEARCH v USING INDEX ve (e>?) | < | 82 83 84 85 86 87 88 89 90 91 92 93 | # automatic index scan. # do_eqp_test 220 { select count(*) from u, v where u.b = v.b and v.e > 34; } { QUERY PLAN |--SEARCH v USING INDEX ve (e>?) `--SEARCH u USING AUTOMATIC COVERING INDEX (b=?) } finish_test |
Changes to test/backup.test.
︙ | ︙ | |||
973 974 975 976 977 978 979 | # do_test backup-11.1 { sqlite3 db1 :memory: sqlite3 db2 :memory: sqlite3_backup B db1 main db2 temp B finish } {SQLITE_OK} | < < < < < < < < < < < < < < < < < < < < < < < | 973 974 975 976 977 978 979 980 981 | # do_test backup-11.1 { sqlite3 db1 :memory: sqlite3 db2 :memory: sqlite3_backup B db1 main db2 temp B finish } {SQLITE_OK} finish_test |
Changes to test/bloom1.test.
︙ | ︙ | |||
95 96 97 98 99 100 101 | |--CO-ROUTINE transit | |--SETUP | | `--SEARCH objs USING COVERING INDEX objs_cspo (o=? AND p=?) | `--RECURSIVE STEP | |--SCAN transit | `--SEARCH objs USING COVERING INDEX objs_cspo (o=? AND p=?) `--SCAN transit | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 95 96 97 98 99 100 101 102 103 104 | |--CO-ROUTINE transit | |--SETUP | | `--SEARCH objs USING COVERING INDEX objs_cspo (o=? AND p=?) | `--RECURSIVE STEP | |--SCAN transit | `--SEARCH objs USING COVERING INDEX objs_cspo (o=? AND p=?) `--SCAN transit } finish_test |
Changes to test/corrupt2.test.
︙ | ︙ | |||
95 96 97 98 99 100 101 | close $f sqlite3 db2 corrupt.db # Note: This test is no longer meaningful due to the deferred computation # of MemPage.nFree catchsql {PRAGMA quick_check} db2 } {0 {{*** in database main *** | | | | 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 | close $f sqlite3 db2 corrupt.db # Note: This test is no longer meaningful due to the deferred computation # of MemPage.nFree catchsql {PRAGMA quick_check} db2 } {0 {{*** in database main *** Page 1: free space corruption}}} do_test corrupt2-1.5 { db2 close # Corrupt the free-block list on page 1. forcedelete corrupt.db forcedelete corrupt.db-journal forcecopy test.db corrupt.db set f [open corrupt.db RDWR] fconfigure $f -encoding binary seek $f 101 start puts -nonewline $f "\x00\xC8" seek $f 200 start puts -nonewline $f "\x00\x00" puts -nonewline $f "\x10\x00" close $f sqlite3 db2 corrupt.db catchsql {PRAGMA quick_check} db2 } {0 {{*** in database main *** Page 1: free space corruption}}} db2 close # Corrupt a database by having 2 indices of the same name: do_test corrupt2-2.1 { forcedelete corrupt.db forcedelete corrupt.db-journal |
︙ | ︙ | |||
244 245 246 247 248 249 250 | db2 eval $::presql db2 eval {SELECT rowid FROM t1} { set result [db2 eval {pragma integrity_check}] break } set result } {{*** in database main *** | | | | 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | db2 eval $::presql db2 eval {SELECT rowid FROM t1} { set result [db2 eval {pragma integrity_check}] break } set result } {{*** in database main *** On tree page 2 cell 0: 2nd reference to page 10 Page 4 is never used}} db2 close proc corruption_test {args} { set A(-corrupt) {} set A(-sqlprep) {} set A(-tclprep) {} |
︙ | ︙ | |||
587 588 589 590 591 592 593 | sqlite3 db test.db execsql { PRAGMA freelist_count } } {2} do_execsql_test 14.3 { PRAGMA integrity_check; } {{*** in database main *** | | | | 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 | sqlite3 db test.db execsql { PRAGMA freelist_count } } {2} do_execsql_test 14.3 { PRAGMA integrity_check; } {{*** in database main *** Main freelist: size is 3 but should be 2}} # Use 2 of the free pages on the free-list. # do_execsql_test 14.4 { INSERT INTO t1 VALUES(randomblob(2500)); PRAGMA freelist_count; } {0} do_execsql_test 14.5 { PRAGMA integrity_check; } {{*** in database main *** Main freelist: size is 1 but should be 0}} finish_test finish_test |
Changes to test/corrupt3.test.
︙ | ︙ | |||
78 79 80 81 82 83 84 | } } [list 0 $bigstring] do_test corrupt3-1.8 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** | | | | | | | 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 | } } [list 0 $bigstring] do_test corrupt3-1.8 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** On tree page 2 cell 0: 2nd reference to page 3}}} # Change the pointer for the first page of the overflow # change to be a non-existant page. # do_test corrupt3-1.9 { db close hexio_write test.db 2044 [hexio_render_int32 4] sqlite3 db test.db catchsql { SELECT substr(x,1,10) FROM t1 } } [list 1 {database disk image is malformed}] do_test corrupt3-1.10 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** On tree page 2 cell 0: invalid page number 4 Page 3 is never used}}} do_test corrupt3-1.11 { db close hexio_write test.db 2044 [hexio_render_int32 0] sqlite3 db test.db catchsql { SELECT substr(x,1,10) FROM t1 } } [list 1 {database disk image is malformed}] do_test corrupt3-1.12 { catchsql { PRAGMA integrity_check } } {0 {{*** in database main *** On tree page 2 cell 0: overflow list length is 0 but should be 1 Page 3 is never used}}} finish_test |
Changes to test/corrupt7.test.
︙ | ︙ | |||
66 67 68 69 70 71 72 | # on page 2 of the database. do_test corrupt7-2.1 { db close hexio_write test.db 1062 FF sqlite3 db test.db db eval {PRAGMA integrity_check(1)} } {{*** in database main *** | | | | 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 | # on page 2 of the database. do_test corrupt7-2.1 { db close hexio_write test.db 1062 FF sqlite3 db test.db db eval {PRAGMA integrity_check(1)} } {{*** in database main *** On tree page 2 cell 15: Offset 65457 out of range 945..1020}} do_test corrupt7-2.2 { db close hexio_write test.db 1062 04 sqlite3 db test.db db eval {PRAGMA integrity_check(1)} } {{*** in database main *** On tree page 2 cell 15: Offset 1201 out of range 945..1020}} # The code path that was causing the buffer overrun that this test # case was checking for was removed. # #do_test corrupt7-3.1 { # execsql { # DROP TABLE t1; |
︙ | ︙ |
Changes to test/corruptC.test.
︙ | ︙ | |||
94 95 96 97 98 99 100 | # insert corrupt byte(s) hexio_write test.db 2053 [format %02x 0x04] sqlite3 db test.db catchsql {PRAGMA integrity_check} } {0 {{*** in database main *** | | | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | # insert corrupt byte(s) hexio_write test.db 2053 [format %02x 0x04] sqlite3 db test.db catchsql {PRAGMA integrity_check} } {0 {{*** in database main *** Page 3: free space corruption}}} # test that a corrupt content offset size is handled (seed 5649) # # Update 2016-12-27: As of check-in [0b86fbca66] "In sqlite3BtreeInsert() when # replacing a re-existing row, try to overwrite the cell directly rather than # deallocate and reallocate the cell" on 2016-12-09, this test case no longer # detects the offset size problem during the UPDATE. We have to run a subsequent |
︙ | ︙ | |||
161 162 163 164 165 166 167 | hexio_write test.db 3119 [format %02x 0xdf] hexio_write test.db 4073 [format %02x 0xbf] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} catchsql {PRAGMA integrity_check} } {0 {{*** in database main *** | | | 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 | hexio_write test.db 3119 [format %02x 0xdf] hexio_write test.db 4073 [format %02x 0xbf] sqlite3 db test.db catchsql {BEGIN; UPDATE t2 SET y='abcdef-uvwxyz'; ROLLBACK;} catchsql {PRAGMA integrity_check} } {0 {{*** in database main *** On tree page 4 cell 19: Extends off end of page} {database disk image is malformed}}} # {0 {{*** in database main *** # Corruption detected in cell 710 on page 4 # Multiple uses for byte 661 of page 4 # Fragmented space is 249 byte reported as 21 on page 4}}} # test that a corrupt free cell size is handled (seed 169595) |
︙ | ︙ |
Changes to test/corruptD.test.
︙ | ︙ | |||
109 110 111 112 113 114 115 | # containing the offset of the first free block in a page. # do_test corruptD-1.1.1 { incr_change_counter hexio_write test.db [expr 1024+1] FFFF catchsql { PRAGMA quick_check } } {0 {{*** in database main *** | | | 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | # containing the offset of the first free block in a page. # do_test corruptD-1.1.1 { incr_change_counter hexio_write test.db [expr 1024+1] FFFF catchsql { PRAGMA quick_check } } {0 {{*** in database main *** Page 2: free space corruption}}} do_test corruptD-1.1.2 { incr_change_counter hexio_write test.db [expr 1024+1] [hexio_render_int32 1021] catchsql { SELECT * FROM t1 ORDER BY rowid } } {1 {database disk image is malformed}} #------------------------------------------------------------------------- |
︙ | ︙ |
Changes to test/corruptI.test.
︙ | ︙ | |||
119 120 121 122 123 124 125 126 127 128 129 130 131 | INSERT INTO t1 VALUES(-1, 'abcdefghij'); INSERT INTO t1 VALUES(0, 'abcdefghij'); } set root [db one {SELECT rootpage FROM sqlite_master}] set offset [expr ($root-1) * 65536] do_test 4.1 { db close hexio_write test.db [expr $offset + 8 + 2] 0000 hexio_write test.db [expr $offset + 5] 0000 sqlite3 db test.db catchsql { DELETE FROM t1 WHERE a=0 } | > > > > > | | 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 | INSERT INTO t1 VALUES(-1, 'abcdefghij'); INSERT INTO t1 VALUES(0, 'abcdefghij'); } set root [db one {SELECT rootpage FROM sqlite_master}] set offset [expr ($root-1) * 65536] ifcapable oversize_cell_check { set res {1 {database disk image is malformed}} } else { set res {0 {}} } do_test 4.1 { db close hexio_write test.db [expr $offset + 8 + 2] 0000 hexio_write test.db [expr $offset + 5] 0000 sqlite3 db test.db catchsql { DELETE FROM t1 WHERE a=0 } } $res #------------------------------------------------------------------------- # Database properties: # # * Incremental vacuum mode. # * Database root table has a single leaf page. |
︙ | ︙ |
Changes to test/corruptL.test.
︙ | ︙ | |||
1265 1266 1267 1268 1269 1270 1271 | | 4048: 37 20 31 0b 03 04 11 11 13 63 31 63 31 37 20 31 7 1......c1c17 1 | 4064: 0e 02 04 11 13 07 63 31 63 31 64 37 20 31 20 31 ......c1c1d7 1 1 | 4080: 0e 01 04 11 13 17 63 31 63 31 63 37 20 31 00 00 ......c1c1c7 1.. | end crash-3afa1ca9e9c1bd.db }]} {} extra_schema_checks 0 | | | < < < | 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 | | 4048: 37 20 31 0b 03 04 11 11 13 63 31 63 31 37 20 31 7 1......c1c17 1 | 4064: 0e 02 04 11 13 07 63 31 63 31 64 37 20 31 20 31 ......c1c1d7 1 1 | 4080: 0e 01 04 11 13 17 63 31 63 31 63 37 20 31 00 00 ......c1c1c7 1.. | end crash-3afa1ca9e9c1bd.db }]} {} extra_schema_checks 0 do_execsql_test 15.1 { PRAGMA cell_size_check = 0; UPDATE c1 SET c= NOT EXISTS(SELECT 1 FROM c1 ORDER BY (SELECT 1 FROM c1 ORDER BY a)) +10 WHERE d BETWEEN 4 AND 7; } {} extra_schema_checks 1 #------------------------------------------------------------------------- reset_db do_execsql_test 16.0 { CREATE TABLE t1(w, x, y, z, UNIQUE(w, x), UNIQUE(y, z)); INSERT INTO t1 VALUES(1, 1, 1, 1); |
︙ | ︙ |
Changes to test/countofview.test.
︙ | ︙ | |||
47 48 49 50 51 52 53 | CREATE VIEW v1(x,y) AS SELECT x,1 FROM t1 UNION ALL SELECT x,2 FROM t1; SELECT count(*) FROM v1 WHERE x<>1; } {4} do_execsql_test 2.1 { SELECT count(*) FROM v1 GROUP BY y; } {3 3} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 47 48 49 50 51 52 53 54 55 56 | CREATE VIEW v1(x,y) AS SELECT x,1 FROM t1 UNION ALL SELECT x,2 FROM t1; SELECT count(*) FROM v1 WHERE x<>1; } {4} do_execsql_test 2.1 { SELECT count(*) FROM v1 GROUP BY y; } {3 3} finish_test |
Changes to test/cursorhint.test.
︙ | ︙ | |||
154 155 156 157 158 159 160 | } } {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))} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 154 155 156 157 158 159 160 161 162 | } } {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/delete.test.
︙ | ︙ | |||
412 413 414 415 416 417 418 | do_execsql_test delete-11.1 { DELETE FROM t11 AS xyz WHERE EXISTS(SELECT 1 FROM t11 WHERE t11.a>xyz.a AND t11.b<=xyz.b); SELECT * FROM t11; } {6 2 12 4 18 6 19 23 20 40} | < < < < < < < < < < < < < < < < < < < < < < < < | 412 413 414 415 416 417 418 419 | do_execsql_test delete-11.1 { DELETE FROM t11 AS xyz WHERE EXISTS(SELECT 1 FROM t11 WHERE t11.a>xyz.a AND t11.b<=xyz.b); SELECT * FROM t11; } {6 2 12 4 18 6 19 23 20 40} finish_test |
Changes to test/distinct.test.
︙ | ︙ | |||
344 345 346 347 348 349 350 | ORDER BY a COLLATE nocase, b COLLATE nocase } { a a a b a c b a b b b c } } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 344 345 346 347 348 349 350 351 352 | ORDER BY a COLLATE nocase, b COLLATE nocase } { a a a b a c b a b b b c } } finish_test |
Changes to test/distinct2.test.
︙ | ︙ | |||
297 298 299 300 301 302 303 | do_execsql_test 3030 { SELECT DISTINCT * FROM t0 WHERE NULL IS c0; } { {} 1 {} {} 1 a } | < < < < < < < < < < < < | 297 298 299 300 301 302 303 304 | do_execsql_test 3030 { SELECT DISTINCT * FROM t0 WHERE NULL IS c0; } { {} 1 {} {} 1 a } finish_test |
Changes to test/e_createtable.test.
︙ | ︙ | |||
1510 1511 1512 1513 1514 1515 1516 | 1 "INSERT INTO t1 VALUES(NULL, 'a')" {t1.a} 2 "INSERT INTO t2 VALUES(NULL, 'b')" {t2.a} 3 "INSERT INTO t3 VALUES('c', 'd', NULL)" {t3.c} 4 "INSERT INTO t3 VALUES('e', NULL, 'f')" {t3.b} 5 "INSERT INTO t3 VALUES(NULL, 'g', 'h')" {t3.a} } | | | | < | 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 | 1 "INSERT INTO t1 VALUES(NULL, 'a')" {t1.a} 2 "INSERT INTO t2 VALUES(NULL, 'b')" {t2.a} 3 "INSERT INTO t3 VALUES('c', 'd', NULL)" {t3.c} 4 "INSERT INTO t3 VALUES('e', NULL, 'f')" {t3.b} 5 "INSERT INTO t3 VALUES(NULL, 'g', 'h')" {t3.a} } # EVIDENCE-OF: R-42511-39459 PRIMARY KEY, UNIQUE and NOT NULL # constraints may be explicitly assigned a default conflict resolution # algorithm by including a conflict-clause in their definitions. # # Conflict clauses: ABORT, ROLLBACK, IGNORE, FAIL, REPLACE # # Test cases 4.15.*, 4.16.* and 4.17.* focus on PRIMARY KEY, NOT NULL # and UNIQUE constraints, respectively. # drop_all_tables |
︙ | ︙ | |||
1628 1629 1630 1631 1632 1633 1634 | " $res do_test e_createtable-4.17.$tn.3 { sqlite3_get_autocommit db } $ac do_execsql_test 4.17.$tn.4 "SELECT * FROM $tbl ORDER BY rowid" $data } catchsql COMMIT | | | | | 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 | " $res do_test e_createtable-4.17.$tn.3 { sqlite3_get_autocommit db } $ac do_execsql_test 4.17.$tn.4 "SELECT * FROM $tbl ORDER BY rowid" $data } catchsql COMMIT # EVIDENCE-OF: R-12645-39772 Or, if a constraint definition does not # include a conflict-clause or it is a CHECK constraint, the default # conflict resolution algorithm is ABORT. # # The first half of the above is tested along with explicit ON # CONFLICT clauses above (specifically, the tests involving t1_xx, t2_xx # and t3_xx). The following just tests that the default conflict # handling for CHECK constraints is ABORT. # do_execsql_test 4.18.1 { |
︙ | ︙ |
Changes to test/e_expr.test.
︙ | ︙ | |||
211 212 213 214 215 216 217 | #------------------------------------------------------------------------- # Check that both = and == are both acceptable as the "equals" operator. # Similarly, either != or <> work as the not-equals operator. # # EVIDENCE-OF: R-03679-60639 Equals can be either = or ==. # | | | 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 | #------------------------------------------------------------------------- # Check that both = and == are both acceptable as the "equals" operator. # Similarly, either != or <> work as the not-equals operator. # # EVIDENCE-OF: R-03679-60639 Equals can be either = or ==. # # EVIDENCE-OF: R-30082-38996 The non-equals operator can be either != or # <>. # foreach {tn literal different} { 1 'helloworld' '12345' 2 22 23 3 'xyz' X'78797A' 4 X'78797A00' 'xyz' |
︙ | ︙ | |||
1888 1889 1890 1891 1892 1893 1894 | do_expr_test e_expr-35.1.5 { (SELECT b FROM t2 UNION SELECT a+1 FROM t2) } null {} do_expr_test e_expr-35.1.6 { (SELECT a FROM t2 UNION SELECT COALESCE(b, 55) FROM t2 ORDER BY 1) } integer 4 | | | | < | 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 | do_expr_test e_expr-35.1.5 { (SELECT b FROM t2 UNION SELECT a+1 FROM t2) } null {} do_expr_test e_expr-35.1.6 { (SELECT a FROM t2 UNION SELECT COALESCE(b, 55) FROM t2 ORDER BY 1) } integer 4 # EVIDENCE-OF: R-22239-33740 A subquery that returns two or more columns # is a row value subquery and can only be used as the operand of a # comparison operator. # # The following block tests that errors are returned in a bunch of cases # where a subquery returns more than one column. # set M {/1 {sub-select returns [23] columns - expected 1}/} foreach {tn sql} { 1 { SELECT (SELECT * FROM t2 UNION SELECT a+1, b+1 FROM t2) } |
︙ | ︙ |
Changes to test/filter1.test.
︙ | ︙ | |||
216 217 218 219 220 221 222 | do_execsql_test 7.1 { SELECT max(a), max(a) FILTER (WHERE b<12345), b FROM t1; } { 444 {} 120000 } | < < | < < < < < < < < < < | 216 217 218 219 220 221 222 223 224 225 | do_execsql_test 7.1 { SELECT max(a), max(a) FILTER (WHERE b<12345), b FROM t1; } { 444 {} 120000 } finish_test |
Changes to test/fkey1.test.
︙ | ︙ | |||
268 269 270 271 272 273 274 | UPDATE sqlite_schema SET name='sqlite_autoindex_sqlite_stat1_1' WHERE name='sqlite_autoindex_sqlite_stat1_2'; PRAGMA writable_schema=RESET; } {} do_catchsql_test 8.3 { REINDEX; } {1 {database disk image is malformed}} | < < < < < < < < < < < | 268 269 270 271 272 273 274 275 | UPDATE sqlite_schema SET name='sqlite_autoindex_sqlite_stat1_1' WHERE name='sqlite_autoindex_sqlite_stat1_2'; PRAGMA writable_schema=RESET; } {} do_catchsql_test 8.3 { REINDEX; } {1 {database disk image is malformed}} finish_test |
Changes to test/fts3join.test.
︙ | ︙ | |||
96 97 98 99 100 101 102 | ) AS rr ON t4.rowid=rr.docid WHERE t4.y = ?; } { QUERY PLAN |--MATERIALIZE rr | `--SCAN ft4 VIRTUAL TABLE INDEX 3: |--SCAN t4 | < | 96 97 98 99 100 101 102 103 104 105 106 | ) AS rr ON t4.rowid=rr.docid WHERE t4.y = ?; } { QUERY PLAN |--MATERIALIZE rr | `--SCAN ft4 VIRTUAL TABLE INDEX 3: |--SCAN t4 `--SEARCH rr USING AUTOMATIC COVERING INDEX (docid=?) LEFT-JOIN } finish_test |
Deleted test/func8.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/fuzzcheck.c.
︙ | ︙ | |||
997 998 999 1000 1001 1002 1003 | } /* ** This function is called to recover data from the database. */ static int recoverDatabase(sqlite3 *db){ int rc; /* Return code from this routine */ | < | < | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 | } /* ** This function is called to recover data from the database. */ static int recoverDatabase(sqlite3 *db){ int rc; /* Return code from this routine */ const char *zLAF = "lost_and_found"; /* Name of "lost_and_found" table */ int bFreelist = 1; /* True to scan the freelist */ int bRowids = 1; /* True to restore ROWID values */ sqlite3_recover *p; /* The recovery object */ p = sqlite3_recover_init_sql(db, "main", recoverSqlCb, 0); sqlite3_recover_config(p, SQLITE_RECOVER_LOST_AND_FOUND, (void*)zLAF); sqlite3_recover_config(p, SQLITE_RECOVER_ROWIDS, (void*)&bRowids); sqlite3_recover_config(p, SQLITE_RECOVER_FREELIST_CORRUPT,(void*)&bFreelist); sqlite3_recover_run(p); if( sqlite3_recover_errcode(p)!=SQLITE_OK ){ const char *zErr = sqlite3_recover_errmsg(p); int errCode = sqlite3_recover_errcode(p); |
︙ | ︙ | |||
1036 1037 1038 1039 1040 1041 1042 | int bCorrupt = 0; while( isspace(zSql[0]&0x7f) ) zSql++; if( zSql[0]==0 ) return SQLITE_OK; if( eVerbosity>=4 ){ printf("RUNNING-SQL: [%s]\n", zSql); fflush(stdout); } | | | 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 | int bCorrupt = 0; while( isspace(zSql[0]&0x7f) ) zSql++; if( zSql[0]==0 ) return SQLITE_OK; if( eVerbosity>=4 ){ printf("RUNNING-SQL: [%s]\n", zSql); fflush(stdout); } (*pBtsFlags) &= ~BTS_BADPRAGMA; rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); if( rc==SQLITE_OK ){ int nRow = 0; while( (rc = sqlite3_step(pStmt))==SQLITE_ROW ){ nRow++; if( eVerbosity>=4 ){ int j; |
︙ | ︙ | |||
1179 1180 1181 1182 1183 1184 1185 | fflush(stdout); } rc = sqlite3_open(0, &cx.db); if( rc ){ sqlite3_free(aDb); return 1; } | < | 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 | fflush(stdout); } rc = sqlite3_open(0, &cx.db); if( rc ){ sqlite3_free(aDb); return 1; } if( bVdbeDebug ){ sqlite3_exec(cx.db, "PRAGMA vdbe_debug=ON", 0, 0, 0); } /* Invoke the progress handler frequently to check to see if we ** are taking too long. The progress handler will return true ** (which will block further processing) if more than giTimeout seconds have |
︙ | ︙ |
Changes to test/fuzzdata8.db.
cannot compute difference between binary files
Changes to test/fuzzinvariants.c.
︙ | ︙ | |||
99 100 101 102 103 104 105 | if( rc!=SQLITE_OK && rc!=SQLITE_RANGE ){ sqlite3_finalize(pTestStmt); return rc; } } if( eVerbosity>=2 ){ char *zSql = sqlite3_expanded_sql(pTestStmt); | | < < < < < < < < > | < | > > | < < < < < < < | < < < | < < | < > | > > > | > > > > > > < < < < < < < < < < < | 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 | if( rc!=SQLITE_OK && rc!=SQLITE_RANGE ){ sqlite3_finalize(pTestStmt); return rc; } } if( eVerbosity>=2 ){ char *zSql = sqlite3_expanded_sql(pTestStmt); printf("invariant-sql #%d:\n%s\n", iCnt, zSql); sqlite3_free(zSql); } while( (rc = sqlite3_step(pTestStmt))==SQLITE_ROW ){ for(i=0; i<nCol; i++){ if( !sameValue(pStmt, i, pTestStmt, i, 0) ) break; } if( i>=nCol ) break; } if( rc==SQLITE_DONE ){ /* No matching output row found */ sqlite3_stmt *pCk = 0; /* This is not a fault if the database file is corrupt, because anything ** can happen with a corrupt database file */ rc = sqlite3_prepare_v2(db, "PRAGMA integrity_check", -1, &pCk, 0); if( rc ){ sqlite3_finalize(pCk); sqlite3_finalize(pTestStmt); return rc; } rc = sqlite3_step(pCk); if( rc!=SQLITE_ROW || sqlite3_column_text(pCk, 0)==0 || strcmp((const char*)sqlite3_column_text(pCk,0),"ok")!=0 ){ *pbCorrupt = 1; sqlite3_finalize(pCk); sqlite3_finalize(pTestStmt); return SQLITE_CORRUPT; } sqlite3_finalize(pCk); if( sqlite3_strlike("%group%by%",sqlite3_sql(pStmt),0)==0 ){ /* ** If there is a GROUP BY clause, it might not cover every term in the ** output. And then non-covered terms can take on a value from any ** row in the result set. This can cause differing answers. */ goto not_a_fault; } if( sqlite3_strlike("%limit%)%order%by%", sqlite3_sql(pTestStmt),0)==0 ){ /* crash-89bd6a6f8c6166e9a4c5f47b3e70b225f69b76c6 ** Original statement is: ** ** SELECT a,b,c* FROM t1 LIMIT 1%5<4 ** ** When running: ** ** SELECT * FROM (...) ORDER BY 1 ** ** A different subset of the rows come out */ goto not_a_fault; } /* The original sameValue() comparison assumed a collating sequence ** of "binary". It can sometimes get an incorrect result for different ** collating sequences. So rerun the test with no assumptions about ** collations. */ rc = sqlite3_prepare_v2(db, "SELECT ?1=?2 OR ?1=?2 COLLATE nocase OR ?1=?2 COLLATE rtrim", -1, &pCk, 0); if( rc==SQLITE_OK ){ sqlite3_reset(pTestStmt); while( (rc = sqlite3_step(pTestStmt))==SQLITE_ROW ){ for(i=0; i<nCol; i++){ if( !sameValue(pStmt, i, pTestStmt, i, pCk) ) break; } if( i>=nCol ){ sqlite3_finalize(pCk); goto not_a_fault; } } } sqlite3_finalize(pCk); /* Invariants do not necessarily work if there are virtual tables ** involved in the query */ rc = sqlite3_prepare_v2(db, "SELECT 1 FROM bytecode(?1) WHERE opcode='VOpen'", -1, &pCk, 0); if( rc==SQLITE_OK ){ sqlite3_bind_pointer(pCk, 1, pStmt, "stmt-pointer", 0); rc = sqlite3_step(pCk); } sqlite3_finalize(pCk); if( rc==SQLITE_DONE ){ reportInvariantFailed(pStmt, pTestStmt, iRow); return SQLITE_INTERNAL; |
︙ | ︙ |
Changes to test/gencol1.test.
︙ | ︙ | |||
611 612 613 614 615 616 617 | CREATE TABLE t0(a PRIMARY KEY,b TEXT AS ('2') UNIQUE); INSERT INTO t0(a) VALUES(2); SELECT * FROM t0 AS x JOIN t0 AS y WHERE x.b='2' AND (y.a=2 OR (x.b LIKE '2*' AND y.a=x.b)); } {2 2 2 2} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 611 612 613 614 615 616 617 618 | CREATE TABLE t0(a PRIMARY KEY,b TEXT AS ('2') UNIQUE); INSERT INTO t0(a) VALUES(2); SELECT * FROM t0 AS x JOIN t0 AS y WHERE x.b='2' AND (y.a=2 OR (x.b LIKE '2*' AND y.a=x.b)); } {2 2 2 2} finish_test |
Changes to test/in.test.
︙ | ︙ | |||
802 803 804 805 806 807 808 | # reset_db do_execsql_test in-21.1 { CREATE TABLE t0(c0); SELECT COUNT(*) FROM t0 ORDER BY (t0.c0 IN ()); } {0} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 802 803 804 805 806 807 808 809 810 | # reset_db do_execsql_test in-21.1 { CREATE TABLE t0(c0); SELECT COUNT(*) FROM t0 ORDER BY (t0.c0 IN ()); } {0} finish_test |
Changes to test/indexexpr1.test.
︙ | ︙ | |||
561 562 563 564 565 566 567 | SUM(1) AS t1, SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2, SUM(c) AS t3, SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4 FROM t1; } {/.*SCAN t1 USING INDEX t1x.*/} | < < < < < < < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 561 562 563 564 565 566 567 568 569 570 | SUM(1) AS t1, SUM(CASE WHEN b->>'x'=1 THEN 1 END) AS t2, SUM(c) AS t3, SUM(CASE WHEN b->>'x'=1 THEN c END) AS t4 FROM t1; } {/.*SCAN t1 USING INDEX t1x.*/} finish_test |
Changes to test/indexexpr2.test.
︙ | ︙ | |||
368 369 370 371 372 373 374 | " {1 2 {} {} 3 4 {} {}} do_execsql_test 8.5.$tn.2 " SELECT ($expr) IS TRUE FROM t1 LEFT JOIN t2 " {1 1} } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 368 369 370 371 372 373 374 375 | " {1 2 {} {} 3 4 {} {}} do_execsql_test 8.5.$tn.2 " SELECT ($expr) IS TRUE FROM t1 LEFT JOIN t2 " {1 1} } finish_test |
Changes to test/join.test.
︙ | ︙ | |||
1034 1035 1036 1037 1038 1039 1040 | CREATE TABLE t0(a, b); CREATE INDEX t0a ON t0(a); INSERT INTO t0 VALUES(10,10),(10,11),(10,12); SELECT DISTINCT c FROM t0 LEFT JOIN (SELECT a+1 AS c FROM t0) ORDER BY c ; } {11} # 2019-12-22 ticket 7929c1efb2d67e98 | < < < < | | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | CREATE TABLE t0(a, b); CREATE INDEX t0a ON t0(a); INSERT INTO t0 VALUES(10,10),(10,11),(10,12); SELECT DISTINCT c FROM t0 LEFT JOIN (SELECT a+1 AS c FROM t0) ORDER BY c ; } {11} # 2019-12-22 ticket 7929c1efb2d67e98 # reset_db ifcapable vtab { do_execsql_test join-23.10 { CREATE TABLE t0(c0); INSERT INTO t0(c0) VALUES(123); CREATE VIEW v0(c0) AS SELECT 0 GROUP BY 1; SELECT t0.c0, v0.c0, vt0.name FROM v0, t0 LEFT JOIN pragma_table_info('t0') AS vt0 ON vt0.name LIKE 'c0' WHERE v0.c0 == 0; } {123 0 c0} } #------------------------------------------------------------------------- reset_db do_execsql_test join-24.1 { CREATE TABLE t1(a PRIMARY KEY, x); CREATE TABLE t2(b INT); |
︙ | ︙ | |||
1241 1242 1243 1244 1245 1246 1247 | # QUERY PLAN # |--MATERIALIZE t3 # | |--SCAN t1 # | `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN # |--SCAN t4 # `--SEARCH t3 USING AUTOMATIC COVERING INDEX (a=?) | < < < < < < < < < < < < < < < < < < | 1203 1204 1205 1206 1207 1208 1209 1210 | # QUERY PLAN # |--MATERIALIZE t3 # | |--SCAN t1 # | `--SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?) LEFT-JOIN # |--SCAN t4 # `--SEARCH t3 USING AUTOMATIC COVERING INDEX (a=?) finish_test |
Changes to test/join2.test.
︙ | ︙ | |||
350 351 352 353 354 355 356 | SELECT ccc, ccc IS NULL AS ddd FROM t1 LEFT JOIN v2; } {{} 1} optimization_control db query-flattener 0 do_execsql_test 9.11 { SELECT ccc, ccc IS NULL AS ddd FROM t1 LEFT JOIN v2; } {{} 1} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 350 351 352 353 354 355 356 357 358 | SELECT ccc, ccc IS NULL AS ddd FROM t1 LEFT JOIN v2; } {{} 1} optimization_control db query-flattener 0 do_execsql_test 9.11 { SELECT ccc, ccc IS NULL AS ddd FROM t1 LEFT JOIN v2; } {{} 1} finish_test |
Changes to test/join8.test.
︙ | ︙ | |||
155 156 157 158 159 160 161 | CREATE TABLE t2(c, d); INSERT INTO t2(c,d) SELECT x, x FROM t1; CREATE INDEX t2dc ON t2(d, c); SELECT (SELECT c FROM sqlite_temp_schema FULL JOIN t2 ON d IN (1,2,3) ORDER BY d) AS x FROM t1; } {0 {- -}} # 2022-04-29 dbsqlfuzz 19f1102a70cf966ab249de56d944fc20dbebcfcf | < | 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | CREATE TABLE t2(c, d); INSERT INTO t2(c,d) SELECT x, x FROM t1; CREATE INDEX t2dc ON t2(d, c); SELECT (SELECT c FROM sqlite_temp_schema FULL JOIN t2 ON d IN (1,2,3) ORDER BY d) AS x FROM t1; } {0 {- -}} # 2022-04-29 dbsqlfuzz 19f1102a70cf966ab249de56d944fc20dbebcfcf # reset_db do_execsql_test join8-6000 { CREATE TABLE t1(a INTEGER PRIMARY KEY, b TEXT, c TEXT, d REAL); INSERT INTO t1 VALUES(1,'A','aa',2.5); SELECT * FROM t1 AS t2 NATURAL RIGHT JOIN t1 AS t3 WHERE (a,b) IN (SELECT rowid, b FROM t1); |
︙ | ︙ | |||
178 179 180 181 182 183 184 | do_execsql_test join8-6020 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INTEGER PRIMARY KEY,b); INSERT INTO t1 VALUES(0,NULL),(1,2); SELECT value, t1.* FROM json_each('17') NATURAL RIGHT JOIN t1 WHERE (a,b) IN (SELECT rowid, b FROM t1); } {17 1 2} | < < < < < < < < < < | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | do_execsql_test join8-6020 { DROP TABLE IF EXISTS t1; CREATE TABLE t1(a INTEGER PRIMARY KEY,b); INSERT INTO t1 VALUES(0,NULL),(1,2); SELECT value, t1.* FROM json_each('17') NATURAL RIGHT JOIN t1 WHERE (a,b) IN (SELECT rowid, b FROM t1); } {17 1 2} # Bloom filter usage by RIGHT and FULL JOIN # reset_db do_execsql_test join8-7000 { CREATE TABLE t1(a INT, b INT, c INT, d INT); WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<10) |
︙ | ︙ |
Changes to test/joinH.test.
︙ | ︙ | |||
85 86 87 88 89 90 91 | CREATE INDEX i1 ON t1( (d IS NULL), d ); } do_execsql_test 4.4 { SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33); } {1} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 85 86 87 88 89 90 91 92 93 | CREATE INDEX i1 ON t1( (d IS NULL), d ); } do_execsql_test 4.4 { SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33); } {1} finish_test |
Deleted test/json/README.md.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted test/json/json-generator.tcl.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted test/json/json-q1.txt.
|
| < < < < |
Deleted test/json/json-speed-check.sh.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/json101.test.
︙ | ︙ | |||
306 307 308 309 310 311 312 | WHERE jx.value<>jx.atom AND type NOT IN ('array','object'); } {} do_execsql_test json-6.1 { SELECT json_valid('{"a":55,"b":72,}'); } {0} do_execsql_test json-6.2 { | < < < < < < < < < < < < < < < | | | < < < < < < | 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 | WHERE jx.value<>jx.atom AND type NOT IN ('array','object'); } {} do_execsql_test json-6.1 { SELECT json_valid('{"a":55,"b":72,}'); } {0} do_execsql_test json-6.2 { SELECT json_valid('{"a":55,"b":72}'); } {1} do_execsql_test json-6.3 { SELECT json_valid('["a",55,"b",72,]'); } {0} do_execsql_test json-6.4 { SELECT json_valid('["a",55,"b",72]'); } {1} # White-space tests. Note that form-feed is not white-space in JSON. # ticket [57eec374ae1d0a1d4a23077a95f4e173fe269113] # foreach {tn isvalid ws} { |
︙ | ︙ | |||
901 902 903 904 905 906 907 908 | BEGIN; INSERT INTO t1 VALUES(0), (json('not-valid-json')); } {1 {malformed JSON}} do_execsql_test json-19.3 { COMMIT; SELECT * FROM t1; } {} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 880 881 882 883 884 885 886 887 888 | BEGIN; INSERT INTO t1 VALUES(0), (json('not-valid-json')); } {1 {malformed JSON}} do_execsql_test json-19.3 { COMMIT; SELECT * FROM t1; } {} finish_test |
Changes to test/json102.test.
︙ | ︙ | |||
297 298 299 300 301 302 303 | # 2017-04-08 ticket b93be8729a895a528e2849fca99f7 # JSON extension accepts invalid numeric values # # JSON does not allow leading zeros. But the JSON extension was # allowing them. The following tests verify that the problem is now # fixed. # | < | | | | | | | | | | < < < < < < | | < < | 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 | # 2017-04-08 ticket b93be8729a895a528e2849fca99f7 # JSON extension accepts invalid numeric values # # JSON does not allow leading zeros. But the JSON extension was # allowing them. The following tests verify that the problem is now # fixed. # do_execsql_test json102-1401 { SELECT json_valid('{"x":01}') } 0 do_execsql_test json102-1402 { SELECT json_valid('{"x":-01}') } 0 do_execsql_test json102-1403 { SELECT json_valid('{"x":0}') } 1 do_execsql_test json102-1404 { SELECT json_valid('{"x":-0}') } 1 do_execsql_test json102-1405 { SELECT json_valid('{"x":0.1}') } 1 do_execsql_test json102-1406 { SELECT json_valid('{"x":-0.1}') } 1 do_execsql_test json102-1407 { SELECT json_valid('{"x":0.0000}') } 1 do_execsql_test json102-1408 { SELECT json_valid('{"x":-0.0000}') } 1 do_execsql_test json102-1409 { SELECT json_valid('{"x":01.5}') } 0 do_execsql_test json102-1410 { SELECT json_valid('{"x":-01.5}') } 0 do_execsql_test json102-1411 { SELECT json_valid('{"x":00}') } 0 do_execsql_test json102-1412 { SELECT json_valid('{"x":-00}') } 0 #------------------------------------------------------------------------ # 2017-04-10 ticket 6c9b5514077fed34551f98e64c09a10dc2fc8e16 # JSON extension accepts strings containing control characters. # # The JSON spec requires that all control characters be escaped. # |
︙ | ︙ |
Changes to test/json104.test.
︙ | ︙ | |||
24 25 26 27 28 29 30 | "f": "g" } }','{ "a":"z", "c": { "f": null } | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | "f": "g" } }','{ "a":"z", "c": { "f": null } }'); } {{{"a":"z","c":{"d":"e"}}}} # This is the example from pages 4 and 5 of RFC-7396 do_execsql_test json104-110 { SELECT json_patch('{ |
︙ | ︙ |
Deleted test/json501.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Deleted test/json502.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/misc1.test.
︙ | ︙ | |||
588 589 590 591 592 593 594 | } {2 3} } do_test misc1-18.1 { set n [sqlite3_sleep 100] expr {$n>=100} } {1} | < < < | 588 589 590 591 592 593 594 595 596 597 598 599 600 601 | } {2 3} } do_test misc1-18.1 { set n [sqlite3_sleep 100] expr {$n>=100} } {1} # 2014-01-10: In a CREATE TABLE AS, if one or more of the column names # are an empty string, that is still OK. # do_execsql_test misc1-19.1 { CREATE TABLE t19 AS SELECT 1, 2 AS '', 3; SELECT * FROM t19; |
︙ | ︙ |
Changes to test/notnull2.test.
︙ | ︙ | |||
24 25 26 27 28 29 30 31 32 33 34 35 36 37 | WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 ) INSERT INTO t1 SELECT i, i FROM x; INSERT INTO t2 SELECT * FROM t1; } do_vmstep_test 1.1.1 { SELECT * FROM t1 LEFT JOIN t2 WHERE a=c AND d IS NULL; } 100 {} do_vmstep_test 1.1.2 { SELECT * FROM t1 LEFT JOIN t2 WHERE a=c AND c IS NULL; } +1000 {} | > > > > > > > > > > > > > > > > > > | 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 | WITH x(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM x WHERE i<1000 ) INSERT INTO t1 SELECT i, i FROM x; INSERT INTO t2 SELECT * FROM t1; } proc do_vmstep_test {tn sql nstep {res {}}} { uplevel [list do_execsql_test $tn.0 $sql $res] set vmstep [db status vmstep] if {[string range $nstep 0 0]=="+"} { set body "if {$vmstep<$nstep} { error \"got $vmstep, expected more than [string range $nstep 1 end]\" }" } else { set body "if {$vmstep>$nstep} { error \"got $vmstep, expected less than $nstep\" }" } # set name "$tn.vmstep=$vmstep,expect=$nstep" set name "$tn.1" uplevel [list do_test $name $body {}] } do_vmstep_test 1.1.1 { SELECT * FROM t1 LEFT JOIN t2 WHERE a=c AND d IS NULL; } 100 {} do_vmstep_test 1.1.2 { SELECT * FROM t1 LEFT JOIN t2 WHERE a=c AND c IS NULL; } +1000 {} |
︙ | ︙ |
Changes to test/pragma.test.
︙ | ︙ | |||
429 430 431 432 433 434 435 | } {ok} do_test pragma-3.9a { execsql { ATTACH 'testerr.db' AS t2; PRAGMA integrity_check } } {{*** in database t2 *** | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 | } {ok} do_test pragma-3.9a { execsql { ATTACH 'testerr.db' AS t2; PRAGMA integrity_check } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}} do_execsql_test pragma-3.9b { PRAGMA t2.integrity_check=t2; } {{row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}} do_execsql_test pragma-3.9c { PRAGMA t2.integrity_check=sqlite_schema; } {ok} do_test pragma-3.10 { execsql { PRAGMA integrity_check=1 } } {{*** in database t2 *** Page 4 is never used}} do_test pragma-3.11 { execsql { PRAGMA integrity_check=5 } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2}} do_test pragma-3.12 { execsql { PRAGMA integrity_check=4 } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2}} do_test pragma-3.13 { execsql { PRAGMA integrity_check=3 } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used}} do_test pragma-3.14 { execsql { PRAGMA integrity_check(2) } } {{*** in database t2 *** Page 4 is never used Page 5 is never used}} do_test pragma-3.15 { execsql { ATTACH 'testerr.db' AS t3; PRAGMA integrity_check } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2}} do_test pragma-3.16 { execsql { PRAGMA integrity_check(10) } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2}} do_test pragma-3.17 { execsql { PRAGMA integrity_check=8 } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2} {row 2 missing from index i2} {wrong # of entries in index i2} {*** in database t3 *** Page 4 is never used Page 5 is never used}} do_test pragma-3.18 { execsql { PRAGMA integrity_check=4 } } {{*** in database t2 *** Page 4 is never used Page 5 is never used Page 6 is never used} {row 1 missing from index i2}} } do_test pragma-3.19 { catch {db close} forcedelete test.db test.db-journal sqlite3 db test.db db eval {PRAGMA integrity_check} } {ok} |
︙ | ︙ | |||
2056 2057 2058 2059 2060 2061 2062 | SELECT * FROM t1; } {1 {database disk image is malformed}} do_catchsql_test 24.2 { PRAGMA integrity_check; } {0 {{database disk image is malformed}}} } database_never_corrupt | < < < < < < < < < < < < < | 2056 2057 2058 2059 2060 2061 2062 2063 | SELECT * FROM t1; } {1 {database disk image is malformed}} do_catchsql_test 24.2 { PRAGMA integrity_check; } {0 {{database disk image is malformed}}} } database_never_corrupt finish_test |
Changes to test/printf.test.
︙ | ︙ | |||
3782 3783 3784 3785 3786 3787 3788 | # 2020-05-23 # ticket 23439ea582241138 # do_execsql_test printf-16.1 { SELECT printf('%.*g',2147483647,0.01); } {0.01} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 3782 3783 3784 3785 3786 3787 3788 3789 | # 2020-05-23 # ticket 23439ea582241138 # do_execsql_test printf-16.1 { SELECT printf('%.*g',2147483647,0.01); } {0.01} finish_test |
Changes to test/pushdown.test.
︙ | ︙ | |||
118 119 120 121 122 123 124 | do_execsql_test 3.4 { SELECT a, quote(b), cd FROM ( SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1 ) WHERE a=2 AND b=0 AND cd=0; } { 2 0 0 } | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 118 119 120 121 122 123 124 125 126 | do_execsql_test 3.4 { SELECT a, quote(b), cd FROM ( SELECT v1.a, v1.b, t0.c0 AS cd FROM t0 LEFT JOIN v0 ON v0.c0!=0, v1 ) WHERE a=2 AND b=0 AND cd=0; } { 2 0 0 } finish_test |
Changes to test/returning1.test.
︙ | ︙ | |||
208 209 210 211 212 213 214 | INSERT INTO log VALUES('insert', new.rowid, new.a, new.b); END; CREATE TRIGGER tr2 INSTEAD OF UPDATE ON t1 BEGIN INSERT INTO log VALUES('update', new.rowid, new.a, new.b); END; } | | | | | | 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | INSERT INTO log VALUES('insert', new.rowid, new.a, new.b); END; CREATE TRIGGER tr2 INSTEAD OF UPDATE ON t1 BEGIN INSERT INTO log VALUES('update', new.rowid, new.a, new.b); END; } do_catchsql_test 10.3 { INSERT INTO t1(a, b) VALUES(1234, 5678) RETURNING rowid; } {1 {no such column: rowid}} do_catchsql_test 10.3 { UPDATE t1 SET a='z' WHERE b='y' RETURNING rowid; } {1 {no such column: rowid}} do_execsql_test 10.4 { SELECT * FROM log; } {} # 2021-04-27 dbsqlfuzz 78b9400770ef8cc7d9427dfba26f4fcf46ea7dc2 # Returning clauses on TEMP tables with triggers. |
︙ | ︙ | |||
404 405 406 407 408 409 410 | reset_db do_execsql_test 17.0 { CREATE TABLE bug(id INTEGER PRIMARY KEY NOT NULL, x); INSERT INTO bug(id,x) VALUES(20, NULL); UPDATE bug SET x=NULL WHERE id = 20 RETURNING quote(x), x IS NULL; } {NULL 1} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 404 405 406 407 408 409 410 411 | reset_db do_execsql_test 17.0 { CREATE TABLE bug(id INTEGER PRIMARY KEY NOT NULL, x); INSERT INTO bug(id,x) VALUES(20, NULL); UPDATE bug SET x=NULL WHERE id = 20 RETURNING quote(x), x IS NULL; } {NULL 1} finish_test |
Changes to test/rowvalue9.test.
︙ | ︙ | |||
304 305 306 307 308 309 310 | CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b); } do_catchsql_test 8.2 { SELECT a FROM t1 NATURAL JOIN t1 WHERE (a,b)> (SELECT 2 IN (SELECT 2,2), 2); } {1 {sub-select returns 2 columns - expected 1}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 304 305 306 307 308 309 310 311 312 313 314 | CREATE INDEX t1x1 ON t1(a,b,a,a,a,a,a,a,a,a,a,b); } do_catchsql_test 8.2 { SELECT a FROM t1 NATURAL JOIN t1 WHERE (a,b)> (SELECT 2 IN (SELECT 2,2), 2); } {1 {sub-select returns 2 columns - expected 1}} finish_test |
Changes to test/scanstatus.test.
︙ | ︙ | |||
41 42 43 44 45 46 47 | } incr idx } uplevel [list do_test $tn [list set {} $ret] [list {*}$res]] } | | | < < < < < < < < | 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | } incr idx } uplevel [list do_test $tn [list set {} $ret] [list {*}$res]] } do_execsql_test 1.1 { SELECT count(*) FROM t1, t2; } 6 do_scanstatus_test 1.2 { nLoop 1 nVisit 2 nEst 1048576.0 zName t1 zExplain {SCAN t1} nLoop 2 nVisit 6 nEst 1048576.0 zName t2 zExplain {SCAN t2} } do_execsql_test 1.3 { ANALYZE; SELECT count(*) FROM t1, t2; } 6 do_scanstatus_test 1.4 { nLoop 1 nVisit 2 nEst 2.0 zName t1 zExplain {SCAN t1} nLoop 2 nVisit 6 nEst 3.0 zName t2 zExplain {SCAN t2} |
︙ | ︙ | |||
98 99 100 101 102 103 104 | nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN t1} } #------------------------------------------------------------------------- # Try a few different types of scans. # reset_db | < | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | nLoop 0 nVisit 0 nEst 2.0 zName t1 zExplain {SCAN t1} } #------------------------------------------------------------------------- # Try a few different types of scans. # reset_db do_execsql_test 2.1 { CREATE TABLE x1(i INTEGER PRIMARY KEY, j); INSERT INTO x1 VALUES(1, 'one'); INSERT INTO x1 VALUES(2, 'two'); INSERT INTO x1 VALUES(3, 'three'); INSERT INTO x1 VALUES(4, 'four'); CREATE INDEX x1j ON x1(j); |
︙ | ︙ | |||
282 283 284 285 286 287 288 | nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN c1} } #------------------------------------------------------------------------- # Further tests of different scan types. # reset_db | < | 273 274 275 276 277 278 279 280 281 282 283 284 285 286 | nLoop 1 nVisit 3 nEst 262144.0 zName c1 zExplain {SCAN c1} } #------------------------------------------------------------------------- # Further tests of different scan types. # reset_db proc tochar {i} { set alphabet {a b c d e f g h i j k l m n o p q r s t u v w x y z} return [lindex $alphabet [expr $i % [llength $alphabet]]] } db func tochar tochar do_execsql_test 5.0 { CREATE TABLE t1(a PRIMARY KEY, b, c); |
︙ | ︙ | |||
371 372 373 374 375 376 377 | } do_eqp_test 5.5.1 { SELECT count(*) FROM t1, t3 WHERE y = c; } { QUERY PLAN |--SCAN t3 | < | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 | } do_eqp_test 5.5.1 { SELECT count(*) FROM t1, t3 WHERE y = c; } { QUERY PLAN |--SCAN t3 `--SEARCH t1 USING AUTOMATIC COVERING INDEX (c=?) } do_execsql_test 5.5.2 { SELECT count(*) FROM t1, t3 WHERE y = c; } {200} do_scanstatus_test 5.5.3 { nLoop 1 nVisit 501 nEst 480.0 zName t3 zExplain {SCAN t3} |
︙ | ︙ |
Changes to test/scanstatus2.test.
︙ | ︙ | |||
15 16 17 18 19 20 21 | set testprefix scanstatus2 ifcapable !scanstatus { finish_test return } | < < | 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | set testprefix scanstatus2 ifcapable !scanstatus { finish_test return } do_execsql_test 1.0 { CREATE TABLE t1(a, b); CREATE TABLE t2(x, y); INSERT INTO t1 VALUES(1, 2); INSERT INTO t1 VALUES(3, 4); INSERT INTO t2 VALUES('a', 'b'); INSERT INTO t2 VALUES('c', 'd'); |
︙ | ︙ | |||
139 140 141 142 143 144 145 | --SCAN t1 (nCycle=nnn) --USE TEMP B-TREE FOR ORDER BY (nCycle=nnn) } #------------------------------------------------------------------------- ifcapable fts5 { reset_db | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 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 | --SCAN t1 (nCycle=nnn) --USE TEMP B-TREE FOR ORDER BY (nCycle=nnn) } #------------------------------------------------------------------------- ifcapable fts5 { reset_db do_execsql_test 2.0 { CREATE VIRTUAL TABLE ft USING fts5(a); INSERT INTO ft VALUES('abc'); INSERT INTO ft VALUES('def'); INSERT INTO ft VALUES('ghi'); } do_graph_test 2.1 { SELECT * FROM ft('def') } { QUERY (nCycle=nnn) --SCAN ft VIRTUAL TABLE INDEX 0:M1 (nCycle=nnn) } } #------------------------------------------------------------------------- reset_db do_execsql_test 3.0 { CREATE TABLE x1(a, b); CREATE TABLE x2(c, d); WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<1000) INSERT INTO x1 SELECT i, i FROM s; INSERT INTO x2 SELECT a, b FROM x1; } do_graph_test 2.1 { SELECT * FROM x1, x2 WHERE c=+a; } { QUERY (nCycle=nnn) --SCAN x1 (nCycle=nnn) --CREATE AUTOMATIC INDEX ON x2(c, d) (nCycle=nnn) --SEARCH x2 USING AUTOMATIC COVERING INDEX (c=?) (nCycle=nnn) } #------------------------------------------------------------------------- reset_db do_execsql_test 4.0 { CREATE TABLE rt1 (id INTEGER PRIMARY KEY, x1, x2); CREATE TABLE rt2 (id, x1, x2); } do_graph_test 4.1 { SELECT * FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=rt1.x1; } { QUERY (nCycle=nnn) --SCAN rt1 (nCycle=nnn) --CREATE AUTOMATIC INDEX ON rt2(x1, id, x2) (nCycle=nnn) --SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn) } do_graph_test 4.2 { SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=rt1.x1; } { QUERY (nCycle=nnn) --SCAN rt1 (nCycle=nnn) --CREATE AUTOMATIC INDEX ON rt2(x1, id) (nCycle=nnn) --SEARCH rt2 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn) } do_graph_test 4.3 { SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND (rt2.x1+1)=(rt1.x1+1); } { QUERY (nCycle=nnn) --SCAN rt1 (nCycle=nnn) --SCAN rt2 (nCycle=nnn) } do_graph_test 4.4 { SELECT rt2.id FROM rt1, rt2 WHERE rt1.id%2 AND rt2.x1=(rt1.x1+1) AND rt2.id>5; } { QUERY (nCycle=nnn) --SCAN rt1 (nCycle=nnn) --CREATE AUTOMATIC INDEX ON rt2(x1, id) WHERE <expr> (nCycle=nnn) --SEARCH rt2 USING AUTOMATIC PARTIAL COVERING INDEX (x1=?) (nCycle=nnn) } do_graph_test 4.5 { SELECT v1.cnt FROM rt1, ( SELECT count(*) AS cnt, rt2.x1 AS x1 FROM rt2 GROUP BY x1 ) AS v1 WHERE rt1.x1=v1.x1 } { QUERY (nCycle=nnn) --CO-ROUTINE v1 ----SCAN rt2 (nCycle=nnn) ----USE TEMP B-TREE FOR GROUP BY --SCAN rt1 (nCycle=nnn) --CREATE AUTOMATIC INDEX ON v1(x1, cnt) (nCycle=nnn) --SEARCH v1 USING AUTOMATIC COVERING INDEX (x1=?) (nCycle=nnn) } finish_test |
Changes to test/seekscan1.test.
︙ | ︙ | |||
20 21 22 23 24 25 26 | WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1997) INSERT INTO t1(a,b,c) SELECT printf('xyz%d',x/10),x/6,x FROM c; INSERT INTO t1 VALUES('abc',234,6); INSERT INTO t1 VALUES('abc',345,7); ANALYZE; } | < | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<1997) INSERT INTO t1(a,b,c) SELECT printf('xyz%d',x/10),x/6,x FROM c; INSERT INTO t1 VALUES('abc',234,6); INSERT INTO t1 VALUES('abc',345,7); ANALYZE; } do_execsql_test 1.1 { SELECT a,b,c FROM t1 WHERE b IN (234, 345) AND c BETWEEN 6 AND 6.5 AND a='abc' ORDER BY a, b; } { abc 234 6 } |
︙ | ︙ | |||
56 57 58 59 60 61 62 | WHERE b IN (234, 345) AND c<=7 AND a='abc' ORDER BY a, b; } { abc 234 6 abc 345 7 } | < < | < < | 55 56 57 58 59 60 61 62 63 | WHERE b IN (234, 345) AND c<=7 AND a='abc' ORDER BY a, b; } { abc 234 6 abc 345 7 } finish_test |
Changes to test/selectC.test.
︙ | ︙ | |||
226 227 228 229 230 231 232 | insert into t_distinct_bug values ('1', '3', 'f'); } {} do_execsql_test selectC-4.2 { select a from (select distinct a, b from t_distinct_bug) } {1 1 1} | < < < < < | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 | insert into t_distinct_bug values ('1', '3', 'f'); } {} do_execsql_test selectC-4.2 { select a from (select distinct a, b from t_distinct_bug) } {1 1 1} do_execsql_test selectC-4.3 { select a, udf() from (select distinct a, b from t_distinct_bug) } {1 1 1 2 1 3} #------------------------------------------------------------------------- # Test that the problem in ticket #190c2507 has been fixed. # |
︙ | ︙ |
Deleted test/selectH.test.
|
| < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < |
Changes to test/shell1.test.
︙ | ︙ | |||
171 172 173 174 175 176 177 | } {1 1} # -version show SQLite version do_test shell1-1.16.1 { set x [catchcmd "-version test.db" ""] } {/3.[0-9.]+ 20\d\d-[01]\d-\d\d \d\d:\d\d:\d\d [0-9a-f]+/} | < < < < < < < < < < | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | } {1 1} # -version show SQLite version do_test shell1-1.16.1 { set x [catchcmd "-version test.db" ""] } {/3.[0-9.]+ 20\d\d-[01]\d-\d\d \d\d:\d\d:\d\d [0-9a-f]+/} #---------------------------------------------------------------------------- # Test cases shell1-2.*: Basic "dot" command token parsing. # # check first token handling do_test shell1-2.1.1 { catchcmd "test.db" ".foo" |
︙ | ︙ | |||
250 251 252 253 254 255 256 | do_test shell1-2.4.2 { catchcmd "test.db" ".mode csv" } {0 {}} do_test shell1-2.4.2 { catchcmd "test.db" ".mode \"csv\"" } {0 {}} | < < < < < | 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | do_test shell1-2.4.2 { catchcmd "test.db" ".mode csv" } {0 {}} do_test shell1-2.4.2 { catchcmd "test.db" ".mode \"csv\"" } {0 {}} #---------------------------------------------------------------------------- # Test cases shell1-3.*: Basic test that "dot" command can be called. # # .backup ?DB? FILE Backup DB (default "main") to FILE do_test shell1-3.1.1 { |
︙ | ︙ |
Changes to test/shell2.test.
︙ | ︙ | |||
212 213 214 215 216 217 218 | .clone clone.db .open clone.db SELECT max(seq) FROM sqlite_sequence;}]] } {0 {t... done done 2}} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 212 213 214 215 216 217 218 219 220 | .clone clone.db .open clone.db SELECT max(seq) FROM sqlite_sequence;}]] } {0 {t... done done 2}} finish_test |
Changes to test/skipscan1.test.
︙ | ︙ | |||
415 416 417 418 419 420 421 | WHERE a = b AND a = 3 AND b IN (1,3,2,4) AND b >= 0 AND a <= 10; } {3} | < < < < < < < < < < | 415 416 417 418 419 420 421 422 | WHERE a = b AND a = 3 AND b IN (1,3,2,4) AND b >= 0 AND a <= 10; } {3} finish_test |
Changes to test/speedtest1.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | "Options:\n" " --autovacuum Enable AUTOVACUUM mode\n" " --big-transactions Add BEGIN/END around all large tests\n" " --cachesize N Set PRAGMA cache_size=N. Note: N is pages, not bytes\n" " --checkpoint Run PRAGMA wal_checkpoint after each test case\n" " --exclusive Enable locking_mode=EXCLUSIVE\n" " --explain Like --sqlonly but with added EXPLAIN keywords\n" | < | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | "Options:\n" " --autovacuum Enable AUTOVACUUM mode\n" " --big-transactions Add BEGIN/END around all large tests\n" " --cachesize N Set PRAGMA cache_size=N. Note: N is pages, not bytes\n" " --checkpoint Run PRAGMA wal_checkpoint after each test case\n" " --exclusive Enable locking_mode=EXCLUSIVE\n" " --explain Like --sqlonly but with added EXPLAIN keywords\n" " --heap SZ MIN Memory allocator uses SZ bytes & min allocation MIN\n" " --incrvacuum Enable incremenatal vacuum mode\n" " --journal M Set the journal_mode to M\n" " --key KEY Set the encryption key to KEY\n" " --lookaside N SZ Configure lookaside for N slots of SZ bytes each\n" " --memdb Use an in-memory database\n" " --mmap SZ MMAP the first SZ bytes of the database file\n" |
︙ | ︙ | |||
36 37 38 39 40 41 42 | " --serialized Set serialized threading mode\n" " --singlethread Set single-threaded mode - disables all mutexing\n" " --sqlonly No-op. Only show the SQL that would have been run.\n" " --shrink-memory Invoke sqlite3_db_release_memory() frequently.\n" " --size N Relative test size. Default=100\n" " --strict Use STRICT table where appropriate\n" " --stats Show statistics at the end\n" | < | 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | " --serialized Set serialized threading mode\n" " --singlethread Set single-threaded mode - disables all mutexing\n" " --sqlonly No-op. Only show the SQL that would have been run.\n" " --shrink-memory Invoke sqlite3_db_release_memory() frequently.\n" " --size N Relative test size. Default=100\n" " --strict Use STRICT table where appropriate\n" " --stats Show statistics at the end\n" " --temp N N from 0 to 9. 0: no temp table. 9: all temp tables\n" " --testset T Run test-set T (main, cte, rtree, orm, fp, debug)\n" " --trace Turn on SQL tracing\n" " --threads N Use up to N threads for sorting\n" " --utf16be Set text encoding to UTF-16BE\n" " --utf16le Set text encoding to UTF-16LE\n" " --verify Run additional verification steps\n" |
︙ | ︙ | |||
98 99 100 101 102 103 104 | int bVerify; /* Try to verify that results are correct */ int bMemShrink; /* Call sqlite3_db_release_memory() often */ int eTemp; /* 0: no TEMP. 9: always TEMP. */ int szTest; /* Scale factor for test iterations */ int nRepeat; /* Repeat selects this many times */ int doCheckpoint; /* Run PRAGMA wal_checkpoint after each trans */ int nReserve; /* Reserve bytes */ | < | 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | int bVerify; /* Try to verify that results are correct */ int bMemShrink; /* Call sqlite3_db_release_memory() often */ int eTemp; /* 0: no TEMP. 9: always TEMP. */ int szTest; /* Scale factor for test iterations */ int nRepeat; /* Repeat selects this many times */ int doCheckpoint; /* Run PRAGMA wal_checkpoint after each trans */ int nReserve; /* Reserve bytes */ int doBigTransactions; /* Enable transactions on tests 410 and 510 */ const char *zWR; /* Might be WITHOUT ROWID */ const char *zNN; /* Might be NOT NULL */ const char *zPK; /* Might be UNIQUE or PRIMARY KEY */ unsigned int x, y; /* Pseudo-random number generator state */ u64 nResByte; /* Total number of result bytes */ int nResult; /* Size of the current result */ |
︙ | ︙ | |||
2200 2201 2202 2203 2204 2205 2206 | printf("-- Compile option: %s\n", azVal[0]); return SQLITE_OK; } int main(int argc, char **argv){ int doAutovac = 0; /* True for --autovacuum */ int cacheSize = 0; /* Desired cache size. 0 means default */ int doExclusive = 0; /* True for --exclusive */ | < | 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 | printf("-- Compile option: %s\n", azVal[0]); return SQLITE_OK; } int main(int argc, char **argv){ int doAutovac = 0; /* True for --autovacuum */ int cacheSize = 0; /* Desired cache size. 0 means default */ int doExclusive = 0; /* True for --exclusive */ int nHeap = 0, mnHeap = 0; /* Heap size from --heap */ int doIncrvac = 0; /* True for --incrvacuum */ const char *zJMode = 0; /* Journal mode */ const char *zKey = 0; /* Encryption key */ int nLook = -1, szLook = 0; /* --lookaside configuration */ int noSync = 0; /* True for --nosync */ int pageSize = 0; /* Desired page size. 0 means default */ |
︙ | ︙ | |||
2265 2266 2267 2268 2269 2270 2271 | }else if( strcmp(z,"big-transactions")==0 ){ g.doBigTransactions = 1; }else if( strcmp(z,"cachesize")==0 ){ ARGC_VALUE_CHECK(1); cacheSize = integerValue(argv[++i]); }else if( strcmp(z,"exclusive")==0 ){ doExclusive = 1; | < < | 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 | }else if( strcmp(z,"big-transactions")==0 ){ g.doBigTransactions = 1; }else if( strcmp(z,"cachesize")==0 ){ ARGC_VALUE_CHECK(1); cacheSize = integerValue(argv[++i]); }else if( strcmp(z,"exclusive")==0 ){ doExclusive = 1; }else if( strcmp(z,"checkpoint")==0 ){ g.doCheckpoint = 1; }else if( strcmp(z,"explain")==0 ){ g.bSqlOnly = 1; g.bExplain = 1; }else if( strcmp(z,"heap")==0 ){ ARGC_VALUE_CHECK(2); |
︙ | ︙ | |||
2393 2394 2395 2396 2397 2398 2399 | #endif }else if( strcmp(z,"vfs")==0 ){ ARGC_VALUE_CHECK(1); zVfs = argv[++i]; }else if( strcmp(z,"reserve")==0 ){ ARGC_VALUE_CHECK(1); g.nReserve = atoi(argv[++i]); | < < | 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 | #endif }else if( strcmp(z,"vfs")==0 ){ ARGC_VALUE_CHECK(1); zVfs = argv[++i]; }else if( strcmp(z,"reserve")==0 ){ ARGC_VALUE_CHECK(1); g.nReserve = atoi(argv[++i]); }else if( strcmp(z,"without-rowid")==0 ){ if( strstr(g.zWR,"WITHOUT")!=0 ){ /* no-op */ }else if( strstr(g.zWR,"STRICT")!=0 ){ g.zWR = "WITHOUT ROWID,STRICT"; }else{ g.zWR = "WITHOUT ROWID"; |
︙ | ︙ | |||
2478 2479 2480 2481 2482 2483 2484 | rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); } #endif if( g.nReserve>0 ){ sqlite3_file_control(g.db, 0, SQLITE_FCNTL_RESERVE_BYTES, &g.nReserve); } | < < < | 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 | rc = sqlite3_db_config(g.db, SQLITE_DBCONFIG_LOOKASIDE,pLook,szLook,nLook); if( rc ) fatal_error("lookaside configuration failed: %d\n", rc); } #endif if( g.nReserve>0 ){ sqlite3_file_control(g.db, 0, SQLITE_FCNTL_RESERVE_BYTES, &g.nReserve); } /* Set database connection options */ sqlite3_create_function(g.db, "random", 0, SQLITE_UTF8, 0, randomFunc, 0, 0); #ifndef SQLITE_OMIT_DEPRECATED if( doTrace ) sqlite3_trace(g.db, traceCallback, 0); #endif if( memDb>0 ){ |
︙ | ︙ | |||
2511 2512 2513 2514 2515 2516 2517 | } if( pageSize ){ speedtest1_exec("PRAGMA page_size=%d", pageSize); } if( cacheSize ){ speedtest1_exec("PRAGMA cache_size=%d", cacheSize); } | < | < < < | 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 | } if( pageSize ){ speedtest1_exec("PRAGMA page_size=%d", pageSize); } if( cacheSize ){ speedtest1_exec("PRAGMA cache_size=%d", cacheSize); } if( noSync ) speedtest1_exec("PRAGMA synchronous=OFF"); if( doExclusive ){ speedtest1_exec("PRAGMA locking_mode=EXCLUSIVE"); } if( zJMode ){ speedtest1_exec("PRAGMA journal_mode=%s", zJMode); } |
︙ | ︙ |
Changes to test/subtype1.test.
︙ | ︙ | |||
49 50 51 52 53 54 55 | do_execsql_test subtype1-230 { WITH t4(a) AS MATERIALIZED (SELECT json(1)) SELECT subtype(a) FROM t4; } {0} do_execsql_test subtype1-231 { WITH t4(a) AS NOT MATERIALIZED (SELECT json(1)) SELECT subtype(a) FROM t4; } {0} | < < | < < < < < < < < < < < < < < < < | 49 50 51 52 53 54 55 56 57 58 59 | do_execsql_test subtype1-230 { WITH t4(a) AS MATERIALIZED (SELECT json(1)) SELECT subtype(a) FROM t4; } {0} do_execsql_test subtype1-231 { WITH t4(a) AS NOT MATERIALIZED (SELECT json(1)) SELECT subtype(a) FROM t4; } {0} finish_test |
Changes to test/tabfunc01.test.
︙ | ︙ | |||
57 58 59 60 61 62 63 | } {1 {too many arguments on generate_series() - max 3}} do_execsql_test tabfunc01-1.8 { SELECT * FROM generate_series(0,32,5) ORDER BY rowid DESC; } {30 25 20 15 10 5 0} do_execsql_test tabfunc01-1.9 { SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC; | | | 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 | } {1 {too many arguments on generate_series() - max 3}} do_execsql_test tabfunc01-1.8 { SELECT * FROM generate_series(0,32,5) ORDER BY rowid DESC; } {30 25 20 15 10 5 0} do_execsql_test tabfunc01-1.9 { SELECT rowid, * FROM generate_series(0,32,5) ORDER BY value DESC; } {1 30 2 25 3 20 4 15 5 10 6 5 7 0} do_execsql_test tabfunc01-1.10 { SELECT rowid, * FROM generate_series(0,32,5) ORDER BY +value DESC; } {7 30 6 25 5 20 4 15 3 10 2 5 1 0} do_execsql_test tabfunc01-1.20 { CREATE VIEW v1(a,b) AS VALUES(1,2),(3,4); SELECT * FROM v1; |
︙ | ︙ | |||
266 267 268 269 270 271 272 | SELECT aa.value, bb.value, '|' FROM carray(inttoptr($PTR4),5,'double') AS aa JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid; } } {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |} # ticket https://www.sqlite.org/src/info/2ae0c599b735d59e | < | 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | SELECT aa.value, bb.value, '|' FROM carray(inttoptr($PTR4),5,'double') AS aa JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid; } } {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |} # ticket https://www.sqlite.org/src/info/2ae0c599b735d59e do_test tabfunc01-751 { db eval { SELECT aa.value, bb.value, '|' FROM carray(inttoptr($PTR4),5,'double') AS aa LEFT JOIN carray(inttoptr($PTR5),5,'char*') AS bb ON aa.rowid=bb.rowid; } } {5.0 x5 | 7.0 x7 | 13.0 x13 | 17.0 x17 | 23.0 x23 |} |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
945 946 947 948 949 950 951 | } proc normalize_list {L} { set L2 [list] foreach l $L {lappend L2 $l} set L2 } | < < < < < < < < < < < < < < < < < < < < < < < | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 | } proc normalize_list {L} { set L2 [list] foreach l $L {lappend L2 $l} set L2 } # Either: # # do_execsql_test TESTNAME SQL ?RES? # do_execsql_test -db DB TESTNAME SQL ?RES? # proc do_execsql_test {args} { |
︙ | ︙ |
Changes to test/testrunner.tcl.
︙ | ︙ | |||
20 21 22 23 24 25 26 | $a0 PERMUTATION FILE $a0 njob ?NJOB? $a0 status where SWITCHES are: --jobs NUMBER-OF-JOBS --fuzztest | < | 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | $a0 PERMUTATION FILE $a0 njob ?NJOB? $a0 status where SWITCHES are: --jobs NUMBER-OF-JOBS --fuzztest Interesting values for PERMUTATION are: veryquick - a fast subset of the tcl test scripts. This is the default. full - all tcl test scripts. all - all tcl test scripts, plus a subset of test scripts rerun with various permutations. |
︙ | ︙ | |||
67 68 69 70 71 72 73 | # Try to estimate a the number of processes to use. # # Command [guess_number_of_cores] attempts to glean the number of logical # cores. Command [default_njob] returns the default value for the --jobs # switch. # proc guess_number_of_cores {} { | < | | | | | | | | | | | < < < < | < | < | 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 | # Try to estimate a the number of processes to use. # # Command [guess_number_of_cores] attempts to glean the number of logical # cores. Command [default_njob] returns the default value for the --jobs # switch. # proc guess_number_of_cores {} { set ret 4 if {$::tcl_platform(os)=="Darwin"} { set cmd "sysctl -n hw.logicalcpu" } else { set cmd "nproc" } catch { set fd [open "|$cmd" r] set ret [gets $fd] close $fd set ret [expr $ret] } return $ret } proc default_njob {} { set nCore [guess_number_of_cores] set nHelper [expr int($nCore*0.75)] expr $nHelper>0 ? $nHelper : 1 } #------------------------------------------------------------------------- #------------------------------------------------------------------------- # Setup various default values in the global TRG() array. # set TRG(dbname) [file normalize testrunner.db] set TRG(logname) [file normalize testrunner.log] set TRG(build.logname) [file normalize testrunner_build.log] set TRG(info_script) [file normalize [info script]] set TRG(timeout) 10000 ;# Default busy-timeout for testrunner.db set TRG(nJob) [default_njob] ;# Default number of helper processes set TRG(patternlist) [list] set TRG(cmdline) $argv set TRG(reporttime) 2000 set TRG(fuzztest) 0 ;# is the fuzztest option present. switch -nocase -glob -- $tcl_platform(os) { *darwin* { set TRG(platform) osx set TRG(make) make.sh set TRG(makecmd) "bash make.sh" } |
︙ | ︙ | |||
348 349 350 351 352 353 354 | if {[string range $a 0 0]=="-"} { if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} { incr ii set TRG(nJob) [lindex $argv $ii] if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --fuzztest]) || $a=="-f"} { set TRG(fuzztest) 1 | < < < < | 340 341 342 343 344 345 346 347 348 349 350 351 352 353 | if {[string range $a 0 0]=="-"} { if {($n>2 && [string match "$a*" --jobs]) || $a=="-j"} { incr ii set TRG(nJob) [lindex $argv $ii] if {$isLast} { usage } } elseif {($n>2 && [string match "$a*" --fuzztest]) || $a=="-f"} { set TRG(fuzztest) 1 } else { usage } } else { lappend TRG(patternlist) [string map {% *} $a] } } |
︙ | ︙ | |||
581 582 583 584 585 586 587 | # set res #} proc make_new_testset {} { global TRG set tests [testset_patternlist $TRG(patternlist)] | < < < < < < | 569 570 571 572 573 574 575 576 577 578 579 580 581 582 | # set res #} proc make_new_testset {} { global TRG set tests [testset_patternlist $TRG(patternlist)] r_write_db { trdb eval $TRG(schema) set nJob $TRG(nJob) set cmdline $TRG(cmdline) set tm [clock_milliseconds] trdb eval { REPLACE INTO config VALUES('njob', $nJob ); } |
︙ | ︙ | |||
714 715 716 717 718 719 720 | if {$c=="build"} { set testdir [file dirname $TRG(info_script)] set srcdir [file dirname $testdir] set builddir [build_to_dirname $b] create_or_clear_dir $builddir | < < < | | | | | < | | | 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 | if {$c=="build"} { set testdir [file dirname $TRG(info_script)] set srcdir [file dirname $testdir] set builddir [build_to_dirname $b] create_or_clear_dir $builddir set cmd [info nameofexec] lappend cmd [file join $testdir releasetest_data.tcl] lappend cmd trscript if {$TRG(platform)=="win"} { lappend cmd -msvc } lappend cmd $b $srcdir set script [exec {*}$cmd] set fd [open [file join $builddir $TRG(make)] w] puts $fd $script close $fd puts "Launching build \"$b\" in directory $builddir..." set target coretestprogs if {$b=="User-Auth"} { set target testfixture } |
︙ | ︙ | |||
880 881 882 883 884 885 886 | puts "Test log is $TRG(logname)" } sqlite3 trdb $TRG(dbname) trdb timeout $TRG(timeout) set tm [lindex [time { make_new_testset }] 0] | < < < | 858 859 860 861 862 863 864 865 866 867 868 | puts "Test log is $TRG(logname)" } sqlite3 trdb $TRG(dbname) trdb timeout $TRG(timeout) set tm [lindex [time { make_new_testset }] 0] puts "built testset in [expr $tm/1000]ms.." run_testset trdb close #puts [pwd] |
Changes to test/tkt-99378177930f87bd.test.
︙ | ︙ | |||
172 173 174 175 176 177 178 | (SELECT avg( (SELECT sum((SELECT 1 FROM t1 NATURAL RIGHT JOIN t1 WHERE a=a)))) AS xyz ) AND a==2 ); } {1 2} | < < < < < < < < < < < < < < < < < | 172 173 174 175 176 177 178 179 | (SELECT avg( (SELECT sum((SELECT 1 FROM t1 NATURAL RIGHT JOIN t1 WHERE a=a)))) AS xyz ) AND a==2 ); } {1 2} finish_test |
Changes to test/update.test.
︙ | ︙ | |||
728 729 730 731 732 733 734 | do_catchsql_test update-20.20 { UPDATE t1 SET a=0; } {1 {constraint failed}} do_execsql_test update-20.30 { PRAGMA integrity_check; } {ok} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 728 729 730 731 732 733 734 735 | do_catchsql_test update-20.20 { UPDATE t1 SET a=0; } {1 {constraint failed}} do_execsql_test update-20.30 { PRAGMA integrity_check; } {ok} finish_test |
Changes to test/vt02.c.
︙ | ︙ | |||
173 174 175 176 177 178 179 180 181 182 183 184 185 186 | #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <stdlib.h> #include <string.h> #include <assert.h> #endif /* Forward declarations */ typedef struct vt02_vtab vt02_vtab; typedef struct vt02_cur vt02_cur; /* ** The complete virtual table */ | > > | 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 | #include "sqlite3ext.h" SQLITE_EXTENSION_INIT1 #include <stdlib.h> #include <string.h> #include <assert.h> #endif #ifndef SQLITE_OMIT_VIRTUALTABLE /* Forward declarations */ typedef struct vt02_vtab vt02_vtab; typedef struct vt02_cur vt02_cur; /* ** The complete virtual table */ |
︙ | ︙ | |||
375 376 377 378 379 380 381 | e = idxNum - 6; assert( e<=argc-2 ); pCur->i = 0; for(m=1000, i=0; i<=e; i++, m /= 10){ sqlite3_int64 v; pVal = 0; if( sqlite3_vtab_in_first(0, &pVal)!=SQLITE_MISUSE | | | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | e = idxNum - 6; assert( e<=argc-2 ); pCur->i = 0; for(m=1000, i=0; i<=e; i++, m /= 10){ sqlite3_int64 v; pVal = 0; if( sqlite3_vtab_in_first(0, &pVal)!=SQLITE_MISUSE || sqlite3_vtab_in_first(argv[iArg], &pVal)!=SQLITE_MISUSE ){ vt02ErrMsg(pCursor->pVtab, "unexpected success from sqlite3_vtab_in_first()"); return SQLITE_ERROR; } v = sqlite3_value_int64(argv[iArg++]); if( v<0 ) v = 0; |
︙ | ︙ | |||
414 415 416 417 418 419 420 | return rc; } }else{ goto vt02_bad_idxnum; } if( bUseOffset ){ int nSkip = sqlite3_value_int(argv[iArg]); | | | 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 | return rc; } }else{ goto vt02_bad_idxnum; } if( bUseOffset ){ int nSkip = sqlite3_value_int(argv[iArg]); while( nSkip-- > 0 ) vt02Next(pCursor); } return SQLITE_OK; vt02_bad_idxnum: vt02ErrMsg(pCursor->pVtab, "invalid idxNum for vt02: %d", iOrigIdxNum); return SQLITE_ERROR; } |
︙ | ︙ | |||
995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 | "d INT NOT NULL, flags INT HIDDEN, logtab TEXT HIDDEN, " "PRIMARY KEY(a,b,c,d));"; sqlite3_create_module(db, "vt02", &vt02Module, 0); sqlite3_create_module(db, "vt02pkx", &vt02Module, (void*)zPkXSchema); sqlite3_create_module(db, "vt02pkabcd", &vt02Module, (void*)zPkABCDSchema); } #ifdef TH3_VERSION static void vt02_init(th3state *p, int iDb, char *zArg){ vt02CoreInit(th3dbPointer(p, iDb)); } #else #ifdef _WIN32 __declspec(dllexport) | > > > > | 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 | "d INT NOT NULL, flags INT HIDDEN, logtab TEXT HIDDEN, " "PRIMARY KEY(a,b,c,d));"; sqlite3_create_module(db, "vt02", &vt02Module, 0); sqlite3_create_module(db, "vt02pkx", &vt02Module, (void*)zPkXSchema); sqlite3_create_module(db, "vt02pkabcd", &vt02Module, (void*)zPkABCDSchema); } #else # define vt02CoreInit(db) #endif /* ifndef SQLITE_OMIT_VIRTUALTABLE */ #ifdef TH3_VERSION static void vt02_init(th3state *p, int iDb, char *zArg){ vt02CoreInit(th3dbPointer(p, iDb)); } #else #ifdef _WIN32 __declspec(dllexport) |
︙ | ︙ |
Changes to test/whereL.test.
︙ | ︙ | |||
185 186 187 188 189 190 191 | FROM tableB WHERE RunYearMonth = 202004 ) AS B ON A.ID = B.ID AND A.RunYearMonth = B.RunYearMonth; } {4 202004 4 202004 5 202004 5 202004} | < < < < < < < < < < < < < < < < < < < | 185 186 187 188 189 190 191 192 193 | FROM tableB WHERE RunYearMonth = 202004 ) AS B ON A.ID = B.ID AND A.RunYearMonth = B.RunYearMonth; } {4 202004 4 202004 5 202004 5 202004} finish_test |
Changes to test/window1.test.
︙ | ︙ | |||
2206 2207 2208 2209 2210 2211 2212 | do_execsql_test 72.1 { CREATE TABLE dual(dummy); INSERT INTO dual VALUES('X'); CREATE VIEW v1(x,y) AS SELECT RANK() OVER (PARTITION BY 0), SUM(0) FROM dual; SELECT * FROM v1 WHERE true; } {1 0} | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2206 2207 2208 2209 2210 2211 2212 2213 | do_execsql_test 72.1 { CREATE TABLE dual(dummy); INSERT INTO dual VALUES('X'); CREATE VIEW v1(x,y) AS SELECT RANK() OVER (PARTITION BY 0), SUM(0) FROM dual; SELECT * FROM v1 WHERE true; } {1 0} finish_test |
Changes to test/with1.test.
︙ | ︙ | |||
1120 1121 1122 1123 1124 1125 1126 | #------------------------------------------------------------------------- reset_db do_execsql_test 24.1 { CREATE TABLE t1(a, b, c); CREATE VIEW v1 AS SELECT max(a), min(b) FROM t1 GROUP BY c; } do_test 24.1 { | | | 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 | #------------------------------------------------------------------------- reset_db do_execsql_test 24.1 { CREATE TABLE t1(a, b, c); CREATE VIEW v1 AS SELECT max(a), min(b) FROM t1 GROUP BY c; } do_test 24.1 { set program [db eval {EXPLAIN SELECT 1 FROM v1,v1,v1}] expr [lsearch $program OpenDup]>0 } {1} do_execsql_test 24.2 { ATTACH "" AS aux; CREATE VIEW aux.v3 AS VALUES(1); CREATE VIEW main.v3 AS VALUES(3); |
︙ | ︙ |
Changes to test/with3.test.
︙ | ︙ | |||
105 106 107 108 109 110 111 | QUERY PLAN |--CO-ROUTINE cnt | |--SETUP | | `--SCAN CONSTANT ROW | `--RECURSIVE STEP | `--SCAN cnt |--SCAN y1 | < | 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | QUERY PLAN |--CO-ROUTINE cnt | |--SETUP | | `--SCAN CONSTANT ROW | `--RECURSIVE STEP | `--SCAN cnt |--SCAN y1 `--SEARCH cnt USING AUTOMATIC COVERING INDEX (i=?) }] } do_execsql_test 3.2.1 { CREATE TABLE w1(pk INTEGER PRIMARY KEY, x INTEGER); CREATE TABLE w2(pk INTEGER PRIMARY KEY); |
︙ | ︙ |
Changes to test/with6.test.
︙ | ︙ | |||
359 360 361 362 363 364 365 | | | |--SCAN i | | |--SEARCH raw USING COVERING INDEX sqlite_autoindex_raw_1 (country=? AND date>?) | | `--USE TEMP B-TREE FOR ORDER BY | |--SCAN src | |--SEARCH raw USING INDEX sqlite_autoindex_raw_1 (country=? AND date>? AND date<?) | `--USE TEMP B-TREE FOR GROUP BY |--SCAN sums | < < < < | 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | | | |--SCAN i | | |--SEARCH raw USING COVERING INDEX sqlite_autoindex_raw_1 (country=? AND date>?) | | `--USE TEMP B-TREE FOR ORDER BY | |--SCAN src | |--SEARCH raw USING INDEX sqlite_autoindex_raw_1 (country=? AND date>? AND date<?) | `--USE TEMP B-TREE FOR GROUP BY |--SCAN sums |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?) |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?) |--SEARCH sums USING AUTOMATIC COVERING INDEX (country=? AND date=?) `--SEARCH i USING AUTOMATIC COVERING INDEX (country=?) } finish_test |
Changes to test/zipfile.test.
︙ | ︙ | |||
858 859 860 861 862 863 864 | # https://sqlite.org/forum/forumpost/d1c96a9032e564f8 # Call to fopen() with a NULL filename. # do_catchsql_test 18.1 { SELECT * FROM zipfile(NULL); } {1 {cannot open file: }} | < < < < < < < < < < < < < < < < < < < < < | 858 859 860 861 862 863 864 865 866 | # https://sqlite.org/forum/forumpost/d1c96a9032e564f8 # Call to fopen() with a NULL filename. # do_catchsql_test 18.1 { SELECT * FROM zipfile(NULL); } {1 {cannot open file: }} finish_test |
Changes to tool/mkctimec.tcl.
︙ | ︙ | |||
94 95 96 97 98 99 100 101 102 103 104 105 106 107 | } # All Boolean compile time options which default to 0 or empty. # set boolean_defnil_options { SQLITE_32BIT_ROWID SQLITE_4_BYTE_ALIGNED_MALLOC SQLITE_ALLOW_URI_AUTHORITY SQLITE_BUG_COMPATIBLE_20160819 SQLITE_CASE_SENSITIVE_LIKE SQLITE_CHECK_PAGES SQLITE_COVERAGE_TEST SQLITE_DEBUG SQLITE_DEFAULT_AUTOMATIC_INDEX | > | 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | } # All Boolean compile time options which default to 0 or empty. # set boolean_defnil_options { SQLITE_32BIT_ROWID SQLITE_4_BYTE_ALIGNED_MALLOC SQLITE_64BIT_STATS SQLITE_ALLOW_URI_AUTHORITY SQLITE_BUG_COMPATIBLE_20160819 SQLITE_CASE_SENSITIVE_LIKE SQLITE_CHECK_PAGES SQLITE_COVERAGE_TEST SQLITE_DEBUG SQLITE_DEFAULT_AUTOMATIC_INDEX |
︙ | ︙ |
Changes to tool/mkkeywordhash.c.
︙ | ︙ | |||
592 593 594 595 596 597 598 | } } printf("%s};\n", j==0 ? "" : "\n"); printf("/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0\n"); printf("** then the i-th keyword has no more hash collisions. Otherwise,\n"); printf("** the next keyword with the same hash is aKWHash[i]-1. */\n"); | | | | | | 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 | } } printf("%s};\n", j==0 ? "" : "\n"); printf("/* aKWNext[] forms the hash collision chain. If aKWHash[i]==0\n"); printf("** then the i-th keyword has no more hash collisions. Otherwise,\n"); printf("** the next keyword with the same hash is aKWHash[i]-1. */\n"); printf("static const unsigned char aKWNext[%d] = {\n", nKeyword); for(i=j=0; i<nKeyword; i++){ if( j==0 ) printf(" "); printf(" %3d,", aKeywordTable[i].iNext); j++; if( j>12 ){ printf("\n"); j = 0; } } printf("%s};\n", j==0 ? "" : "\n"); printf("/* aKWLen[i] is the length (in bytes) of the i-th keyword */\n"); printf("static const unsigned char aKWLen[%d] = {\n", nKeyword); for(i=j=0; i<nKeyword; i++){ if( j==0 ) printf(" "); printf(" %3d,", aKeywordTable[i].len+aKeywordTable[i].prefix); j++; if( j>12 ){ printf("\n"); j = 0; } } printf("%s};\n", j==0 ? "" : "\n"); printf("/* aKWOffset[i] is the index into zKWText[] of the start of\n"); printf("** the text for the i-th keyword. */\n"); printf("static const unsigned short int aKWOffset[%d] = {\n", nKeyword); for(i=j=0; i<nKeyword; i++){ if( j==0 ) printf(" "); printf(" %3d,", aKeywordTable[i].offset); j++; if( j>12 ){ printf("\n"); j = 0; } } printf("%s};\n", j==0 ? "" : "\n"); printf("/* aKWCode[i] is the parser symbol code for the i-th keyword */\n"); printf("static const unsigned char aKWCode[%d] = {\n", nKeyword); for(i=j=0; i<nKeyword; i++){ char *zToken = aKeywordTable[i].zTokenType; if( j==0 ) printf(" "); printf("%s,%*s", zToken, (int)(14-strlen(zToken)), ""); j++; if( j>=5 ){ printf("\n"); |
︙ | ︙ | |||
665 666 667 668 669 670 671 | printf("static int keywordCode(const char *z, int n, int *pType){\n"); printf(" int i, j;\n"); printf(" const char *zKW;\n"); printf(" if( n>=2 ){\n"); printf(" i = ((charMap(z[0])*%d) %c", HASH_C0, HASH_CC); printf(" (charMap(z[n-1])*%d) %c", HASH_C1, HASH_CC); printf(" n*%d) %% %d;\n", HASH_C2, bestSize); | | | < | 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 | printf("static int keywordCode(const char *z, int n, int *pType){\n"); printf(" int i, j;\n"); printf(" const char *zKW;\n"); printf(" if( n>=2 ){\n"); printf(" i = ((charMap(z[0])*%d) %c", HASH_C0, HASH_CC); printf(" (charMap(z[n-1])*%d) %c", HASH_C1, HASH_CC); printf(" n*%d) %% %d;\n", HASH_C2, bestSize); printf(" for(i=((int)aKWHash[i])-1; i>=0; i=((int)aKWNext[i])-1){\n"); printf(" if( aKWLen[i]!=n ) continue;\n"); printf(" zKW = &zKWText[aKWOffset[i]];\n"); printf("#ifdef SQLITE_ASCII\n"); printf(" if( (z[0]&~0x20)!=zKW[0] ) continue;\n"); printf(" if( (z[1]&~0x20)!=zKW[1] ) continue;\n"); printf(" j = 2;\n"); printf(" while( j<n && (z[j]&~0x20)==zKW[j] ){ j++; }\n"); printf("#endif\n"); printf("#ifdef SQLITE_EBCDIC\n"); printf(" if( toupper(z[0])!=zKW[0] ) continue;\n"); printf(" if( toupper(z[1])!=zKW[1] ) continue;\n"); printf(" j = 2;\n"); printf(" while( j<n && toupper(z[j])==zKW[j] ){ j++; }\n"); printf("#endif\n"); printf(" if( j<n ) continue;\n"); for(i=0; i<nKeyword; i++){ printf(" testcase( i==%d ); /* %s */\n", i, aKeywordTable[i].zOrigName); } printf(" *pType = aKWCode[i];\n"); printf(" break;\n"); printf(" }\n"); printf(" }\n"); printf(" return n;\n"); printf("}\n"); printf("int sqlite3KeywordCode(const unsigned char *z, int n){\n"); printf(" int id = TK_ID;\n"); printf(" keywordCode((char*)z, n, &id);\n"); printf(" return id;\n"); printf("}\n"); printf("#define SQLITE_N_KEYWORD %d\n", nKeyword); printf("int sqlite3_keyword_name(int i,const char **pzName,int *pnName){\n"); printf(" if( i<0 || i>=SQLITE_N_KEYWORD ) return SQLITE_ERROR;\n"); printf(" *pzName = zKWText + aKWOffset[i];\n"); printf(" *pnName = aKWLen[i];\n"); printf(" return SQLITE_OK;\n"); printf("}\n"); printf("int sqlite3_keyword_count(void){ return SQLITE_N_KEYWORD; }\n"); printf("int sqlite3_keyword_check(const char *zName, int nName){\n"); printf(" return TK_ID!=sqlite3KeywordCode((const u8*)zName, nName);\n"); printf("}\n"); return 0; } |
Changes to tool/showwal.c.
︙ | ︙ | |||
229 230 231 232 233 234 235 | unsigned int s0, s1; iStart = 32 + (i64)(iFrame-1)*(pagesize+24); aData = getContent(iStart, 24); extendCksum(pCksum, aData, 8, 0); extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0); s0 = getInt32(aData+16); s1 = getInt32(aData+20); | | | > < < < < < < | 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 | unsigned int s0, s1; iStart = 32 + (i64)(iFrame-1)*(pagesize+24); aData = getContent(iStart, 24); extendCksum(pCksum, aData, 8, 0); extendCksum(pCksum, getContent(iStart+24, pagesize), pagesize, 0); s0 = getInt32(aData+16); s1 = getInt32(aData+20); fprintf(stdout, "Frame %4d: %6d %6d 0x%08x,%08x 0x%08x,%08x %s\n", iFrame, getInt32(aData), getInt32(aData+4), getInt32(aData+8), getInt32(aData+12), s0, s1, (s0==pCksum->s0 && s1==pCksum->s1) ? "" : "cksum-fail" ); /* Reset the checksum so that a single frame checksum failure will not ** cause all subsequent frames to also show a failure. */ pCksum->s0 = s0; pCksum->s1 = s1; free(aData); } |
︙ | ︙ |
Changes to tool/speed-check.sh.
︙ | ︙ | |||
154 155 156 157 158 159 160 | ;; --cte) SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte" ;; --fp) SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp" ;; | < < < | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | ;; --cte) SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset cte" ;; --fp) SPEEDTEST_OPTS="$SPEEDTEST_OPTS --testset fp" ;; -*) CC_OPTS="$CC_OPTS $1" ;; *) BASELINE=$1 ;; esac |
︙ | ︙ |